Tie Git Submodules to a Particular Commit or Branch
While working on getting QUnit-CLI cleaned up and refactored a bit, I realized I needed to tie the example code in the Git repository to a particular version of QUnit.js (those guys are making changes too fast for me to keep up). I have used SVN:externals prevsiously so Git submodules seemed like an obvious solution. A single submodule should allow me to keep QUnit-CLI inherently pointing to a particular revision of QUnit.js without requiring me to seperately document which version I was testing against.
The man page for git-submodule as well as the Git Book chapter on Submodules do a good job of documenting the command with some simple examples, but none that were 100% clear for my needs. In addition, I need my Git submodule to point to a specific commit (or branch) so that everyone cloning my code consistently can run my examples w/o fear that a new commit on HEAD will break something.
Step 1 : Add the submodule
Once the module is checked out, I need to add the QUnit submodule. First grab the GitHub url for my QUnit fork (eventually this will be replaced with the main QUnit repo) and execute the “add” command from within your local repository root.
git submodule add git://github.com/asynchrony/qunit.git qunit
Afterward there will be two modified and staged objects in your repo: .gitmodules will contain the submodule’s local path and source URL and a new folder named qunit which contains a full clone of your source repository.
** Fraser Speirs has a good writeup on what is going on behind the scenes with the Git internals and how the key to all of this is in the index files of each repo and the modes the changes are committed with. **
Step 2 : Fix the submodule to a particular commit
By default the new submodule will be tracking HEAD of the master branch but will NOT be updated as you update your primary repo. In order to change the submodule to track a particular commit or different branch change directory to the submodule folder and switch branches just like you would in a normal repo.
git checkout -b dev_branch origin/dev_branch
Now the submodule is fixed on the development branch instead of HEAD of master. Just easily I could set it to specific commit or tag.
Step 3 : Commit everything
Now from your primary repository you still have two modified objects: .gitmodules file and qunit folder. Commiting these changes will persist the new submodule tracking your desired branch.
Step 4 : Clone Recursive
The next time you (or someone else) clones this repo, they will need to do one of two things.
A) Add the –recursive flag to their git clone command
git clone REPO_URL --recursive
B) manually initialize and the submodules after the clone
git clone REPO_URL git submodule update --init --recursive