Fix Git src refspec main does not match any and rejected pushes
Separate an unborn branch, wrong local branch, missing ref, wrong remote, and non-fast-forward protection before choosing an explicit push, fetch/rebase, or reviewed force-with-lease.
Publish the intended commits to the intended remote branch without losing remote history or pushing secrets and generated files.
- Git 2.43+
- Repository Work from the intended repository root with no unknown in-progress merge or rebase.
- Remote ownership Know the intended hosting project and target branch policy.
- Secret review Scan staged commits for credentials or private files before publishing.
OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.
Full guide
What you will build
- A repeatable Git incident record that starts with the literal `src refspec main does not match any` or `failed to push some refs` symptom and preserves the first useful failure instead of hiding it with an early restart or broad permission change.
- A layer-by-layer decision path from client context through configuration and runtime evidence to one narrowly scoped remediation, followed by positive and negative verification.
- A reusable evidence bundle containing commands, concrete example output, timestamps, identities, effective configuration, and stop conditions that another operator can review without access to the original terminal.
- You can identify which boundary failed, explain why competing hypotheses were rejected, and state what changed before declaring the incident resolved.
- The repaired path succeeds under the intended identity while an unauthorized or incorrect path still fails, proving that the fix did not simply remove a security control.
- The final evidence distinguishes a transient recovery from a durable repair by checking logs, counters, configuration provenance, and the original user-visible operation.
Architecture
How the parts fit together
Git troubleshooting is treated as an evidence pipeline rather than a list of guesses. The operator captures the symptom, resolves client and target context, inspects the first authoritative server-side failure, tests the smallest cause boundary, applies one reviewed change, and repeats the same observation path. This keeps a secondary error from replacing the primary cause and makes rollback possible.
- Copy the literal error and the command that produced it before retrying, restarting, pruning, resetting, or editing anything.
- Resolve the selected identity, configuration, target, and current runtime state so later commands inspect the same path the user exercised.
- Read the nearest authoritative log or effective configuration and align timestamps across the client and server evidence.
- Test one hypothesis with a read-only command; if evidence disagrees, return to the previous layer instead of stacking speculative changes.
- Back up the affected configuration or reference, apply the narrow repair, validate syntax, and reload only the component that owns the decision.
- Repeat the original action plus a negative control, record the outcome, and keep rollback material until the observation window is complete.
Assumptions
- The local `.git` directory belongs to the intended project.
- Remote history must be preserved unless an explicit rewrite is approved.
- Authentication is handled separately from ref selection and history topology.
- Clocks are close enough that client and server timestamps can be correlated. If they are not, record the offset before comparing logs.
- The operator has a recovery path that does not depend on the component being changed, such as console access, a second session, or a preserved remote reference.
- Commands are first run in the affected environment with placeholders reviewed. OneLiners never executes them and does not know local policy, tenancy, or maintenance constraints.
Key concepts
- Ref
- A named pointer such as refs/heads/main; a source ref must exist locally before Git can push it.
- Unborn branch
- A branch name selected before the repository has its first commit, so no branch ref exists yet.
- Refspec
- The source:destination mapping that tells push which local ref updates which remote ref.
- Non-fast-forward
- A proposed update that would discard remote-reachable commits rather than moving the branch tip forward.
- force-with-lease
- A guarded history rewrite that proceeds only if the remote ref still matches the expected observed value.
Fill these once. Every matching command and configuration block updates immediately; values stay in this page only.
Security and production boundaries
- Review commits for secrets, private keys, dumps, and generated credentials before the first successful push.
- Branch protection and non-fast-forward rejection are safety controls, not obstacles to disable during diagnosis.
- Do not paste private keys, tokens, complete environment dumps, authorization headers, or unredacted customer data into tickets or external analysis tools.
- A successful operation after disabling authentication, trust, host verification, sandboxing, or least privilege is a security regression, not a valid repair.
- Prefer effective configuration and narrow identity tests over recursive ownership changes, mode 777, global trust bypasses, or force options copied from unrelated incidents.
Stop before continuing if
- Stop if the remote project or authenticated account is unexpected.
- Stop before rewriting any commit already consumed by others without explicit approval.
- Stop if the target, account, environment, repository, or service instance cannot be identified unambiguously.
- Stop before a destructive cleanup, force update, broad permission change, or production reload when backup and recovery evidence is missing.
- Stop if the proposed action would conceal the first error or remove logs, failed objects, repository references, or configuration needed for diagnosis.
instruction
Freeze the symptom and define the incident boundary
Before changing Git, preserve the literal `src refspec main does not match any` or `failed to push some refs` message, the exact action that produced it, the affected identity, target, UTC time, and expected result. Decide which production boundary is in scope and name the independent recovery path you will keep available.
Why this step matters
A retry, restart, cleanup, permission change, or configuration edit can replace the primary failure with a secondary one. A fixed starting record lets every later check answer a specific hypothesis.
What to understand
Record whether the problem affects one user or workload, one target, one host, or every comparable path; this determines whether to begin at the client, transport, or service boundary.
Write down the expected successful behavior in observable terms such as an exit status, HTTP response, remote object ID, authenticated principal, or stable service state.
Keep console access, a second session, an earlier configuration, or a recoverable reference independent of the component being diagnosed.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Incident scope Tool: Git Observed: `src refspec main does not match any` or `failed to push some refs` Affected target: production-app-01 Observed at: 2026-08-17T14:02:11Z Expected: the reviewed operation completes without weakening an access or safety control Recovery path: console session and last known-good configuration retained
Security notes
- Redact secrets and customer data, but retain error text, timestamps, object IDs, modes, owners, and target names needed to reproduce the decision.
Alternatives
- When direct production inspection is restricted, reproduce the same version and configuration boundary in an isolated environment and mark which evidence is illustrative.
Stop conditions
- Stop before any mutation if the target, identity, affected environment, expected result, or recovery path is still ambiguous.
command
Prove repository, branch, HEAD, and operation state
Capture the repository root, current branch, HEAD existence, status, and any merge/rebase state before changing refs.
Why this step matters
The refspec error often means the typed source branch does not exist because there is no commit or the local branch has another name.
What to understand
`git status --branch` exposes an unborn branch and in-progress operations without modifying the index.
Do not rename a branch until repository conventions and remote default branch are known.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
symbolic-ref --short -q HEAD- Prints the selected local branch name even before the first commit.
rev-parse --verify HEAD- Proves whether the repository has a commit object at HEAD.
git rev-parse --show-toplevel && git status --short --branch && git symbolic-ref --short -q HEAD || true && git rev-parse --verify HEAD 2>/dev/null || echo UNBORN_HEAD/srv/app ## No commits yet on master master UNBORN_HEAD
Checkpoint: Checkpoint: Prove repository, branch, HEAD, and operation state
git rev-parse --show-toplevel && git status --short --branch && git symbolic-ref --short -q HEAD || true && git rev-parse --verify HEAD 2>/dev/null || echo UNBORN_HEADContinue whenThe repository root, current branch, commit existence, and clean/in-progress state are explicit.
Stop whenThe repository is wrong, a merge/rebase is unresolved, or unreviewed changes contain secrets.
If this step fails
fatal: not a git repository
Likely causeThe shell is outside the intended worktree or a parent `.git` boundary is missing.
pwdgit rev-parse --show-toplevel
ResolutionEnter the verified clone or restore repository metadata; do not initialize Git in an arbitrary directory.
Security notes
- Status can reveal sensitive filenames; redact them externally.
Alternatives
- Use `git worktree list` when multiple worktrees may contain the intended branch.
Stop conditions
- The repository is wrong, a merge/rebase is unresolved, or unreviewed changes contain secrets.
command
List local refs and recent commits
Inspect branches, tags, symbolic HEAD, and the recent graph to find the actual source commit intended for publication.
Why this step matters
A valid local commit may exist under master, a feature branch, tag, detached HEAD, or another worktree even when `main` does not.
What to understand
Choose the commit by content and provenance, not only by branch spelling.
Detached HEAD can be pushed explicitly, but first create a named branch so the work remains recoverable.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
show-ref --heads --tags- Lists exact local reference names and object IDs.
log --all --decorate --graph- Shows reachable commit topology across local refs.
git show-ref --heads --tags || true; git log --oneline --decorate --graph --all -n 20 || true8f19c2a refs/heads/master * 8f19c2a (HEAD -> master) Add health check * 9c41a6e Initial commit
Checkpoint: Checkpoint: List local refs and recent commits
git show-ref --heads --tags || true; git log --oneline --decorate --graph --all -n 20 || trueContinue whenThe intended source commit has a stable local branch/ref and reviewed history.
Stop whenThe intended commits are unreachable, unsigned when policy requires signatures, or contain unreviewed changes.
If this step fails
No refs or commits are printed.
Likely causeThe repository has no first commit.
git statusgit diff --cached --stat
ResolutionReview and create the first commit before pushing; an empty branch name alone cannot be published.
Security notes
- Inspect staged content and secret scanning results before creating or selecting the first commit.
Alternatives
- Create a recoverable branch with `git switch -c` from the reviewed detached commit.
Stop conditions
- The intended commits are unreachable, unsigned when policy requires signatures, or contain unreviewed changes.
command
Verify remote URL, default branch, and refs
Record the exact fetch/push URLs and query remote heads without modifying local history.
Why this step matters
A correct local branch pushed to the wrong fork, organization, protocol, or default branch is still a failed and potentially sensitive operation.
What to understand
`ls-remote --symref` reports the remote default branch without a fetch.
Fetch and push URLs can differ; automation may also rewrite URLs through Git configuration.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
remote get-url --all- Shows every configured URL after rewrite rules.
ls-remote --symref- Reads remote symbolic HEAD and refs without updating local refs.
Values stay on this page and are never sent or saved.
git remote -v && git remote get-url --all {{remote}} && git ls-remote --symref {{remote}} HEAD && git ls-remote --heads {{remote}}origin git@github.com:example/app.git (fetch) origin git@github.com:example/app.git (push) ref: refs/heads/main HEAD 4c71de2 refs/heads/main
Checkpoint: Checkpoint: Verify remote URL, default branch, and refs
git remote -v && git remote get-url --all {{remote}} && git ls-remote --symref {{remote}} HEAD && git ls-remote --heads {{remote}}Continue whenThe remote project, protocol, default branch, and target ref match the intended destination.
Stop whenThe remote belongs to another project/account or authentication unexpectedly targets another identity.
If this step fails
Permission denied (publickey).
Likely causeSSH authentication fails before Git can inspect refs.
ssh -T git@github.comgit remote get-url {{remote}}
ResolutionUse the dedicated SSH public-key tutorial; do not change branch history to solve authentication.
Security notes
- Do not embed access tokens in remote URLs or incident output.
Alternatives
- Use an approved HTTPS credential helper when SSH is not the organization standard.
Stop conditions
- The remote belongs to another project/account or authentication unexpectedly targets another identity.
command
Fetch safely and compare local with remote topology
Fetch remote refs without merging, then count and inspect commits unique to each side of the intended branch.
Why this step matters
A non-fast-forward rejection protects remote-only commits; fetching and comparing makes the divergence explicit before merge, rebase, or rewrite.
What to understand
The left count is remote-only and the right count is local-only for the shown range.
Do not use `pull` before deciding whether project policy expects merge, rebase, or a separate pull request.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
fetch --prune- Updates remote-tracking refs and removes stale ones without changing the current branch.
rev-list --left-right --count- Counts commits unique to remote and local sides.
log --left-right- Labels individual divergent commits for review.
Values stay on this page and are never sent or saved.
git fetch --prune {{remote}} && git rev-list --left-right --count {{remote}}/{{branch}}...HEAD && git log --oneline --left-right --graph {{remote}}/{{branch}}...HEAD -n 302 3 < 4c71de2 Remote hotfix < 913df20 Update deployment > 8f19c2a Add health check > 1a77f09 Refactor worker > c204ab1 Add tests
Checkpoint: Checkpoint: Fetch safely and compare local with remote topology
git fetch --prune {{remote}} && git rev-list --left-right --count {{remote}}/{{branch}}...HEAD && git log --oneline --left-right --graph {{remote}}/{{branch}}...HEAD -n 30Continue whenThe branch is identified as empty, ahead, behind, or diverged with every remote-only commit visible.
Stop whenRemote-only commits are unexpected, protected, or represent another release line.
If this step fails
fatal: ambiguous argument origin/main
Likely causeThe remote branch does not exist or uses another name.
git ls-remote --heads {{remote}}git branch -r
ResolutionSelect the actual target branch or create a new reviewed remote branch explicitly.
Security notes
- Fetching is read-only to the remote but may download private history; use the approved repository and workstation.
Alternatives
- Compare object IDs with hosting UI/API when local fetch is restricted.
Stop conditions
- Remote-only commits are unexpected, protected, or represent another release line.
decision
Choose explicit first push, rebase, merge, or guarded rewrite
Apply the project's history policy to the observed topology and keep a local backup ref before any rewrite.
Why this step matters
An explicit HEAD-to-full-destination refspec removes branch-name ambiguity, while a backup ref and reviewed integration preserve recoverability.
What to understand
For an unborn repository, create and review the first commit, then push HEAD explicitly to the approved remote branch.
For divergence, rebase only private local commits; merge or use a pull request when published history or policy requires it.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- Creates a local backup ref, may rewrite private local commits through rebase, and updates the reviewed remote branch when the push succeeds.
Syntax explained
branch backup/... HEAD- Creates a recoverable local pointer before history transformation.
rebase remote/branch- Replays local-only commits after the current remote tip; use only when policy permits.
push --set-upstream remote HEAD:refs/heads/branch- Pushes the exact current commit to an explicit remote branch and records tracking.
Values stay on this page and are never sent or saved.
git branch backup/before-push-$(date -u +%Y%m%dT%H%M%SZ) HEAD && git rebase {{remote}}/{{branch}} && git push --set-upstream {{remote}} HEAD:refs/heads/{{branch}}Successfully rebased and updated refs/heads/main. branch 'main' set up to track 'origin/main'. To github.com:example/app.git 4c71de2..b821f73 HEAD -> main
Checkpoint: Checkpoint: Choose explicit first push, rebase, merge, or guarded rewrite
git branch backup/before-push-$(date -u +%Y%m%dT%H%M%SZ) HEAD && git rebase {{remote}}/{{branch}} && git push --set-upstream {{remote}} HEAD:refs/heads/{{branch}}Continue whenThe intended commits extend the reviewed remote history and the explicit target branch updates successfully.
Stop whenRebase conflicts are unclear, remote-only commits must not be rewritten, or branch protection requires a pull request.
If this step fails
The push is rejected by branch protection.
Likely causeDirect updates, unsigned commits, required checks, or force pushes are prohibited.
git remote show {{remote}}git log --show-signature -1
ResolutionPush a feature branch and use the required review/check workflow; do not bypass protection.
Security notes
- Run secret and artifact review before the network-changing push.
Alternatives
- Push `HEAD:refs/heads/fix/refspec` and open a pull request instead of updating the protected branch directly.
Stop conditions
- Rebase conflicts are unclear, remote-only commits must not be rewritten, or branch protection requires a pull request.
command
Verify remote object identity and tracking
Compare local HEAD with the remote branch object ID, tracking status, and recent decorated graph after the push.
Why this step matters
A success message is less useful than proving the exact object now referenced remotely and that local tracking has no unexplained ahead/behind state.
What to understand
Object IDs must match for the expected direct update; a hosting merge queue may intentionally produce another commit and should be verified through its workflow.
Keep the backup ref until CI, deployment, and reviewer checks finish.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
rev-parse- Resolves local and remote-tracking refs to exact commit object IDs.
status --branch- Shows tracking and ahead/behind state after fetch.
Values stay on this page and are never sent or saved.
git fetch {{remote}} && printf 'local=%s\nremote=%s\n' "$(git rev-parse HEAD)" "$(git rev-parse {{remote}}/{{branch}})" && git status --short --branch && git log --oneline --decorate --graph -n 8local=b821f7386a1... remote=b821f7386a1... ## main...origin/main * b821f73 (HEAD -> main, origin/main) Add health check
Checkpoint: Checkpoint: Verify remote object identity and tracking
git fetch {{remote}} && printf 'local=%s\nremote=%s\n' "$(git rev-parse HEAD)" "$(git rev-parse {{remote}}/{{branch}})" && git status --short --branch && git log --oneline --decorate --graph -n 8Continue whenLocal HEAD and the intended remote-tracking branch point to the expected commit with clean tracking state.
Stop whenThe remote object differs unexpectedly or CI/protection reports another revision.
If this step fails
The remote changes again after verification.
Likely causeAnother writer, bot, merge queue, or force update advanced the branch.
git fetch {{remote}}git log --oneline --left-right {{remote}}/{{branch}}...HEAD
ResolutionRe-evaluate the new remote history; do not overwrite it with an old expected value.
Security notes
- Retain commit IDs and signatures as evidence without exposing private repository URLs publicly.
Alternatives
- Verify the exact commit in the hosting provider's protected-branch or deployment record.
Stop conditions
- The remote object differs unexpectedly or CI/protection reports another revision.
verification
Observe for recurrence and close with evidence
After the original Git operation succeeds, repeat the same read-only observation path used at the start. Watch the relevant logs, counters, identities, and target state for a bounded period, then record the proven cause, exact change, verification result, rollback point, and remaining uncertainty.
Why this step matters
A single successful retry may be a transient recovery. Repeating the original checks and retaining the rollback point distinguishes a durable repair from a restart-only improvement.
What to understand
Use the same client identity, target, path, and configuration selection as the original failure so the positive result is comparable.
Include one negative or unauthorized control where safe; this proves the repair did not work by removing authentication, trust, isolation, or branch protection.
Keep the evidence concise enough for another operator to reproduce, but include software versions and exact object or configuration references.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Observation window: 15 minutes Original operation: PASS Original signature recurrences: 0 Negative control: PASS Rollback point retained: yes Cause and repair recorded: yes Remaining uncertainty: none observed within the stated boundary
Checkpoint: Checkpoint: the repair remains valid
git fetch {{remote}} && printf 'local=%s\nremote=%s\n' "$(git rev-parse HEAD)" "$(git rev-parse {{remote}}/{{branch}})" && git status --short --branch && git log --oneline --decorate --graph -n 8Continue whenThe intended operation stays healthy, the original signature does not recur, and the negative control still enforces the expected boundary.
Stop whenThe result depends on an unexplained retry, disabled control, different target, or unrecorded manual state.
If this step fails
The error returns during the observation window.
Likely causeThe change treated a symptom, another instance still has the old state, or an automated process reverted or recreated the failing condition.
git rev-parse --show-toplevel && git status --short --branch && git symbolic-ref --short -q HEAD || true && git rev-parse --verify HEAD 2>/dev/null || echo UNBORN_HEADgit fetch {{remote}} && printf 'local=%s\nremote=%s\n' "$(git rev-parse HEAD)" "$(git rev-parse {{remote}}/{{branch}})" && git status --short --branch && git log --oneline --decorate --graph -n 8
ResolutionPreserve the recurrence, compare it with the first evidence set, restore the known-good state if necessary, and reopen the unresolved layer instead of stacking another repair.
Security notes
- Store only redacted operational evidence and remove temporary debug output according to local retention policy after review.
Alternatives
- Use the service's approved monitoring or audit trail when an interactive observation window is not practical.
Stop conditions
- Do not close the incident while the result is intermittent, the rollback point is missing, or a safety control remains weakened.
Finish line
Verification checklist
git fetch {{remote}} && printf 'local=%s\nremote=%s\n' "$(git rev-parse HEAD)" "$(git rev-parse {{remote}}/{{branch}})" && git status --short --branch && git log --oneline --decorate --graph -n 8The operation completes with exit status 0 and without the original error. The output identifies the intended host, service, repository, or endpoint.git rev-parse --show-toplevel && git status --short --branch && git symbolic-ref --short -q HEAD || true && git rev-parse --verify HEAD 2>/dev/null || echo UNBORN_HEADA fresh diagnostic capture shows the healthy path and no recurrence of the original signature. Logs and counters remain stable during the observation window.Recovery guidance
Common problems and safe checks
remote origin already exists
Likely causeRepository setup is being repeated against an existing remote name.
git remote -vgit remote get-url origin
ResolutionVerify and set the existing remote URL deliberately or choose another named remote; do not stack duplicates.
cannot lock ref
Likely causeConcurrent Git process, stale lock, ref namespace conflict, permissions, or repository corruption.
git statusfind .git -name '*.lock' -lsgit fsck --no-dangling
ResolutionStop concurrent writers and diagnose the exact lock/ref; remove a stale lock only after proving no process owns it.
force-with-lease rejected
Likely causeThe remote ref changed since the expected lease was observed.
git fetch origingit log --left-right origin/main...HEAD
ResolutionReview the new remote commits and integrate them; never replace `--force-with-lease` with `--force` automatically.
Reference
Frequently asked questions
Why does main not match any?
Usually no local `main` ref exists: the repository has no commit, the branch is named differently, or the desired commit is detached/unreachable.
Should I run git push --force?
No. First fetch and inspect divergence. If an approved rewrite is required, use a precise `--force-with-lease` expectation after preserving a backup ref.
Can I rename master to main?
Yes when repository policy calls for it, but verify local commits, remote default branch, automation, protection, and open work before changing names.
Why did authentication fail after I fixed the refspec?
Ref selection and transport authentication are separate layers. Diagnose the remote protocol and credentials without changing history.
Recovery
Rollback
Restore the local backup ref and, if an approved remote rewrite occurred, use the recorded previous remote object with a reviewed lease.
- Switch to or reset a new recovery branch at `backup/before-push-*` without deleting current work.
- Fetch and record the current remote branch before any corrective update.
- Use a pull request or explicitly approved `--force-with-lease=<ref>:<expected-old-id>`; never use an unguarded force.
Evidence