Moving Git Repos Containing Submodules
August 19, 2012

If you work with submodules in git, and you’ve ever tried to move a repository locally to a different place on your machine, you may have encountered a problem.

In recent versions of git, the embedded submodules don’t have their own “.git” directory. Instead they contain a text file called .git which points git back at the root .git directory, which contains all the information for all submodules. Furthermore, there’s a config file for each submodule, hidden in the main .git directory, which points “forward” to the submodule.

That would all be fine except for one incredibly stupid thing: in versions of git prior to 1.7.10, this path was stored in absolute format.

Which means that if you move the repo on your disk, all of these paths break, and the repo no longer works!

This is, to put it mildly, a bit of a pain in the arse.

What to do?

The long answer is to go through all of the submodules and do the following:

That’s all fine and dandy, but it’s a tricky process, and if you’ve got lots of submodules, some of which may even have embedded submodules, it’s a lot of work.

Luckily, there’s a short answer:

This isn’t ideal, but it gets you working again.

What’s more, it’s a lot easier to automate. Figuring out the proper relative paths isn’t that easy to automate, but doing a search and replace of one known string with another across a bunch of files is.

Here’s a script I wrote to do it.

It’s not a perfect script, and please be aware that it makes permanent changes to files so you may well want to zip up the whole of your repo first as a paranoid backup.

However, it seems to work for me. It could take the old and new paths as parameters, but I decided to embed them in the script for a couple of reasons.

One, it’s a better example of what the paths should look like. Two, this situation is most likely to occur when you’ve made some sort of global change, like renaming or changing your hard drive. In that case you’ll probably want to do the same replacement lots of times on different repos, so embedded it in the script is helpful (and also reduces the risk of typing it wrong).