目次

git submodule

git submodule update --init --recursive

since 2023-03-02

(以下は ChatGPT の回答)

"git submodule update –init –recursive"は、Gitでリポジトリ内のすべてのサブモジュールを、親リポジトリの参照に従って最新のコミットに更新するために使用されるコマンドです。

各オプションの説明は以下の通りです。

"git submodule update"は、親リポジトリに参照されているコミットに、リポジトリ内のサブモジュールを更新します。

"–init"は、まだ初期化されていないリポジトリに追加された新しいサブモジュールを初期化します。

"–recursive"は、サブモジュール内のサブモジュールを再帰的に初期化および更新します。

したがって、「git submodule update –init –recursive」を実行すると、Gitはすべてのサブモジュールが初期化され、親リポジトリの参照に従って最新のコミットに更新されることを保証します。これは、複数のサブモジュールが含まれる大規模または複雑なプロジェクトを扱う場合に特に便利です。

The command "git submodule update –init –recursive" is used in Git to update all submodules in a repository to their latest commit according to the main repository's references.

Here's what each option does:

"git submodule update" updates the submodules in the repository to the commit referenced in the parent repository.

"–init" initializes any new submodules added to the repository but not yet initialized.

"–recursive" initializes and updates any submodules in the submodules recursively.

So, when you run "git submodule update –init –recursive", Git will ensure that all submodules are initialized and updated to their latest commit, as referenced by the parent repository. This is particularly useful when working with large or complex projects that may contain multiple submodules that need to be updated and synced with the main repository.

以下は過去の記事

http://git-scm.com/book/en/Git-Tools-Submodules

http://qiita.com/items/0d525e568a6088f6f6bb

git subtree というのもある:

http://tech.a-listers.jp/2013/05/17/alternatives-to-git-submodule-git-subtree/

http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/

使ってみる

since 2013-06-05

新しいレポジトリを作って、サブディレクトリはすでにある別のレポジトリの中身を使う:

$ mkdir gitsubtest
$ cd gitsubtest/
$ git init
Initialized empty Git repository in /Users/nishimotz/work/gitsubtest/.git/
$ echo "hello" > readme.md
$ git add readme.md 
$ git commit -m "initial"
[master (root-commit) b628967] initial
 1 file changed, 1 insertion(+)
 create mode 100644 readme.md

ここでは somewhare.org の x2013www プロジェクトをサブディレクトリ www として取り込む:

$ git submodule add git@somewhare.org:nishimotz/x2013www.git www
Cloning into 'www'...
remote: Counting objects: 223, done.
remote: Compressing objects: 100% (181/181), done.
remote: Total 223 (delta 37), reused 223 (delta 37)
Receiving objects: 100% (223/223), 3.00 MiB | 932 KiB/s, done.
Resolving deltas: 100% (37/37), done.
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   .gitmodules
#	new file:   www
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	.DS_Store
$ git commit -m "add x2013www as a submodule www"
[master 8ab54e1] add x2013www as a submodule www
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 www
$ git show
commit 8ab54e13c2f21702c32ed1ef86f3af98bbbfe293
Author: Takuya Nishimoto <nishimotz@gmail.com>
Date:   Wed Jun 5 11:39:24 2013 +0900

    add x2013www as a submodule www

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..f0c8264
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "www"]
+       path = www
+       url = git@somewhare.org:nishimotz/x2013www.git
diff --git a/www b/www
new file mode 160000
index 0000000..6cb241c
--- /dev/null
+++ b/www
@@ -0,0 +1 @@
+Subproject commit 6cb241c12bc911e53d1e17ace4eff508f12423e9

サブモジュールから .gitignore をコピーして親モジュールに追加する:

$ cp www/.gitignore .
$ git add .gitignore 
$ git commit -am "gitignore"
[master 0116bcc] gitignore
 1 file changed, 2 insertions(+)
 create mode 100644 .gitignore

reflog するとサブモジュールディレクトリの外と中で別々の履歴が見える:

