Accepts or discards all changes on Git conflicts
1 September 2020
Once you start dealing with conflicts in Git, one question often comes back:
How to accept/discard all changes from the other/base branch?
And, as always in tech, the answer is: it depends. It depends on whether you are merging from another branch, or rebasing on a base branch. Here’s why.
Conflicts when merging
When you are merging a branch, say
feat, into the base branch on which
you are currently working, say
master, the command you would use is
git merge feat. By doing so, git will produce a new commit on
commit will in effect be the top of the
master branch, leaving the
branch where it was. This may sound trivial but it has some importance.
Now, let’s imagine that your
feat branch is conflicting with your base
branch, and you would like to retain all the changes from
feat no matter
what. In that case, you can tell git to automatically deal with conflicts by
feat changes with a
git merge -X theirs feat. The extra
strategy option (
--strategy-option) we passed here indicates that
all conflicts must be resolved by preferring the changes from the branch we
are bringing in, in other words, their changes.
This should come to no surprise but you can get the opposite behaviour by
preferring the changes from the base branch using the
-X ours strategy
option. In that case, because the changes of the currently checked out
branch are preferred, those are considered as our changes, as opposed to
the changes from the branch we are bringing in.
As always, don’t hesitate to refer to the official man page of the
merge command using
man git-merge which is well detailed and is
completely offline. The equivalent online documentation is available
Does it all make sense now?
ours refers to the base branch while
corresponds to the other branch. Well, during a rebase, this is the
opposite. Git’s fun, right?
Conflicts when rebasing
In case you’re wondering: no, git authors are not mad men who just want their
users to suffer every time they use
rebase. The real reason is consistency.
Let’s perform a rebase from our previous example using the
git rebase master
command (supposing we started from the
feat branch) to understand why
theirs work oppositely.
When conflicts arise during a rebase, you would have to specify
-X theirs to
force git to resolve conflicts by applying
feat branch changes. Conversely,
if your goal is to resolve the conflicts by always using the changes from
the base branch, you would need to use
This surely sounds counter-intuitive at first. However, if we take the time
to put ourselves in the shoes of
git rebase, this makes more sense.
Here’s what is (mostly) happening during our
git rebase master operation:
# Step 1. git checkout <HASH_OF_THE_COMMIT_POINTED_BY_THE_MASTER_BRANCH> # Step 2. git cherry-pick <FIRST_COMMIT_OF_FEAT_BRANCH> git cherry-pick <SECOND_COMMIT_OF_FEAT_BRANCH> # ... a few more cherry-picks may happen here # Step 3. git branch --force feat HEAD
You can notice from steps 1. and 3. that the rebase does not operate directly
feat branch. Instead, it cherry-picks the commits from the
branch, one by one (this is step 2), directly onto the original commit
pointed by the
In that context, we can see why the changes of the
feat branch, from which
we started the rebase, are considered as
theirs. Meanwhile, the commits
from the base branch
master are considered as
ours. What happens here is
the same as what we described in the previous section. The difficulty only
lies in the fact that rebase moves around while doing its duties, and does
not remain on the branch it started from.