Is there a "theirs" version of "git merge -s ours"?
When merging topic branch "B" into "A" using git merge
, I get some conflicts. I know all the conflicts can be solved using the version in "B".
I am aware of git merge -s ours
. But what I want is something like git merge -s theirs
.
Why doesn't it exist? How can I achieve the same result after the conflicting merge with existing git
commands? (git checkout
every unmerged file from B)
The "solution" of just discarding anything from branch A (the merge commit point to B version of the tree) is not what I am looking for.
Solution 1:
A similar alternative is the --strategy-option
(short form -X
) option, which accepts theirs
. For example:
git checkout branchA
git merge -X theirs branchB
However, this is more equivalent to -X ours
than -s ours
. The key difference being that -X
performs a regular recursive merge, resolving any conflicts using the chosen side, whereas -s ours
changes the merge to just completely ignore the other side.
In some cases, the main problem using -X theirs
instead of the hypothetical -s theirs
is deleted files. In this case, just run git rm
with the name of any files that were deleted:
git rm {DELETED-FILE-NAME}
After that, the -X theirs
may work as expected.
Of course, doing the actual removal with the git rm
command will prevent the conflict from happening in the first place.
Solution 2:
A possible and tested solution for merging branchB into our checked-out branchA:
# in case branchA is not our current branch
git checkout branchA
# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB
# make temporary branch to merged commit
git branch branchTEMP
# get contents of working tree and index to the one of branchB
git reset --hard branchB
# reset to our merged commit but
# keep contents of working tree and index
git reset --soft branchTEMP
# change the contents of the merged commit
# with the contents of branchB
git commit --amend
# get rid off our temporary branch
git branch -D branchTEMP
# verify that the merge commit contains only contents of branchB
git diff HEAD branchB
To automate it you can wrap it into a script using branchA and branchB as arguments.
This solution preserves the first and second parent of the merge commit, just as you would expect of git merge -s theirs branchB
.
Solution 3:
Older versions of git allowed you to use the "theirs" merge strategy:
git pull --strategy=theirs remote_branch
But this has since been removed, as explained in this message by Junio Hamano (the Git maintainer). As noted in the link, instead you would do this:
git fetch origin
git reset --hard origin
Beware, though, that this is different than an actual merge. Your solution is probably the option you're really looking for.
Solution 4:
It is not entirely clear what your desired outcome is, so there is some confusion about the "correct" way of doing it in the answers and their comments. I try to give an overview and see the following three options:
Try merge and use B for conflicts
This is not the "theirs version for git merge -s ours
" but the "theirs version for git merge -X ours
" (which is short for git merge -s recursive -X ours
):
git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB
This is what e.g. Alan W. Smith's answer does.
Use content from B only
This creates a merge commit for both branches but discards all changes from branchA
and only keeps the contents from branchB
.
# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB
# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA
# Set branchA to current commit and check it out.
git checkout -B branchA
Note that the merge commits first parent now is that from branchB
and only the second is from branchA
. This is what e.g. Gandalf458's answer does.
Use content from B only and keep correct parent order
This is the real "theirs version for git merge -s ours
". It has the same content as in the option before (i.e. only that from branchB
) but the order of parents is correct, i.e. the first parent comes from branchA
and the second from branchB
.
git checkout branchA
# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB
# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB
# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA
# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA
# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD
This is what Paul Pladijs's answer does (without requiring a temporary branch).
Solution 5:
I used the answer from Paul Pladijs since now. I found out, you can do a "normal" merge, conflicts occur, so you do
git checkout --theirs <file>
to resolve the conflict by using the revision from the other branch. If you do this for each file, you have the same behaviour as you would expect from
git merge <branch> -s theirs
Anyway, the effort is more than it would be with the merge-strategy! (This was tested with git version 1.8.0)