TL;DR: you need -s theirs
which does not exist
There are several substitutes, though. See the other answers to this question, search StackOverflow for "git merge strategy theirs", and/or read Is there a "theirs" version of "git merge -s ours"? carefully (since the original querent was actually looking for -X theirs
, which I describe below). Or use the following rather magic bit of sh/bash script code:
git merge --ff-only $(git commit-tree -p HEAD -p dev dev^{tree} -F /tmp/commitmsg)
after putting the commit message you want into the file /tmp/commitmsg
. Be very sure this is really what you want to do, because it almost never is.
Description
The -X
(eXtended arguments) ours
and theirs
do not mean use our version or use their version. They mean, instead, when there is a conflict, use our change or use their change.
What this means
In your example, the tip of master
is commit C
and the tip of dev
is commit E
. So if the current branch is master
, the current commit is C
. It does not matter at this point whether you pass the name dev
, or the hash ID of commit E
, to git merge
: both select commit E
as the commit to merge.
In any case, commit A
is the merge base, because tracing backwards from both C
and E
simultaneously to the first point where they meet, arrives at commit A
.
Therefore, git merge
will:
- diff commit
A
against commit C
: this is what changed in your current branch, i.e., ours
.
- diff commit
A
against commit E
: this is what changed in theirs
.
- Attempt to combine these two diffs.
Suppose that one of the files is named animals.txt
, in all three commits. In commit A
we find some lines about cats and some about elephants. There are more lines (about aardvarks, bats, dogs, finches, gerbils, hamsters, iguanas, jackrabbits, and so on—something for every letter of the alphabet!) but we'll concentrate on Cats and Elephants for the moment ... and also on Shrews, which are Shared.
In commit C
compared to A
, there is a new or different claim about cats. So the diff from A
to C
shows this change about Cats (C). There is also a change to Shrews:
$ git diff <hash-of-A> <hash-of-C>
...
@@ ... @@
blah blah
-something about Cats
+something different about Cats
blah blah
@@ ... @@
etc
-the Shrew flies through the air, carefree
+the Shrew swims the ocean, carefree
etc
In commit E
compared to A
, there is a new or different claim about elephants. So the diff of A
-to-E
shows this change about Elephants. There is a different, conflicting change to Shrews—we'll omit everything but that here:
@@ ... @@
etc
-the Shrew flies through the air, carefree
+the Shrew eats rhinos, though it causes indigestion
etc
When Git goes to merge these changes, it will pick up the change to Cats from A
-to-C
and the change to Elephants from A
-to-E
. These changes do not conflict so there is no problem combining them. But it will also see the changes to the lies about shrews, and these changes conflict and cannot be combined.
The -X
options direct Git to choose one side or the other of a conflict
Because there is a conflict here, Git needs help resolving the merge. By default, Git just declares "there is a conflict", writes both changes into the work-tree, and stops with a conflict, leaving you to clean up the mess yourself. (There's much more done behind the scenes to help you with conflict resolution, but none of that matters right now.)
With one of these -X
options, though, Git is told to choose ours, or choose theirs, and just plow on ahead. But this only affects conflicting changes. Git will still combine non-conflicting changes as usual: in the example above, regardless of which -X
you pick, Git will take both the Cat and Elephant changes, and -X
will simply choose which Shrew change to pick.
Merge strategies are different
There is a Git merge strategy called ours
, invoked as git merge -s ours
, that is very different from the -X ours
option. This strategy tells Git not to bother with a merge base after all, and just to keep the source tree from the "ours" commit. Git will make the merge commit, after doing no work at all to produce a proper merge. The effect is to "kill off" the other branch while preserving its commits; this allows you to delete the other branch name, keeping the commits in case you want to view them sometime, while declaring that you intend never to use them again (but obviously aren't quite sure about it :-) ).
If git merge -s theirs
existed, it would do much the same, except that it would "kill off" the current branch in favor of the new one. There may be times when you want this, and when they come up, it might be nice if Git had git merge -s theirs
, but for whatever reason, it has only git merge -s ours
.
The substitutes work, and the trick with git commit-tree
allows you to tie together arbitrarily many commits using any arbitrary existing source tree attached to any existing commit—hence it covers both -s ours
(use HEAD^{tree}
) and -s theirs
. The resulting commit object has no name, but is an immediate descendant of the HEAD
commit, so git merge --ff-only
will add it to the current branch.