Darren Oakey
Darren Oakey

Reputation: 3654

any documentation for writing a custom git merge strategy?

There's certain binary file types that I have written my own code to merge cleanly. I've tried to add my own merge strategy by adding a merge command line with a driver in .gitconfig and adding a file expression in .gitattributes to point to my merge program.

And it works - if I do a git merge with that file type, it calls my program - if I exit with 1 it fails and says there's a conflict - if 0 it succeeds.

HOWEVER - I can't find any documentation on how it gets parameters - ie how do I know what file is being merged - what file it's being merged with etc. They aren't coming in as environment variables... I know on the driver command line I can put some variables, but with trial and error, $PWD is the only one that I've found that works.

Can anyone point me to any documentation about how to write a custom merge strategy?

Upvotes: 2

Views: 377

Answers (1)

torek
torek

Reputation: 489293

This answer is in two parts, because what you have described is not a merge strategy but rather a merge driver.

Merge strategies

I don't think there is any proper documentation. There is only the source code. You can get a good high level overview of how the strategies work using GIT_TRACE, though, because git merge computes some information and then runs git-merge-recursive or git-merge-octopus or whatever other -s <strategy> you've selected. If you write your own git-merge-oakey command, and run git merge -s oakey, you can view the arguments.

Merge drivers

Your merge driver is invoked in the way described in the gitattributes documentation (search for Defining a custom merge driver). The %-character substitutions will fill in the various arguments. As it says, wherever you write %O, %A, or %B, Git will fill in the name of a temporary file that holds the data from the appropriate index stage (copied out to an ordinary file in the work-tree). You're expected to overwrite the file that %A names.

how do I know what file is being merged ...

You don't know (and cannot tell) which file name is being merged; you're expected to complete your job using only the three input contents. Ultimately, there isn't necessarily a single file name anyway: Git may have detected a rename on one side of the merge, so that the file is named foo in the merge base and on one side, and bar on the other side. (As Hasturkun noted in a comment, the %P placeholder will expand to whichever name Git is going to use as its best guess for the final path-name. Do not use this as one of the three inputs to the merge process, though—the three inputs are in the %O, %A, and %B files.)

Upvotes: 6

Related Questions