submodule

[!TIP|label:reference:]

init submodule

$ git submodule add --name <NAME> -b <BRANCH> <REPO_URL> </path/in/repo>
$ git submodule init
$ git submodule update --init
  • i.e.:

    $ git submodule add --name ansible-completion \
                        -b master \
                        https://github.com/dysosmus/ansible-completion.git \
                        confs/home/.marslo/.completion/ansible-completion
    $ git submodule add --name bash-completion \
                        -b master \
                        https://github.com/scop/bash-completion.git \
                        confs/home/.marslo/bin/bash-completion
    $ git submodule init
    $ git submodule update --init

update submodule

# update branch
$ git config -f .gitmodules submodule.<NAME>.branch <NEW_BRANCH>
$ git submodule update --remote

$ git submodule deinit -f .
$ git submodule update --init
  • or

    $ git submodule foreach --recursive git clean -dffx
    $ git submodule foreach --recursive git reset --hard

submodule update history

$ git log --oneline [--name-only] -- /path/to/submodule

# list all
$ git config --blob HEAD:.gitmodules --get-regexp path |
  awk '{print $NF}' |
  xargs -I{} bash -c "echo -e \"\\n~~> {}:\"; git log -1 --oneline -- {}"

list submodules

[!TIP|label:references:]

example:

$ git config --blob HEAD:.gitmodules --get-regexp [url|branch|path]
# or
$ git config --blob HEAD:.gitmodules --get-regexp ^submodule.\(.+\).\(path\|url\|branch\)

$ git config --blob HEAD:.gitmodules --list
# or
$ git show HEAD:.gitmodules | git config --file - --list
  • get dynamic refs

    $ git cat-file -p <refs>:.gitmodules
    
    # or
    $ git show -p <refs>:.gitmodules

get name

$ git submodule foreach --quiet 'echo $name'

# or
$ git submodule foreach --quiet 'echo $name' |
  xargs -I{} bash -c "git ls-tree -z -d HEAD -- {}; echo ''"

get path

$ git show HEAD:.gitmodules | git config --file - --get-regexp path

# or
$ git --no-pager config \
      --file \$(git rev-parse --show-toplevel)/.gitmodules \
      --get-regexp ^submodule.\\(.+\\).path

get url

$ git show HEAD:.gitmodules | git config --file - --get-regexp url

# or
$ git --no-pager config \
      --file \$(git rev-parse --show-toplevel)/.gitmodules \
      --get-regexp ^submodule.\\(.+\\).url

# or
$ git submodule foreach -q git config remote.origin.url

# or
$ find .git/modules/ -name config -exec grep url {} \;

# or
$ git config --list | grep -E ^submodule.*.url

get branch

$ git config --blob HEAD:.gitmodules --get-regexp branch

working with submodule

pull from remote

  • update submodule only

    $ git submodule update --remote --recursive --force --rebase
  • update both super and submodule

    $ git pull [--rebase] --recurse-submodules

push to remote

  • push submodule only

    $ cd ./path/to/submodule
    $ git push --recurse-submodule=on-demand
  • push for both super and submodule

    $ cd ./path/to/submodule
    $ git add --all
    $ git commit -am ".. comments here .."
    $ git push --recurse-submodule=on-demand
    
    $ cd $(git rev-parse --show-superproject-working-tree)
    # or: https://stackoverflow.com/a/7359782/2940319
    $ cd $(git rev-parse --show-superproject-working-tree --show-toplevel | head -1)
    
    $ git add --all
    $ git commit -am ".. comments here .."
    $ git push origin $(git rev-parse --abbrev-ref HEAD)

remove submodule

$ git submodule deinit -f <NAME>                              ### operational
$ git rm --cached <NAME>
$ rm -rf <submodulePath>
$ rm -rf .git/modules/<NAME>
$ git config -f .gitmodules --remove-section submodule.<NAME> ### or $ rm -rf .gitmodules
$ git config -f .git/config --remove-section submodule.<NAME> ### or $ vim .git/config

Last updated