Git - Submodules

From Training Material
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.

200PX

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