git submodule

使ってみる

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

  • .gitmodulesファイルから該当する行を削除
  • .git/configファイルから該当する行を削除
$ 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 が付いてしまう。

git_submodule.txt · 最終更新: 2014/01/16 17:59 by Takuya Nishimoto
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0