`git merge -s theirs` needed but it does not exist

Many thanks to @VonC for suggesting the use of the merge=custom-driver attribute in the .gitattributes file. While this will work, I’m reluctant to pollute my workspace with .git files, and while I could use $GIT_DIR/info/attributes to avoid the pollution, I’m bothered by the need for 2 rules to catch dot-files and non-dot files.

After a bit of experimentation I managed to get a solution with the merge.default configuration variable (mentioned in the gitattributes(5) manpage) working. The trick I missed was that merge.default takes the name of a custom driver you have defined previously; you don’t give it the custom command directly. Here’s what works for me…

First define your copy-merge custom driver. You can use shell commands directly; there’s no need for an external script (just make sure you get your shell meta-character quoting right):

git config merge.copy-merge.name   'Copy Merge'
git config merge.copy-merge.driver 'mv %B %A'

Note that mv returns 0 on success, 1 on failure, meeting the criteria for reporting merge “success” back to git.

Now tell git that ALL merges are copy-merges:

git config merge.default copy-merge

Hey Presto! Job done. git merge <branch> will now copy-merge everything so the branch you’re on contains exact copies of all files on <branch>. QED.

If you want to do a non-copy-merge then simply reset the default merge driver:

git config --unset merge.default

If you do want to be more selective then leave merge.default unset and use attributes as @VonC says:

cd path/to/copy-merge/in
echo '* merge=copy-merge'  >  .gitattributes
echo '.* merge=copy-merge' >> .gitattributes

Do this at the top of every subtree you want to copy-merge in. If there’s a sub-subtree that you DON’T want to copy-merge in, you can turn it off again:

cd path/to/copy-merge/in/path/to/normal-merge/in
echo '* merge'  >  .gitattributes
echo '.* merge' >> .gitattributes

WARNING: littering your working tree with lots of .gitattributes files is bound to lead to confusion, especially if you also use things like “*.bin -merge” in other directories to force all merges of .bin files to fail with conflicts. It may be better to use $GIT_DIR/info/attributes for this sort of thing, as it has the highest precedence.

Leave a Comment