Git clone vs Git submodule

April 17, 2008 by Ed Spencer · 8 Comments 

Having recently made the switch from svn to git, I wanted to achieve what svn externals did (and what Piston did better). Turns out this is pretty simple, for example to get rails on edge:

cd your_git_dir
git submodule add git://github.com/rails/rails.git vendor/rails[/code]
A couple of other default submodules you'll want:

git submodule add git://github.com/dchelimsky/rspec.git vendor\plugins\rspec
git submodule add git://github.com/dchelimsky/rspec-rails.git vendor\plugins\rspec-rails
[/code]
What submodule does is to check out the submodules as their own repositories, so they are tracked independently of the repository you made them submodules of. The submodules you have are tracked in the .gitmodules file, which might look something like this:

[submodule "vendor\rails"]
path = vendor/rails
url = git://github.com/rails/rails.git
[submodule "vendor/plugins/rspec"]
path = vendor/plugins/rspec
url = git://github.com/dchelimsky/rspec.git
[submodule "vendor/plugins/rspec-rails"]
path = vendor/plugins/rspec-rails
url = git://github.com/dchelimsky/rspec-rails.git
[/code]
Or at least that's how it should look, Windows seems to mess this up into looking something like the following:

[submodule "vendor\rails"]
path = vendor\\rails
[submodule "vendor\rails"]
url = git://github.com/rails/rails.git
[submodule "vendor\plugins\rspec"]
path = vendor\\plugins\\rspec
[submodule "vendor\plugins\rspec"]
url = git://github.com/dchelimsky/rspec.git
[submodule "vendor\plugins\rspec-rails"]
path = vendor\\plugins\\rspec-rails
[submodule "vendor\plugins\rspec-rails"]
url = git://github.com/dchelimsky/rspec-rails.git
[/code]
Note especially that you need to remove the \\'s and replace all \'s with /'s. If you don't git will give a fail message like:

fatal: bad config file line 2 in .gitmodules
No submodule mapping found in .gitmodules for path 'vendor/plugins/attachment_fu'
[/code]
I don't know why it's doing that, maybe it's something I'm doing wrong but you'll need to tidy it up to make it look more like the first example in order for it to work properly.

One final thing to be aware of is that when you clone onto a new machine you'll need to run the following commands:

git submodule init
git submodule update
[/code]
This will initialise the submodules that are referenced in the .gitmodules file, then pull them down. By default cloning doesn't seem to do that.

Related posts

About Ed Spencer
Geek

Comments

8 Responses to “Git clone vs Git submodule”
  1. Matt Jones says:

    Great post! This really helped out a lot in understanding how to migrate to git from svn. I had been using svn:externals, and the git submodule approach does seem a lot better!

  2. kain says:

    and where’s the “vs” git clone in this article?

  3. Edward Spencer says:

    @Matt glad it helped :)

    @kain clone is the default way of checking out a repository instance but submodule does a fairly similar thing. I guess I thought that too obvious to mention what clone does and just concentrate on the differences. Sorry about that, does it make more sense now?

  4. falker911 says:

    Thanks for the article.

  5. Anonymous says:

    Thanks for posting this… so now if you want to update the submodules to newer revs, do I simply do a ‘git pull’ in them and then commit in the super-tree to get new refs for them stored in the index?

  6. Edward Spencer says:

    @Anonymous yes that’s correct – cd into the submodule’s directory and do a git pull. You’ll then need to cd into your main repo’s directory, add your changes using git add, commit and push.

    When someone else pulls next, they can run git submodule update which will update their submodules to the version you just pulled.

    If you had added a new submodule, the other person would need to run git submodule init again before git submodule update.

  7. Anonymous says:

    git submodules are handy. So is git-svn. Can the two play nice or do you need an intermediate
    git-svn repository?

    i.e. I'm running a git project A. I want to track an external project, a django plugin say, as a submodule of A. But that external project uses svn repo X. Do I need to make a git repo B that tracks X with git-svn, then track B as a submodule of A, or can I track X in A without an explicit repo B ?

  8. Mike Zazaian says:

    Thanks for the great tutorial! Here's another article about submodules that extends a little bit on this functionality:

    http://doblock.com/articles/using-git-submodules-to-manage-plugins-in-rails

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!