【git】git submodule の挙動を確認してみる【雑記】

``submodule``の挙動を確認するために、一つずつコマンドを実行して挙動を確認していく。

## サブモジュールの登録

```bash
> git submodule add git@github.com:kiyo27/git-submodule.git
```

変更を確認する。``.gitmodules``が作成されている。

```bash
> git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   .gitmodules
        new file:   git-submodule
> git diff HEAD git-submodule
diff --git a/git-submodule b/git-submodule
new file mode 160000
index 0000000..94a3033
--- /dev/null
+++ b/git-submodule
@@ -0,0 +1 @@
+Subproject commit 94a3033e4124495a4f6c44d373b02f14c24cf213
```

変更をプッシュする

```bash
> git add .gitmodules
> git add git-submodule
> git commit -m "update submodule to new version"
> git push origin main
```

コミットのポインタが登録されている

![2021-07-18_005217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/780549/6dc158c2-108a-b0e0-c7ff-350c683838fe.png)


## サブモジュールの更新

サブプロジェクト更新

```bash
// git-submodule(submoduleのリポジトリ)
> touch version.txt
> echo "version 1" > version.txt
> git add version.txt
> git commit -m "add version file"
> git push origin main
```

サブモジュールを含むプロジェクトでサブモジュールの更新を取り込む。

```bash
> cd git-submodule
> git fetch
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 287 bytes | 16.00 KiB/s, done.
From github.com:kiyo27/git-submodule
   94a3033..388a533  main       -> origin/main
> git merge origin/main
Updating 94a3033..388a533
Fast-forward
 version.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 version.txt
> ls
README.md  version.txt
```

### git submodule update --remote

マージを手動でおこなったが、``git submodule update --remote``だと自動で行える。


```bash
> git submodule update --remote
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 279 bytes | 16.00 KiB/s, done.
From github.com:kiyo27/git-submodule
   49324e5..d1d4ad0  main       -> origin/main
Submodule path 'git-submodule': checked out 'd1d4ad0f0223cb676f6b71b6c4fafe0be83520c6'
```

ブランチをチェックアウトしている(detachech HEADの状態になる)

detached HEAD の状態

```bash
> git status
HEAD detached at d1d4ad0
nothing to commit, working tree clean
> git branch
* (HEAD detached at d1d4ad0)
  main
```

detached HEAD の状態だとサブモジュールに変更を加えても、``git submodule update``を実行すると変更した内容はなくなる

サブモジュールに変更加える

```txt:git-practice/git-submodule/version.txt
ver 7
file change in sub project.
```

変更をコミット

```bash
> git commit -am "update"
```

メインプロジェクトで``git submodule update``を実行

```bash
> git submodule update --remote
Submodule path 'git-submodule': checked out 'd1d4ad0f0223cb676f6b71b6c4fafe0be83520c6'
```

サブモジュールで変更を加えたファイルを確認すると、変更した内容がなくなっている

```bash
> cd git-submodule
> cat version.txt
ver 7
```

### git submodule update --remote --merge

``git submodule update --remote --merge``を実行することでブランチをマージする

```bash
> git submodule update --remote --merge
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 1), reused 4 (delta 1), pack-reused 0
Unpacking objects: 100% (4/4), 496 bytes | 29.00 KiB/s, done.
From github.com:kiyo27/git-submodule
   351be29..a2913d2  main       -> origin/main
Updating 351be29..a2913d2
Fast-forward
Submodule path 'git-submodule': merged in 'a2913d257fe9442460eeae93d61ca2078212ef90'
```

ブランチの状態。detached HEAD ではない。

```bash
> git branch
* main
```

## メインプロジェクトでサブモジュールの更新

サブモジュールの内容を変更

```bash
> cd git-submodule
> echo "version @" > version.txt
> git commit -am "update"
```

メインプロジェクトでリポートにプッシュしてみる
差分確認

```bash
> git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   git-submodule (new commits)

no changes added to commit (use "git add" and/or "git commit -a")
```

変更をコミットしてリモートにプッシュする。

```bash
> git add git-submodule
> git commit -m "update submodule"
> git push origin main
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 268 bytes | 268.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:kiyo27/git-practice.git
   0c89257..a150914  main -> main
```

サブモジュールの変更をプッシュしないで、メインプロジェクトをコミット・プッシュすると他の人がサブモジュールの変更を取得できなくなる。
メインプロジェクトのサブモジュールは変更したポインタを指示している

