スタック・オーバーフローに参加する
684万人以上のプログラマーが集まるスタック・オーバーフローに参加しませんか?
簡単な登録後、すぐにご利用いただけます。
登録

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)

UPDATE: 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.

share|improve this question
1  
Also see this answer: stackoverflow.com/questions/928646/… - it's trivial to change the example to use version B instead of A. – Robie Basak Nov 8 '10 at 23:11
7  
See SO answer git command for making one branch like another for all the current possible ways to simulate git merge -s their. – VonC Mar 13 '11 at 8:54
4  
So you are not really looking for a git merge -s theirs (that can be achieved easily with git merge -s ours and a temporary branch), since -s ours completely ignores the changes of the merge-from branch... – Nicolò Martini May 8 '14 at 12:01
4  
@Torek - do the Git devs really find it that offensive to provide theirs in addition to ours??? This is a symptom of one of the high level engineering and design problems in Git: inconsistency. – jww Sep 15 '16 at 15:25

14 Answers 14

up vote 603 down vote accepted

Add the -X option to theirs. For example:

git checkout branchA
git merge -X theirs branchB

Everything will merge in the desired way.

The only thing I've seen cause problems is if files were deleted from branchB. They show up as conflicts if something other than git did the removal.

The fix is easy. Just run git rm with the name of any files that were deleted:

git rm {DELETED-FILE-NAME}

After that, the -X theirs should work as expected.

Of course, doing the actual removal with the git rm command will prevent the conflict from happening in the first place.

share|improve this answer
5  
actually this is the best answer. – Felipe Micaroni Lalli Mar 13 '11 at 20:56
2  
this saved my day! Favoriting for future reference :) – Pabluez Dec 21 '11 at 20:32
4  
See other answer below for a better solution (Paul Pladijs) to the original question. – Malcolm Jul 16 '13 at 13:54
105  
Worth to note that this is not the same as "merge strategy theirs". -Xtheirs is the strategy option applied to recursive strategy. This means that recursive strategy will still merge anything it can, and will only fall back to "theirs" logic in case of conflicts. While this is what one needs in most cases like above, this is not the same as "just take everything from branch B as is". It does the real merge instead anyway. – Timur Oct 14 '13 at 11:57
2  
It works with other commands as well. I just did a 'git cherry-pick sha1 -X theirs'. Thanks! – Max Hohenegger Oct 17 '14 at 15:33

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.

share|improve this answer
20  
This works absolutely perfectly. This answer should be considered THE ANSWER. – UsAaR33 Jun 25 '11 at 0:41
4  
+1 Of all the solutions I read online, this is the one that worked for me. – Craige Oct 5 '11 at 20:54
4  
@cdunn2001: Somehow I thought the same thing, but no. Note that git reset --hard changes which commit branchA points to. – Tsuyoshi Ito Nov 9 '12 at 19:37
4  
sorry to ask a stupid question but why is this method better the -xtheirs? what are the advantages/disadvantages – chrispepper1989 Feb 10 '15 at 10:19
4  
@chrispepper1989 -x theirs only affects conflicts, if a hunk of ours can be applied cleanly it will get through to the resulting merge. In this case, as shown by the last command, we are getting a merge that is perfectly identical to branchB, regardless of whether there would have been conflicts or not. – UncleZeiv May 5 '15 at 16:37

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.

share|improve this answer
    
thanks, I am not totally satisfy by my answer though, it was missing the checkout of other files in old. it was odd, I add to checkout them... to commit --amend them then. – elmarco Oct 6 '08 at 23:25
4  
I really don't understand Junio Hamano's explanation at all. How is git reset --hard origin a solution for a theirs style merge? If I wanted to merge BranchB into BranchA (like in Alan W. Smith's answer), how would I do it using the reset method? – James McMahon Sep 20 '12 at 14:23
2  
@James McMahon: Junio C Hamano’s point is not git reset --hard does a “theirs”-style merge. Of course, git reset --hard does not create any merge commit, or any commit for that matter. His point is that we should not use a merge to replace whatever in HEAD by something else. I do not necessarily agree, though. – Tsuyoshi Ito Nov 9 '12 at 19:44
6  
It is a shame that the theirs was removed because the rationale was incomplete. It failed to allow for those instances where the code is good, its just that the upstream is maintained on a different philosophical basis, so in that sense is 'bad', so one does want to both keep up to date with the upstream, but at the same time retain ones good code 'fixes' [git & msysgit have this some of this 'conflict' because of their different target platform's philosophies] – Philip Oakley Aug 5 '13 at 19:53
1  
It's also missing the use case I'm stuck with right now, where I'm sharing a branch with someone else and we both happened to push up changes (on different files) at the same time. So I want to clobber all the old versions I have locally and use his newer ones instead. He wants to do the same for the files I updated. There's nothing to 'reset'. And the solution to checkout each individual file is not practical when it's ~20 files. – szeitlin Sep 24 '15 at 18:50

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)

share|improve this answer
1  
would be great if the list of files could be retrieved. For example, git ls-files --modified | xargs git add I wanted to do this for added on both sides merge :/ – andho Nov 26 '12 at 8:02
    
Actually git returns the added on both sides files with git ls-files --modified so i guess this is also a viable solution. – andho Nov 26 '12 at 8:06
    
Thanks for adding this too. More often then not it's needed on a file-by-file base. Also, git status shows "Unmerged Paths" at the very bottom. To get the list of unresolved paths, I use this alias: git config --global alias.unresolved '!git status --short|egrep "^([DAU])\1"' – Melvyn Jan 10 '15 at 17:22

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).

share|improve this answer
4  
I think this is BEST answer of this question. – sonicfly Feb 14 '15 at 4:46
    
A cleaner version of option 3: git checkout branchA; git merge -s ours --no-commit branchB; git read-tree -um @ branchB; git commit – jthill May 21 '16 at 18:22
    
@jthill: While your version is more concise it also uses the low-level ("plumbing") command read-tree that the average git user might not be used to (at least I am not ;-) ). The solutions in the answer use only the high-level ("porcelain") commands most git users should know. I prefer them but thank you for your version nevertheless! – siegi May 21 '16 at 18:56
    
Can you explain the second to last step (checkout branchA)? It seems like it should not be there. – Patrick Jun 17 '16 at 2:44
    
@Patrick, this step is required. If you skip it, you'll get the same commit but you would not have a branch pointing to this commit. So as soon as you switch to another commit/branch the commit you did with the last command (…commit --amend…) would be "lost". I'm planning to add some graphical explanations to this answer as soon as I have time to do them… ;-) – siegi Jun 17 '16 at 11:35

I solved my problem using

git checkout -m old
git checkout -b new B
git merge -s ours old
share|improve this answer
    
a branch "B" from "old" branch – elmarco Feb 22 '10 at 17:07
    
If this is the solution, then you should mark it as the answer. – Ziggy Jul 15 '11 at 21:31

If you are on branch A do:

git merge -s recursive -X theirs B

Tested on git version 1.7.8

share|improve this answer

When merging topic branch "B" in "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 their.

I'm assuming that you created a branch off of master and now want to merge back into master, overriding any of the old stuff in master. That's exactly what I wanted to do when I came across this post.

Do exactly what it is you want to do, Except merge the one branch into the other first. I just did this, and it worked great.

git checkout Branch
git merge master -s ours

Then, checkout master and merge your branch in it (it will go smoothly now):

git checkout master
git merge Branch
share|improve this answer

To really properly do a merge which takes only input from the branch you are merging you can do

git merge -s ours ref-to-be-merged

git diff --binary ref-to-be-merged | git apply -R --index

git commit --amend

There will be no conflicts in any scenario I know of, you don't have to make additional branches, and it acts like a normal merge commit.

This doesn't play nice with submodules however.

share|improve this answer
    
THANK YOU for this. This works for me every time when I just can't get a feature branch to merge into master without a lot of pain. – jathanism Jul 16 '14 at 23:13
    
What does the -R do here? – P. Myer Nore Jun 30 '15 at 12:14
    
This way you lose the history of files "moved and changed". Am I right? – elysch Apr 19 '16 at 22:43

See Junio Hamano's widely cited answer: if you're going to discard committed content, just discard the commits, or at any rate keep it out of the main history. Why bother everyone in the future reading commit messages from commits that have nothing to offer?

But sometimes there are administrative requirements, or perhaps some other reason. For those situations where you really have to record commits that contribute nothing, you want:

(edit: wow, did I manage to get this wrong before. This one works.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard
share|improve this answer

This will merge your newBranch in existing baseBranch

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch
share|improve this answer
    
I'd suggest adding git commit --amend to the end of your example, or users may see the merge commit with git log and assume the operation is complete. – Michael R Apr 22 '15 at 18:55

This one uses a git plumbing command read-tree, but makes for a shorter overall workflow.

git checkout <base-branch>

git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit

# Check your work!
git diff <their-branch>
share|improve this answer
git merge -Xtheirs <branch_name>
share|improve this answer
2  
As with the accepted answer, this does not do what -s theirs would do. – jthill Feb 23 '15 at 17:00

I think what you actually want is:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

This seems clumsy, but it should work. The only think I really dislike about this solution is the git history will be confusing... But at least the history will be completely preserved and you won't need to do something special for deleted files.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.