Git Submodulesの操作手順

親リポジトリに子リポジトリ(サブモジュール)を追加する

  1. 親リポジトリ: 子リポジトリを配置するディレクトリに移動する

  2. 親リポジトリ: 子リポジトリを追加する。子リポジトリがcloneされ、親リポジトリのルートディレクトリに .gitmodules が追加される。

    git submodule add <REMOTE_CHILD_REPO_URL> [<CHILD_REPO_PATH>]
    
  3. 【子リポジトリの特定のコミットをチェックアウトする場合】

    cd <LOCAL_CHILD_REPO>
    git fetch
    
    # コミットIDでチェックアウト
    git checkout <COMMIT_ID>
    # または最新のブランチをチェックアウト
    git branch -vaa
    git switch <BRANCH_NAME>
    git branch -vaa
    
  4. 親リポジトリ: 子リポジトリを追加したことをコミットする

    # 子リポジトリのコミットIDの確認
    git submodule
    git status
    git add .gitmodules <LOCAL_CHILD_REPO>
    git commit -m "update: Add submodule"
    

子リポジトリを含む親リポジトリを一括でcloneする

  • 親リポジトリ: リモートの親リポジトリと複数の子リポジトリを一括でcloneする [1]

    git clone --recurse-submodules <REMOTE_PARENT_REPO_URL> [<LOCAL_DIR>]
    
  • 親リポジトリ: 後で全ての子リポジトリをcloneする [1]

    cd <LOCAL_PARENT_REPO>
    # 親リポジトリの指定コミットをチェックアウト
    git submodule update --init --recursive
    

リモートリポジトリから一括でpullする

# 差分確認----
git fetch
# ローカルとリモートの差分を確認
git status -sb
# behind確認
git log --oneline HEAD..@{u}
# ahead確認
git log --oneline @{u}..HEAD
# ----

# pull実行
git pull --recurse-submodules

子リポジトリに最新の更新を取り込む

  1. 親リポジトリ: pullして最新のリモートの更新を取り込む。親リポジトリが記録する子リポジトリのコミットIDが更新される。

    git pull
    git submodule
    ===
    +<commit-id> <path> (<abbrev-sha>)  # +が先頭についていると、親リポジトリが記録しているコミットIDとは異なるコミットIDを指している
    ===
    
  2. 親リポジトリ: 親リポジトリが記録しているコミットIDで子リポジトリをチェックアウトする [1]

    git submodule update --init --recursive
    git submodule
    ===
    # +表示がなくなる
    ===
    

子リポジトリに変更を加える、子リポジトリのブランチを切り替える

  1. 子リポジトリ: 子リポジトリに変更を加えられるようにブランチを切り替え、HEAD detachedから脱する [1]

    cd <CHILD_REPO>
    git branch -vaa
    ===
    * (HEAD detached at xxxxx) # HEAD detachedを確認
    ===
    git switch <BRANCH_NAME>
    git pull
    
  2. 子リポジトリ: 変更を加えて、コミットとpush

    git add <CHANGED_OR_ADDED_FILES>
    git commit -m "<COMMENT>"
    git push [<origin>] [<branch>]
    
  3. 親リポジトリ: 子リポジトリのチェックアウトコミットIDをコミットし、リモートリポジトリへpush

    cd <PARENT_REPO>
    git add <CHILD_REPO>
    git commit -m "<COMMENT>"
    git push [<origin>] [<branch>]