Search code examples
gitgit-mergegit-merge-conflict

git take theirs/ours AND successfully merged code


Suppose there is conflict when rebasing a feature Git branch on a master Git branch:

git init
echo -e "one\ntwo\nthree\nfour\nfive" > foo
git add foo
git commit -m a

echo -e "ONE\ntwo\nTHREE\nfour\nfive" > foo
git commit -a -m b

git checkout -b feature HEAD^
echo -e "One\ntwo\nthree\nfour\nFive" > foo
git commit -a -m c

git rebase master

The conflicting file foo is:

<<<<<<< HEAD
ONE
=======
One
>>>>>>> c
two
THREE
four
Five

How can I obtain from command line the file foo_master containing the sucessfull merge (THREE and Five), and is case of conflict, the master code (ONE):

ONE
two
THREE
four
Five

Note that it is different from git checkout --ours foo, which does not contains the modificatoin from feature successfully applied (Five):

ONE
two
THREE
four
five

I would also like to have the counterpart file foo_feature containing the feature code in case of conflict, but with the modificatons from master that are successfully applied (ONE):

One
two
THREE
four
Five

My goal is then to vertically vimdiff the files foo_master and foo_feature to solve the conflict.


Solution

  • Use git merge-file, twice, with --ours in one case and --theirs in the other. (Note that these are not the same as -s ours but more like -X ours, but they apply only to one set of three input files.)

    You will need all three input files, but they are available during a conflicted merge, as all three are in the index, at stage 1 (base), 2 (ours), and 3 (theirs). Use git checkout-index --stage=all to extract all three at once. Note that this implies --temp, so that you get three file names printed, containing the three copies of the three input files, copied out of the index, into a usable format.

    (This is how git mergetool obtains the three copies of the files to feed to an external merge tool such as vimdiff.)