Git
GitHub
Subversion
svn
GitLab

SVN externalヘビーユーザのためのGit submoduleの考え方

Subversion(SVN)で外部参照(externalプロパティ)ヘビーユーザのためのGit submoduleの考え方についてまとめました。

SVNでめちゃくちゃexternal使っていた方のために。

Git submoduleとは?

SubmoduleとはGitにおいて、SVNでいうところのexternalプロパティです。

共用APIなど、他のリポジトリなどにあるファイル、またはディレクトリを外部参照で引っ張ってきたい時に使います。

この記事はそもそもSVN externalを理解している人のためのものなので、詳細は省略します。

SVNから移行する時に、このexternalを使っている場合、submoduleを使うことになります。

SVN externalとの違いは?

SVN externalとGit submoduleの大きな違いは、更新の方法です。

SVN externalは親ディレクトリでSVN updateをすると、その下に属するexternal属性が付いたサブディレクトリは全て最新に更新されます。

一方、Git submoduleは親ディレクトリでpullしようが、mergeしようが、更新されません。

submoduleを設定したその時のCommit IDが記録されているだけなのです。

更新するには、外部参照しているディレクトリをPullコマンドなどで更新した後、

submodule updateというコマンドを実行してあげないといけません。

1つ1つフォルダを指定してsubmodule updateしなきゃならないの?

その必要はありません。そこはちゃんと考えられています。

親ディレクトリでsubmodule updateを実行すると、同時に更新するpathを設定できます。(Tortoise Gitの場合)

ここで複数パスを選ぶことが出来るので、どこかのディレクトリだけ取り残されたというようなことを防げます。

submoduleにbranchは指定できる?

もちろんbranch側も指定可能です。

別々の異なるリポジトリのコードを組み合わせて一時的な開発用ブランチを作るといったケースでも使いますね。

submodule addをするときに、branch側を指定すればそれ以降そのbranchの変更を取り込んでいくことが出来ます。

submodule設定しているディレクトリをbranchしたらどうなる?

前述したように、submoduleはcommit IDを指定したスナップショットのようなものです。

そのため、branchするとその時のcommit IDがそのまま引き継がれます。

submoduleの設定も引き継がれますので、branchした後もsubmodule updateすることは可能です。

submodule指定されたフォルダ以下のファイルは更新できない

SVN externalのように、リポジトリをチェックアウトしているわけでは無く、

あくまでスナップショットなので、変更をコミットすることが出来ません。

コミットもしたいという場合は、別コマンドであるSubtreeを使ってください。

色々試した結果思ったこと

Git submoduleでもSVN externalのような運用は可能ということが分かりました。

しかし、SVNと違って勝手に更新されないので、その意識が無いと組み合わせるモジュールが古かった等のミスを誘発しかねません。

従って、Gitに移行する際には、「本当に外部参照が必要なのか?」をもう一度考え直して、

その機会に外部参照は極力使わない方向でツリーを見直すというのがベストかと思います。