Search code examples
gitgit-checkoutmerge-conflict-resolution

Resolve conflicts in favor of our/their keeping unconflicting changes


git checkout --theirs . for example just takes the whole "theirs" file.

I search for a way to use "ours" or "theirs", but only for conflicts, as if by always removing the respective other part and the conflict markers.


Solution

  • You can, before you start the git merge operation, choose just that, using the -X options. These options1 allow you to choose to have "ours" or "theirs" override during low level (inside-a-file) conflicts, without affecting the merging of non-conflicting changes from both sides.

    If you've already started the merge and resolved some conflicts, aborting the merge and restarting with -X ours or -X theirs is painful. It's also unnecessary, because Git provides a separate command, git merge-file, that performs the three-way merge on a single set of three input files.

    Hence, suppose you've started a merge, and it had three conflicts and stopped. If you ran git status at this point you'd see those three files as unmerged. So, you manually merged one of the three files, and started on the second and then thought: Wait, I'd like to just have Git do this for me.

    What you can do at this point is stop resolving the work-tree file manually. Exit any editor you're in, back to the command line. For the second of the three files, extract all three inputs:

    git show :1:file.ext > file.BASE
    git show :2:file.ext > file.OURS
    git show :3:file.ext > file.THEIRS
    

    You now have the three inputs that Git tried, and failed, to merge on its own. Git's attempt at merging the three is in file.ext; the three inputs are in these three files named .BASE, .OURS, and .THEIRS.

    You can now invoke git merge-file and pass it --ours or --theirs to choose our or their changes where there are conflicts:

    git merge-file --ours file.OURS file.BASE file.THEIRS
    

    The resulting merge is written back to file.OURS. Inspect it and see if you like the result; if so, rename it to file.ext and git add file.ext to mark this file resolved. Remove the file.BASE and file.THEIRS copies that are cluttering your work-tree.

    You have one remaining unresolved file. Repeat the three extraction commands and the git merge-file command on those three copies of that one remaining file.

    (There ought to be a user-oriented Git command that does all this for you, but there isn't.)


    1I call them "eXtended options" or "eXtended strategy options" to account for the letter X. The Git documentation just calls them "strategy-options", which is confusing because the -s option selects the strategy and hence is the strategy option. The -X arguments are thus the strategy-option options, distinct from the strategy option. ("Clear as mud", as they say.) Saying that -s is the strategy option and -X supplies eXtended options just seems a lot less confusing.