Wrong branch: committed or pushed to the wrong place
Advanced
Why this matters
Committing to main is the most common Git mistake there is, and it happens to everyone who works on more than one thing at once. It is completely recoverable, in two commands, provided you have not pushed.
Case 1: committed to main, not pushed
This is the standard fix, and it is worth memorising as a pair.
You notice the problem in git status:
$ git status -sb## main...origin/main [ahead 1]$ git log --oneline -295a0014 docs: add Windows steps to installation guide (#12)
d3b92ec chore: add CI configuration and contributing guide
Ahead by one, and that one should have been on a branch. Two commands:
$ git branch docs/12-windows-install-steps
$ git reset --hard origin/mainHEAD is now at d3b92ec chore: add CI configuration and contributing guideThe first gives the commit a name without switching to it, so nothing moves. The second moves main back to match the remote. Confirm:
$ git log --oneline -1d3b92ec chore: add CI configuration and contributing guide$ git log --oneline -1 docs/12-windows-install-steps95a0014 docs: add Windows steps to installation guide (#12)
main is clean and the work is on its branch, ready to be pushed and turned into a merge request. Then git switch docs/12-windows-install-steps and carry on.
For several commits, the shape is identical: git branch <name> then git reset --hard origin/main moves all of them, because the branch you just created points at the newest one and takes the whole chain with it.
Case 2: uncommitted work on the wrong branch
Nothing has been committed, so nothing needs undoing. Move the work:
$ git stash
$ git switch -c docs/faq-tidy
$ git stash pop M docs/faq.mdYour edits are now on the new branch. If the target branch already exists, drop the -c.
There is an even shorter version when the branches share the same starting point: git switch -c <name> on its own carries uncommitted changes with it, because switching does not touch modified files unless it has to. The stash version always works, so it is the one to remember.
Case 3: the commit is on the wrong branch and belongs on another
git cherry-pick copies a commit onto the branch you are on:
$ git switch release/1.2
$ git cherry-pick 95a0014[release/1.2 83d3709] docs: add Windows steps to installation guide (#12)
1 file changed, 4 insertions(+)Note the new hash: cherry-pick creates a copy, it does not move anything. The original commit is still on its original branch, which is why the second half of the job is removing it there, with a reset if it is unpushed or a revert if it is not.
This is also how backports work: a fix lands on main and is cherry-picked onto a release branch (lesson 13.5).
Case 4: already pushed to the wrong branch
Once it is on the server, rewriting is off the table unless the branch is yours alone (lesson 12.8). The safe sequence has three steps:
- Cherry-pick the commit onto the branch it should be on, and push that branch.
- Revert it on the branch it should not be on:
git revert <hash>, then push. - Say so in the merge request or the team channel, because for a few minutes the history contained something unexpected and someone may have pulled it.
If the wrong branch was main and it is protected, step 2 is a merge request like any other, which is exactly what protection is for.
Case 5: pushed to a protected branch and were refused
Nothing is broken. The push was rejected, so the commit is still only in your clone:
remote: GitLab: You are not allowed to push code to protected branches on this project.Apply case 1: name the commit with a branch, reset main, push the branch. The rejection did the work of catching the mistake.
How to do it
The two-command fix, and the stash version:
$ git branch <new-branch> # name the commit where it is
$ git reset --hard origin/main # move main back$ git stash # uncommitted work
$ git switch -c <new-branch>
$ git stash pop
There is no single action for this. The reliable route is the Command Palette: Git: Create Branch (which does not move your commits), then Git: Checkout to main, then a terminal for the reset. For uncommitted work, Git: Stash, create the branch, Git: Pop Stash.
IntelliJ handles this well. Right-click the commit in the Log → New Branch from Selected Commit, then right-click the commit main should return to → Reset Current Branch to Here… → Hard. Cherry-pick is a right-click action on any commit in the log.
The platform's contribution is prevention: a protected main refuses the push in the first place (lesson 9.5). If something wrong did reach a branch, the Revert button on the commit page creates the revert and a merge request for it.
The same: rulesets refuse the push, and a merged pull request or a commit page offers Revert.
Common mistakes
git switch -c <name>first, then wondering how to remove the commit frommain. Creating the branch first, while still onmain, is what makes the fix two commands.git reset --hardwith uncommitted work. Stash first.- Resetting a branch that was already pushed, which then needs a force push.
- Cherry-picking and forgetting to remove the original, leaving the same change on two branches with different hashes.
- Panicking about a rejected push. A rejection means nothing happened, which is the good outcome.
Try it yourself
Goal: commit to main on purpose and fix it.
- On your practice repository with
maintrackingorigin/main, make a change and commit it tomain. - Run
git status -sband see[ahead 1]. - Run
git branch fix/wrong-branch-demo, thengit reset --hard origin/main. - Confirm with
git log --oneline -1on bothmainand the new branch. git switch fix/wrong-branch-demo, push it, and open a merge request as usual.- Repeat with uncommitted work, using the stash version.
Expected result: main matches the remote, the commit is on its own branch, and you have done the fix once before you need it in earnest.
Show solution
The order in step 3 is the entire trick, and it is worth saying why: git branch <name> creates a name at the current commit without switching to it, so main and the new branch briefly point at the same commit. The reset then moves only main, leaving the new branch where it was.