この記事は谷ゼミの落書き帳 Advent Calendar 2018 の17日目の投稿になります。
書くネタに困ってしまったので、備忘録の意味も含めて以前調べたGitのsubtreeとsubmoduleについてまとめようと思います。
はじめに
Gitのsubtreeとsubmoduleについてですが、どちらも外部リポジトリを自リポジトリに取り込む方法です。
多くの場合パッケージ管理システム(PHPの場合のcomposer等)が使われることが多いと思いますが、
それが使えない(それを使わない)場合の取り込み方法の選択肢としてそれぞれについて調べてみました。
subtree
subtreeを使用するには外部リポジトリを取り込みたいリポジトリのディレクトリで以下を実行します。
git remote add 外部リポジトリ判別用の名称 URL
git subtree add --prefix=取り込むディレクトリのパス --squash 外部リポジトリ判別用の名称 ブランチ名
ここで気をつける必要があるのが--squash
の指定です。
subtreeは外部リポジトリのhistoryもすべて取り込もうとしてしまうため、不要な場合は--squash
でまとめてあげる必要があります。
git subtree add
を実行すると、取り込んだディレクトリ(ファイル)はすべて自リポジトリの一部として扱うことができるため、変更を加えることもコミットすることも可能です。
自リポジトリへのコミット&pushを行えば、取り込んだディレクトリ(ファイル)もすべて一緒に自リポジトリのリモートに反映されます。
外部リポジトリに変更をpushすることも、外部リポジトリから変更を取り込むことも可能です。
subtreeのディレクトリを削除したい場合、他のディレクトリ同様rm
等で削除するだけです。
取り込んでしまえばあとは自リポジトリのものとして扱うことができるという部分がsubtreeの特徴かと思います。
submodule
submoduleを使用するには外部リポジトリを取り込みたいリポジトリのディレクトリで以下を実行します。
git submodule add URL 取り込むディレクトリのパス
取り込むディレクトリは自リポジトリで作成済みのディレクトリを選ぶことができないので注意が必要です。
git subtree add
との違いがここから出てきますが、submoduleは外部リポジトリのソースが自リポジトリに展開されません。
submoduleは外部リポジトリのある地点のコミットを参照するということだけが管理されます(コミットハッシュだけが管理されます)。
参照だけなので、変更を加えることも、ソースを自リポジトリのリモートにpushすることもできません。
※ 参照のためにローカルに展開することは可能です
※ 力技で変更することもできますが、あまりおすすめしないので方法も割愛します
※ 参照元のリポジトリが削除された場合にどうなってしまうのか等、まだまだ試せていないことも多いです
参照するコミットハッシュを変更する場合は、submoduleのディレクトリでgit pull
し、自リポジトリをpushすることで変更が反映されます。
submoduleのディレクトリを削除したい場合は、rm
等で削除するのではなく以下のコマンドを実行する必要があります、
git submodule deinit 取り込んだディレクトリのパス
submoduleはsubtreeと比較するとパッケージ管理システムの考え方に近いのが特徴かと思います。
終わりに
今回はあまり特殊なことはせずに基本的な部分のことを確認し、まとめてみました。
まだまだ紹介していないオプション等があると思いますので、これをきっかけにいろいろ調べてみると面白い発見があるかもしれません。
Qiitaへの投稿が初ということもありうまくまとめることのできなかった記事になってしまいましたが、読んでくださりありがとうございました!