When I encounter a merge conflict using git rebase
, how can I identify the source of the conflict in terms of commits, rather than just file differences?
I already know how to make (basic) use of git mergetool
or git add
before git rebase --continue
, but sometimes the differences between files just isn't enough: I want to see the commit log and diff of the commit that just failed to be applied to the working tree.
I've read in other questions that git log --merge
would show the parent commits if I were using git merge
. I tried it anyways when I encountered a conflict and got told fatal: --merge without MERGE_HEAD?
.
How can I identify the problematic commit?
Note that before Git 2.29 (Q4 2020), Git could also change the hash of the commit onto which you are rebasing in the todo message, commit which should not change (since you are replaying old commits onto this one).
If the change that you submitted has a merge conflict, you need to manually resolve it using git rebase. Rebasing is used to integrate changes from one branch into another to resolve conflicts when multiple commits happen on the same file. Never do a rebase on public (master) branches.
If it says
Patch failed at 0001 commit message for F
Then run
$ head -1 .git/rebase-apply/0001 From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001
To get the SHA ad1c77
of the failing commit, and then use git show ad1c77
to have a look at it.
Let's start with this tree:
A---B---C---D \ E---F---G $ git checkout G $ git rebase D
When a rebase conflict occurs, it is a conflict between
C--D
) from the the common ancestor (B
) PLUS the already rebased changes and already resolved conflict (E'
) versus F
)Let's see what happens:
1) A---B---C---D---E' <- E patched and committed successfully as E' 2) A---B---C---D---E'--- <- failed to patch F onto E'
Here's the error message:
First, rewinding head to replay your work on top of it... Applying: commit message for F Using index info to reconstruct a base tree... Falling back to patching base and 3-way merge... Auto-merging 1.txt CONFLICT (content): Merge conflict in 1.txt Failed to merge in the changes. Patch failed at 0001 commit message for F
First, you can see that it was F
, because the commit message appears. However, if your commit messages all look like "foo", "documentation" or "some fixes", then this won't help, and you really want the SHA id ad1c77
or the contents of the patch.
F
:When it lists the rebase conflict, it will say something like:
Patch failed at 0001 commit message for F
Now look in .git/rebase-apply/
, where you will find the patch file 0001
:
$ ls .git/rebase-apply 0001 head-name msg orig-head sign 0002 info msg-clean patch threeway apply-opt keep next quiet utf8 final-commit last onto rebasing
The patch file includes the original commit-id
$ head -1 .git/rebase-apply/0001 From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001
You can then look at that.
There must be an easier way, but this works.
Note that the fact that the patch failed may be due to a different commit (if you are rebasing onto a common ancestor of HEAD
and the rebase target). Finding that commit is rather more complicated, although you could try doing the rebase in reverse to find it:
$ git checkout D $ git rebase G
During a git rebase
which stops to resolve conflicts, the following command will show the conflicting commit (all of it, not just the conflicting files), that is, your commit currently being replayed/rebased onto the new base, regardless of where you are up-to:
git show $(< .git/rebase-apply/original-commit)
If you want to see only the conflicts for a specific conflicting file (the one you are resolving), in-isolation:
git show $(< .git/rebase-apply/original-commit) -- /path/to/conflicting/file
No cats were abused in the construction of this answer :).
This may be a new feature, but REBASE_HEAD
gives you the commit where you're currently stopped (e.g. if the commit failed to apply). If you want to see the commit in full you can use
git show REBASE_HEAD
As a more verbose alternative, you can use git rebase --show-commit-patch
. The docs say they are equivalent.
If you want to see what's changed between where you're rebasing from and where you're rebasing to, you can get a diff between the two branches. For example, if you're rebasing from master
onto origin/master
you can use:
git diff master..origin/master
Or if you want to see the changes as individual commits:
git log -p master..origin/master
If you'd prefer to use the hash or maybe are coming back to a rebase after a while and can't remember which branches you're rebasing, you can use git status
to see the two branches. For example:
You are currently rebasing branch 'master' on 'b5284275'
Then, to see what's changed you can use:
git diff master..b5284275
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