I frequently find myself in this situation:
In the last step, I use git checkout -b new-branch-name, but after invoking that command, the current head no longer has references to the pulled changes. It only has one parent. It's no longer a merge.
How can I, while performing a merge, commit that merge to a new branch?
Personally, I avoid git pull. By avoiding it, I can first run git fetch, then inspect what's coming in. Having looked, I then use git merge but usually wind up also avoiding this particular mistake in the first place because I can see that the merge might be difficult and start on a new branch in advance.
Still, it is useful to be able to recover ... and it's easy! Just do this, as you did already:
git pull
# oh no, merge conflicts!
# resolve conflicts
git commit # or git merge --continue
and commit to the wrong branch, and then fix it up afterward:
git branch new-branch-name # create new branch to contain the merge
git reset --hard HEAD^1 # back up current branch to first-parent
git checkout new-branch-name # return to new branch
Diagrammatically, you start with:
o--o--o <-- your-branch (HEAD)
/
...
\
o--o--o <-- origin/your-branch
The conclusion of the merge advances your-branch to point to the new merge commit * you make:
o--o--o
/ \
... * <-- your-branch (HEAD)
\ /
o--o--o <-- origin/your-branch
We now add a new branch, pointing to this same merge commit:
o--o--o
/ \
... * <-- your-branch (HEAD), new-branch-name
\ /
o--o--o <-- origin/your-branch
and then use git reset to drag the branch name to which HEAD is attached back one step, in the first-parent direction, which restores it to its previous commit:
o--o--o <-- your-branch (HEAD)
/ \
... * <-- new-branch-name
\ /
o--o--o <-- origin/your-branch
and we're all set.
All of this relies on a useful principle about Git: Git is really all about commits. The branch names move around all the time; they're just how we find the commits. The commits are permanent (well, as long as we can find them) and unchangeable. Get the commits the way you like and then you can reshuffle the names at leisure.
(If HEAD^1 is hard to type for various reasons, note that you can use any of HEAD^ or HEAD~ or even @^ or @~. That is:
HEAD and @ are synonyms.^1 and ^ without 1, as suffixes, are synonyms: the 1 is implied if you omit it.~1 and ~ without 1, as suffixes, are synonyms: the 1 is implied if you omit it.^ and ~ do different things, both mean "go back some number of steps in the graph".The number after the ^ is the parent-number and is meaningful only for merge commits: 1 means first parent. So HEAD^1 means first parent of HEAD, and HEAD~1 means go back one first-parent. Applying all the synonym rules is what gives us the @^ and @~ constructs.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With