Consider two commits: one adds file A, and the other adds file B. These
commits don't conflict; you can merge them with no problem.
But if the two commits instead add submodules A and B, and you try to merge,
you'll likely get a conflict in .gitmodules. This seems wrong; .gitmodules
happens to be a plain text file as an implementation detail, but in terms of
interpretation, it is more like a map of maps (name1 -> {path -> "...", url ->
"..."}, name2 -> ...).
We (Two Sigma) keep our .gitmodules file in alphabetical order (so we don't use
git submodule add -- our .gitmodules file is instead generated by some more
complicated offline process). But even for ordinary .gitmodules files, order
is not important so long as it's consistent.
I could set my .gitattributes for the .gitmodules file to use a custom merge
driver. But: (a) I don't see an off-the-shelf one that does what I want
("union" happens to work in the add/add case, but not in the add/remove case or
other cases) and (b) I would have to rewrite my whole history in order to have
the .gitmodules file exist at every commit (or find a way to get
.git/info/attributes into each of my users' clones) and (c) this should work
correctly without customization; Git already treats the .gitmodules file as
special for commands like "status"; there's no reason it shouldn't do so for
merge and rebase.
I'm not sure I'll necessarily have time to implement this -- for our use case (
http://github.com/twosigma/git-meta ), we might be able to get away with doing
it in JS, and using something like
https://github.com/mirkokiefer/diff-merge-patch#sets . But if I did have time,
do others agree that it would be reasonable to special-case this file?
(Naturally, before doing the merge, we would check that the file was in fact
parseable as a git config file; merging two changed gitmodules files of which
either is unparseable would fall back to merging as text).