Git - Submodules
Jump to navigation
Jump to search
Submodule
- Git does not allow partial checkouts by default (needs a special setup and treatment: git-scm.com/docs/partial-clone)
- Copying libraries to git is one option, but in big projects it is impossible due to the size of the code
- Git's submodule support allows a repository to contain, as a subdirectory, a checkout of an external project.
- Submodules maintain their own identity; the submodule support just stores the submodule repository location and commit ID
- ("superproject") can easily clone all the submodules at the same revision
- Partial checkouts of the superproject are possible: you can tell Git to clone none, some or all of the submodules.
Examples
- We will create four repositories a,b,c,d in a /g folder
Making 4 repos
cd
mkdir g
cd g
for i in a b c d
do
mkdir $i
cd $i
git init
echo "module $i" > $i.txt
git add $i.txt
git commit -m "Initial commit, submodule $i"
cd ..
done
Create superproject and add all the submodules
# necessary setup for file protocol
git config --global protocol.file.allow always
#
cd
mkdir super
cd super
git init
for i in a b c d
do
git submodule add ~/g/$i $i
done
git commit -m "Add submodules a, b, c and d."
Git submodule
- clones the submodule under the current directory and by default checks out the master branch.
- adds the submodule's clone path to the .gitmodules file and adds this file to the index, ready to be committed.
- adds the submodule's current commit ID to the index, ready to be committed.
Cloning repos with submodules
git clone super cloned
cd cloned
git submodule status
ls -a a
git submodule init # add the submodules repos URL to .git/config
git submodule update # clone submodule repos and check them out
ls -a a
git submodule status
Shorter way
git clone --recurse-submodules super clonedShorter
Updating Submodules
When the submodule will have updates
Pulling
# commit new changes to the subproject
cd ~/g/a
echo something > newfile.txt
git add newfile.txt
git commit -m "new file"
# check it out in the superproject
cd ~/super/a
git pull
# look at it
cd ..
git diff
git diff --submodule
# save it and search it
git commit -am "upd a"
git log -p --submodule
Shorter way, for all submodules
# commit new changes to the subproject b
cd ~/g/b
echo something >> b.txt
git commit -am "upd b"
# commit new changes to the subproject c
cd ~/g/c
echo something >> c.txt
git commit -am "upd b"
# pull in all subm
cd ~/super
git submodule update --remote
# look at it
git diff
git diff --submodule
# save it and search it
git commit -am "upd b and c"
git log -p --submodule
Updating the cloned one
cd ~/cloned
git submodule update --remote
git diff --submodule
git pull
git log -p --submodule
Tweaking the submodule
Preparing the setup
cd ~/g
git clone --bare a a.git
cd ~/g/a/
git remote add origin ~\g\a.git\
git push --set-upstream origin master
# Edit file '~/super/.gitmodules'
## [submodule "a"]
## path = a
## url = C:/Users/Lenovo/g/a.git
cd ~/super
git status
git commit -am "tweaking submodule setup"
cd ~
git clone --bare super super.git
cd ~/super
git remote add origin ~\super.git\
git push --set-upstream origin master
cd ~/super/a
git remote rm origin
git remote add origin ~\g\a.git\
git push --set-upstream origin master
Within subproject
cd ~/g/a
echo "change in the upstream" >> a.txt
git commit -am "not dodgy hack"
git push
Within our super project submodule
cd ~/super/a
echo "change a" >> a.txt
git commit -am "dodgy hack"
Finally in the super project
cd ~/super
git submodule update --remote --merge
git status
git submodule status
cd ~/super/a
git checkout --theirs a.txt
git add .
git commit -m "the upstream better"
cd ~/super
git diff
git diff --submodule
git commit -am "main line"
git push --recurse-submodules=on-demand