I am working on a project where we manage external libs/headers and qa with git. Here is what every developers' directory structure looks like:
~/dev/proj
~/dev/ext
~/dev/qa
proj, ext and qa are different git repositories. Under svn, synchronization of these dirs was simple: a single update under ~/dev would update all of them recursively. With git, we need to do 'git pull' separately for each dir. This is not nice; someone will always forget to update (git pull) one of these dirs and his project will be out of sync (e.g. new qa will not pass with old code). I looked into 'git submodules' and it doesn't provide a single point for 'git pull' to update these three separate modules at the same time [Correction: I was wrong here but please read my answer below].
You could argue that we should have put proj, ext and qa under the same git repository but I thought that would have been against the git philosophy of keeping different concepts in different repositories.
Does anyone have a solution (other than writing a script to do git pull on every dir under ~/dev) to this trivial problem?
Thanks,
Altan
Herr Doktor,
You are comparing apples to oranges. git-submodules is similar to svn:externals, aka svn-submodules. In fact, when you use the -r
to attach an svn submodule at a specific revision, the behavior is nearly identical. To commit with svn-submodules, you have to commit in each submodule directory separately, just as with git-submodules.
There is a big difference though: Most devs, at least during some phase of development, prefer to attach to a branch of each submodule, which is not supported by git-submodules. That can be useful for coordinated development. (Google's Repo tool a wrapper around Git, meant for use with Gerrit, a code-review tool, is sort of similar. But trust me: Stay away from Repo. It solves a different problem.) The huge drawback is that you cannot recover an exact contour of your codebase. That seems fine for awhile, but I've heard nasty war stories.
The alternative for you is not Subversion, but simply a single repository, which could be in Git, Subversion, or whatever. But you actually want a combination of single repo and multiple repos, right? You want the benefits of each. So you need a more sophisticated solution.
One idea is to have one project repo, where you do most of your development, plus several separate repos, from which you distribute modules:
proj/.git
proj/subA
proj/subB
subA/.git
subB/.git
You could move code between them using rsync. The beauty is that you've made a sharp distinction between development and distribution. You develop your large project as normal, with branches, merges, etc. When you are ready to distribute a sub-directory as a library, you decide exactly what version of that library you want, and you copy it over to its own repo. When you need to merge instead of just copy, there is the git subtree merge strategy.
There is another system, built on top of the subtree-merge strategy. It's called git-subtrees, and it is part of git-1.7.11. Here is a nice description of its operation. You can see from the pictures that its timelines can look confusing, but functionally it's exactly what you want. Here is a more recent write-up, with excellent advice.
If you don't mind the extra 'update' step of git-submodules, but you're upset about how it handles conflicts, you could try giternal. The author has included a script to show how its behavior compares with git-submodules and braid (which is for vending submodules, but not merging them).
Personally, I like git-slave, which is a simple wrapper around git. Basically, it applies your gits
commands as git
commands to all your repos. It's really just a convenience. It's very easy to understand, has zero impact on the individual repos, and is great for branch-switching (which is not yet supported in git-subtrees).