$ git reflog
0116bcc HEAD@{0}: commit: gitignore
8ab54e1 HEAD@{1}: commit: add x2013www as a submodule www
b628967 HEAD@{2}: commit (initial): initial
$ cd www/
$ git reflog
6cb241c HEAD@{0}: clone: from git@somewhare.org:nishimotz/x2013www.git

サブディレクトリの中に add する

http://stackoverflow.com/questions/9035895/how-do-i-add-a-submodule-to-a-sub-directory

コマンドそのものは .git がある場所でしか実行できない:

$ cd assets/
$ git submodule add git@somewhere.org:nishimotz/x2013www.git www
You need to run this command from the toplevel of the working tree.

しかし add 先を深くすることができる:

$ cd ..
$ git submodule add git@somewhere.org:nishimotz/x2013www.git assets/www
Cloning into 'assets/www'...
remote: Counting objects: 223, done.
remote: Compressing objects: 100% (181/181), done.
remote: Total 223 (delta 37), reused 223 (delta 37)
Receiving objects: 100% (223/223), 3.00 MiB | 933 KiB/s, done.
Resolving deltas: 100% (37/37), done.

clone する

親レポジトリが gitsubtest としてサーバに push されているとする。

これを git clone すると、サブモジュールは空のディレクトリになるが、下記の手順で中身を取り出せる:

$ git clone git@somewhare.org:nishimotz/gitsubtest.git
$ cd gitsubtest
$ git submodule init
$ git submodule update

この状態でサブモジュールの中で git branch すると (no branch) と出てくる。 git checkout master などしておいたほうが、あとでコミットするときに安全かも知れない。

init して update するのと、下記は等価なのか、何か違うのか。。

$ git submodule update --init

サブモジュールの中にさらにサブモジュールがある場合の操作:

$ git submodule update --init --recursive

conflict 対策

親レポジトリで git pull origin master すると、サブモジュールのメタ情報 subdir が CONFLICT になることがある。

http://stackoverflow.com/questions/826715/how-do-i-manage-conflicts-with-git-submodules

サブモジュールのメタ情報をファイルに見立てて reset すればいいという話:

$ git reset HEAD subdir
$ git commit -am "message"

サブモジュールの削除

親リポジトリの管理下に戻したいので削除する、というときは。

http://d.hatena.ne.jp/oppara/20101116/p1

$ git rm --cached path/to/hoge

この状態でこうなる:

#	deleted:    path/to/hoge
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   .gitmodules
#
# Untracked files:
#	path/to/hoge/

コミット:

$ git add .gitmodules
$ git commit -m "message"

それから path/to/hoge を add し直す:

$ cd path/to/hoge
$ rm -rf .git
$ rm .gitignore
$ git add .
$ cd ../../..
$ git commit -m "message"

リモートで更新されたサブモジュールが更新されない

サブモジュールを git pull origin master してから親モジュールで git submodule update

msysgit だと git submodule foreach がうまく動かない。

http://rochefort.hatenablog.com/entry/20110410/p1

サブモジュールの中で fetch & merge する

since 2013-12-24

サブモジュールの origin

公開レポジトリ https://bitbucket.org/nvdajp/nvdajpmiscdep

を更新したので、親レポジトリからの参照を更新したい:

親レポジトリからは miscDepsJp という名前で git submodule add されている。

> cd miscDepsJp
> git fetch origin master
> git merge FETCH_HEAD

git status / git branch する:

> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit, working directory clean

>git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

なぜか ahead になっているが。。

submodule が使われたレポジトリを clone すると、サブモジュールは名前のないブランチになるが、自分で add したサブモジュールは master ブランチになる、のだろうか。。

親レポジトリに戻って、参照をコミットする:

> cd ..

> git status
# On branch jpbranch
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   miscDepsJp (new commits)
#

サブモジュールの中が完全に clean であること。 さもなくば、git diff したときに、ハッシュ値の後ろに -dirty が付いてしまう。