I wanted to document how to deal with an annoying corner case with git-submodules here. This applies in two variations:
- Changing the URL of a submodule to another tree with different ids (eg, two different git-svn conversions of the same SVN project).
- Converting an entire existing directory to a submodule.
If you apply the changes to all of your branches right when you make them, they are easy to do, but if you have old rotting branches, and you haven't kept them up to date, you can run into fun errors like the following:
fatal: cannot read object c1a25b84627516da46b6c375f4dc874deedbb597 'vendor/plugins/rspec~a4c30e94d52232e958d4f53c6a633ed438c54bcc': It is a submodule!
"vendor/plugins/rspec" already existed as a directory in this case. So how to do we work with this problem?
- Look at the "git log ${PARENT_BRANCH} .gitmodules". Every time there was a change to the file, make a temporary tag. I suggest using tags with date+time in the name, as you will be making more tags in a bit. You should do this on the branch that is the parent of the branch you want to fix, to cut down on conflicts.
- Next, identify spots that directories were deleted immediately prior to conversion to submodules, or between submodule URLs. Also tag these.
- Edit your .git/config, and comment out ALL submodule references.
- Now one at a time, issue "git pull . tags/${TAGNAME}", for each of your temporary tags, in order.
- If you hit conflicts, fix them up as usual (edit files, "git-update-index ${FILES}", "git commit -F .git/MERGE_MSG")
- If you think you messed up, use "git reset --hard ${COMMITISH} && git clean -f" with a known good point to reset you.
- Remember to clean up your temporary tags afterwards.
- Do "git submodule init" again.
I don't see why Git couldn't be made to do this automatically, since the process is reasonable simple, if a bit long to do by hand.