Git has something called submodule support. This allows you to specify one or more other git repositories within another – a bit like svn:externals (except trickier, but more powerful of course :).
The git user manual describes submodules but it took me a while to figure it out, so I’m hoping these examples will help others (and me again when I forget and find my own page when googling about it :)
These examples deal with
your_project and the project you’ll be adding as a submodule,
Adding a submodule to your_project
$ git submodule add email@example.com:other_project.git other_project Initialized empty Git repository in /home/john/dev/your_project/other_project/.git/ remote: Counting objects: 59, done. remote: Compressing objects: 100% (59/59), done. remote: Total 59 (delta 22), reused 0 (delta 0) Receiving objects: 100% (59/59), 8.33 KiB, done. Resolving deltas: 100% (22/22), done.
other_project and sets up the
.gitmodules config to
your_project and adds them both ready to be committed. You’ll notice that the
other_project directory is added, not all the files within. Git just records the commit id from the
other_project repository and uses that when cloning – a bit like a tag.
$ git status # new file: .gitmodules # new file: other_project
So now commit those changes:
$ git commit .gitmodules other_project -m "Added other_project submodule" $ git push
Cloning a tree with submodules
Git doesn’t automatically fetch all your submodules, so you need to do the following after cloning your tree:
$ git submodule init Submodule 'other_project' (firstname.lastname@example.org:other_project.git) registered for path 'other_project' $ git submodule update Initialized empty Git repository in /home/john/dev/your_project/other_project/.git/ remote: Counting objects: 59, done. Receiving objects: 100% (59/59), 8.33 KiB, done.bjects: 91% (54/59) Resolving deltas: 100% (22/22), done. remote: Compressing objects: 100% (59/59), done. remote: Total 59 (delta 22), reused 0 (delta 0) Submodule path 'other_project': checked out '6d5ca374208715501832eb33ed6a70022a3bb60c'
Updating a submodule
So somebody pushed some updates to
other_project and you want them in
$ cd other_project $ git pull origin master Updating 6d5ca37..235996d Fast forward 5 files changed, 100 insertions(+), 10 deletions(-) $ cd .. $ git add other_project $ git commit otherproject -m " Updated other_project submodule to latest HEAD"
If you want a particular commit rather than the head of master, then just specify that commit id on pull (instead of master). If you want the head of a particular branch then specify that branch name instead of master.
It is important not to have a trailing slash when you add
other_project as this will treat it as a normal directory, adding all the files within it to
your_project and forgetting about it’s submodule status
Making changes to a submodule within your_project
To make changes to
your_project tree, you need to explicitly checkout a branch first:
$ cd other_project $ git checkout master ...make your changes... $ git commit -a -m "Fixed a bug" $ git push $ cd .. $ git add other_project $ git commit -m "Updated other_project"
You need to remember to push changes to
other_project before you push
your_project else others won’t be able to clone
your_project properly as it will reference commits to
other_project that haven’t been published yet!