``--recurse-submodules=check``を付与することで、サブモジュールの変更がプッシュ済み確認し、プッシュ済みでない場合はメインプロジェクトのプッシュでのプッシュをできないようにする

```bash
> git push --recurse-submodules=check
The following submodule paths contain changes that can
not be found on any remote:
  git-submodule

Please try

        git push --recurse-submodules=on-demand

or cd to the path and use

        git push

to push them to a remote.

fatal: Aborting.
```

``--recurse-submodules=on-demand``を付与することで、メインプロジェクトのpush時にサブモジュールもpushする

```bash
> git push --recurse-submodules=on-demand
Pushing submodule 'git-submodule'
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 291 bytes | 291.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:kiyo27/git-submodule.git
   3822fdd..351be29  main -> main
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 261 bytes | 261.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:kiyo27/git-practice.git
   72055b4..0c89257  main -> main
```

または、サブモジュールで作業してプッシュする

```bash
> cd git-submodule
> git push origin main
```

## サブモジュールを含むプロジェクトのクローン

サブモジュールを含むプロジェクトをクローンする。ただクローンしただけでは、サブモジュールの中身はからっぽ。

```bash
> git clone git@github.com:kiyo27/git-practice.git main-project
> ls -la
total 0
drwxrwxrwx 1 ubuntu ubuntu 4096 Jul 18 12:20 .
drwxrwxrwx 1 ubuntu ubuntu 4096 Jul 18 12:20 ..
```

``git submodule init``と``git submodule update``を実行する

```bash
> git submodule init
Submodule 'git-submodule' (git@github.com:kiyo27/git-submodule.git) registered for path 'git-submodule'
> git submodule update
Cloning into 'C:/Users/narik/workspace/git/main-project/git-submodule'...
Submodule path 'git-submodule': checked out 'daf413635a93e7622c31d11d7313e042eee91ea5'
```

サブモジュールの中身

```bash
> ls -la git-submodule
total 0
drwxrwxrwx 1 ubuntu ubuntu 4096 Jul 18 12:24 .
drwxrwxrwx 1 ubuntu ubuntu 4096 Jul 18 12:20 ..
-rwxrwxrwx 1 ubuntu ubuntu   38 Jul 18 12:24 .git
-rwxrwxrwx 1 ubuntu ubuntu   17 Jul 18 12:24 README.md
-rwxrwxrwx 1 ubuntu ubuntu    9 Jul 18 12:24 version.txt
```

ブランチは detached HEAD の状態になっている

```bash
> git branch
* (HEAD detached at daf4136)
  main
```

サブモジュールを含むプロジェクトをクローンするときに``--recursive``オプションを使用すると、サブモジュールの初期化とデータの取得を一緒に行ってくれる

```bash
> git clone --recursive git@github.com:kiyo27/git-practice.git main-project
Cloning into 'main-project'...
remote: Enumerating objects: 72, done.
remote: Counting objects: 100% (72/72), done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 72 (delta 12), reused 66 (delta 6), pack-reused 0
Receiving objects: 100% (72/72), 8.20 KiB | 839.00 KiB/s, done.
Resolving deltas: 100% (12/12), done.
Submodule 'git-submodule' (git@github.com:kiyo27/git-submodule.git) registered for path 'git-submodule'
Cloning into 'C:/Users/narik/workspace/git/main-project/git-submodule'...
remote: Enumerating objects: 42, done.
remote: Counting objects: 100% (42/42), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 42 (delta 2), reused 40 (delta 0), pack-reused 0
Receiving objects: 100% (42/42), done.
Resolving deltas: 100% (2/2), done.
Submodule path 'git-submodule': checked out 'daf413635a93e7622c31d11d7313e042eee91ea5'
```

サブモジュールの中身。データが取得できている。

```bash
> ls -la git-submodule/
total 0
drwxrwxrwx 1 ubuntu ubuntu 4096 Jul 18 12:29 .
drwxrwxrwx 1 ubuntu ubuntu 4096 Jul 18 12:29 ..
-rwxrwxrwx 1 ubuntu ubuntu   38 Jul 18 12:29 .git
-rwxrwxrwx 1 ubuntu ubuntu   17 Jul 18 12:29 README.md
-rwxrwxrwx 1 ubuntu ubuntu    9 Jul 18 12:29 version.txt
```

## 参考

https://git-scm.com/docs/gitsubmodules

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB