Accidental Commit to Main¶
Two commits meant for a feature branch landed on main instead, because the branch was never created first. Interviewers use this because the safe fix is a two-step move (name the commits, then rewind main) and the tempting wrong move (reset --hard before saving the commits) throws the work away.
Symptom¶
"I did some work and committed it, then realised I was on main the whole time and never made a branch. Nothing is pushed yet. Get my commits onto a feature branch and put main back where it was."
Clarifying Questions¶
- Are the commits pushed? If
mainis local-only ahead oforigin/main, a rewind is safe; if pushed, this becomes a shared-history problem needingrevert. - How many commits are on the wrong branch?
git log origin/main..HEADcounts them exactly. - Is
mainprotected upstream? A protectedmainwould have rejected a direct push anyway, which confirms nothing shared was affected. - Is the working tree clean? Uncommitted changes must be handled before any
reset --hard, which would discard them.
Diagnostic Path¶
1. Confirm main Is Ahead and Nothing Is Pushed¶
git status -sb
Output:
## main...origin/main [ahead 2]
[ahead 2] means the local main has two commits origin/main does not, so the accident is entirely local. Listing exactly those commits confirms what will move.
git log --oneline origin/main..HEAD
Output:
e65525a Wire up login
812fddf Add login form
Both commits are the feature work. origin/main..HEAD is the precise set to relocate, and it excludes the shared history that must stay on main.
Root Causes¶
| Cause | Evidence | Fix |
|---|---|---|
| Forgot to branch before committing | main ahead of origin/main by the feature commits | Branch at the tip, rewind main |
Committed on main, already pushed | git status shows up to date or the push was accepted | git revert on main, or a coordinated reset |
| Meant to amend, made a new commit | Two commits with near-identical intent | Squash after relocating, if wanted |
Fix¶
The move is two steps: first give the commits a branch so they cannot be lost, then rewind main to the remote.
git branch feature/login
git reset --hard origin/main
Output:
HEAD is now at ede4502 Add app
git branch feature/login created a pointer at the current tip, so both commits are now reachable from feature/login. git reset --hard origin/main moved main back to match the remote. Verifying shows the commits safe on the new branch and main clean.
git log --oneline --all --decorate
Output:
e65525a (feature/login) Wire up login
812fddf Add login form
ede4502 (HEAD -> main, origin/main) Add app
git switch feature/login
Output:
Switched to branch 'feature/login'
main now equals origin/main, and the feature work continues on feature/login. Because the commits were branched before the reset, the --hard was safe; without the branch, git reflog would have been the only way back.
Branch before you rewind, not after
git reset --hard moves the branch and discards anything not otherwise reachable. Run git branch <name> first so the commits have a second pointer; then the reset only moves main and loses nothing.
Prevention¶
- Start feature work with
git switch -c feature/<name>before the first commit, somainnever receives it. - Protect
mainon the remote (branch protection lives in GitHub) so a stray direct push is rejected. - Watch the branch name in the shell prompt or
git statusheader; the## mainline is the tell. - If the commits were already pushed, do not rewind shared history; use
git revertand open a proper branch for the redo.
Related¶
- Branches: creating the branch that saves the commits
- Undoing Changes:
resetmodes and why--hardneeds a saved pointer first - Wrong-Branch Commits: the same problem when commits landed on the wrong feature branch
- Round 3: Troubleshooting: the read-only-first method this fix follows
Captured on macOS 26 with git 2.50.1 (throwaway local repositories), 2026-09.