Git - Submodules
Submodule
- Git does not allow partial checkouts
 - 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
 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
