Git Submodule vs. Subtree 比較

外部リポジトリをプロジェクトに取り込むには、主にGit SubmoduleとGit Subtreeの2つの方法がある。本記事では、両者の違いについて詳しく解説する。

比較まとめ

まず、SubmoduleとSubtreeの主な違いを以下の表にまとめた。

項目 Git Submodule (リンク方式) Git Subtree (コピー方式)
基本概念 外部リポジトリへのリンク(参照)を保持する 外部リポジトリのファイルと履歴を丸ごとコピーする
履歴管理 親と子の履歴は完全に分離される 親リポジトリに子の履歴が統合される
リポジトリサイズ 最小限(参照情報のみ追加)である 子リポジトリの分だけ増加する
クローン時 git clone --recurse-submodules が必要である 通常の git clone のみで良い
更新の取得 ① submoduleディレクトリに移動
git pull
git subtree pull コマンドを使用する
変更の反映 ① submodule内でコミット&プッシュ
② 親リポジトリで更新をコミット
git subtree push コマンドを使用する

Git Submodule

親リポジトリ内に、外部リポジトリの特定のコミットを指し示す「ポインター」を置く方法である。履歴は完全に独立している。

メリット 👍

  • 親リポジトリの履歴がクリーンに保たれる
  • プロジェクトと依存関係の分離が明確である
  • 子リポジトリへの変更の反映が簡単である

デメリット 👎

  • ワークフローが複雑である(追加コマンドが必要)
  • submoduleの更新コミットを忘れやすい
  • Git初心者に優しくない

Git Subtree

外部リポジトリのファイルと履歴を、親リポジトリのサブディレクトリに「コピー」する方法である。一度取り込むと親の一部となる。

メリット 👍

  • 利用者は特別なコマンドが不要でシンプルである
  • .gitmodulesのような管理ファイルが不要である
  • オフラインでも作業可能である

デメリット 👎

  • 親リポジトリの履歴が複雑化・肥大化する
  • 子リポジトリへの変更反映が少し複雑である

どちらを選ぶべきか?

どちらの方法が適しているかは、プロジェクトの要件やチームのスキルセットによって異なる。

Submoduleが適しているケース

  • 外部ライブラリのバージョンを厳密に管理したい場合。
  • コードを直接変更せず、定期的な更新が主である場合。
  • 親プロジェクトの履歴をクリーンに保ちたい場合。

Subtreeが適しているケース

  • プロジェクト利用者の手間を減らしたい場合。
  • 外部コードを頻繁にカスタマイズし、親側で管理したい場合。
  • シンプルなワークフローを優先したい場合。

まとめ

Gitの依存関係管理はプロジェクトの効率に大きく影響する。Submoduleは依存関係の分離を重視する場合に、Subtreeはシンプルさを求める場合に適している。それぞれのメリット・デメリットを理解し、プロジェクトに合った最適な方法を選択することが重要である。