OliverRadini
OliverRadini

Reputation: 6466

Create custom merge strategy

I've heard it mentioned that you can create your own strategies for detecting merge conflicts. This question, for instance, suggests that it's possible. I'd like to give this a try, but I can't find any further information at all.

I understand that I need to create some executable and have it in the path - no problem - but what will be passed to this executable, and what should it output

Upvotes: 1

Views: 152

Answers (1)

torek
torek

Reputation: 489293

A merge strategy is one selected by git merge -s. You're correct that you would just have to put an executable program into your $PATH (or Git's git-core directory, which the git front end adds to $PATH).

The problem is that writing a merge strategy is not trivial (in fact it's very hard in general) and the arguments that Git passes are undocumented. You will have to figure them out from the Git source, and be aware that they might change in a future version of Git. Some of them are secreted in environment variables—in particular, the legends you can attach to the commits involved in the merge are in environment variables that contain the hash ID of the commits in question.

(I have not written a merge strategy myself and don't have any particular advice, other than: use GIT_TRACE=1 git merge -s <strategy> to invoke your strategy to see what the argv elements are. The hidden environment variables used to be exposed in the git stash script but git stash has been rewritten in C.)

Your merge strategy's job is to update Git's index to hold the merge result, then exit with a zero status (success); or, don't, and exit with a nonzero status—normally 1—to indicate failure. If you wish to be user-friendly it's advisable to update the work-tree based on any successful merge result, too. There may be a special exit status for "merge not even attempted" (vs "merge failed, I leave a mess for human to finish merge with") but that too is not documented.


The built in set of merge strategies is:

  • git-merge-recursive: git merge -s recursive invokes this one; it's the usual one most people are most familiar with.
  • git-merge-resolve: git merge -s resolve invokes this. It's actually the same program as git merge-recursive, it just does something different when there is more than one merge base commit.
  • git-merge-octopus: While git merge -s octopus invokes this one, so does any git merge that lacks a -s option, but mentions more than one other-commit to merge.
  • git-merge-ours: git merge -s ours invokes this.
  • git-merge-subtree: git merge -s subtree invokes this. Like git-merge-resolve, is just a variant of git-merge-recursive.

If you don't pass a -s argument, Git will use -s recursive unless you named two or more commit arguments.

As you can see from the list above, there are really only three strategies built in to Git: octopus, ours, and "everything else". The octopus strategy does not handle merge conflicts (at all), and -s ours completely ignores all other input commits, which makes its code relatively simple, so most of the hard work is in the single remaining merge strategy.

Upvotes: 3

Related Questions