サブツリー
サブツリーは、別のリポジトリを自分のディレクトリの中にコピーします。そのあとファイルは
本当にそこにあります。ふつうの git clone で手に入り、git checkout はほかの
ファイルと同じように動かし、そのディレクトリがよそから来たことを誰も知らなくて構い
ません。
サブモジュール との違いはまさにそこです。サブモジュールはポインタしか
保存せず、--recurse-submodules と、自前のチェックアウトと、把握し続けるべき自前の
detached HEAD を必要とします。
⌘K → サブツリー。

誰も言わない落とし穴
git はサブツリーのマニフェストを記録しません。 サブモジュールには .gitmodules
があり、url とパスがすべて並んでいます。サブツリーには何もありません。取り込みを行った
コミットに付いた git-subtree-dir: トレーラーだけです。
つまりリポジトリはサブツリーを含みながら、それがどこから来たのかを知る手立てを与えて くれない、ということが起こり得ます。Gitcito はできる範囲のことをします。
- 一覧は、そのトレーラーを読むことで履歴から発見されます。誰がどんなツールで追加した サブツリーでも現れます。
- 取得元のリポジトリと ref は Gitcito が、このリポジトリの git 設定に覚えて おきます。履歴から発見されたサブツリーは、最初その欄が空です。一度埋めれば、そこ から先はプルもプッシュも動きます。
覚えられた値は .git/config の gitcito.subtree.* にあるので、リポジトリには
残りますがクローンには付いていきません。忘れる はそれを消すだけで、ほかには
何も触れません。
追加する
| 項目 | 意味 |
|---|---|
| ディレクトリ | 置き場所。例: vendor/parser。まだ存在していてはいけません |
| 取得元リポジトリ | URL、またはディスク上のパス |
| ブランチまたはタグ | 取り込む対象 |
| スカッシュ | 履歴すべてではなく、1 コミットとして取り込む |
理由がない限り スカッシュはオンのままに。オフにすると、そのライブラリのすべての
コミットが自分のログに永久に織り込まれ、git log は自分のプロジェクトの話ではなく
なります。
付き合っていく
| 操作 | 実行されるもの |
|---|---|
| プル | git subtree pull — 上流の変更が、そのディレクトリへのマージとして届きます |
| プッシュ | git subtree push — そのディレクトリ配下のローカルの変更を取得元へ戻します |
| スプリット | git subtree split -b <branch> — そのディレクトリ自身の履歴を、ファイルをルートに置いたブランチとして取り出します |
覚えておく価値があるのは スプリット です。取り込んだディレクトリを、単体の リポジトリの履歴へ戻します。サブツリーがサブツリーであることをやめる方法が、これです。
知っておくべき制限
- プッシュは遅いです。 毎回そのディレクトリの履歴をゼロから計算し直します。大きな リポジトリでは一瞬ではなく数秒から数分かかり、Gitcito にできるのは待つことだけです。
- プルはマージです。 ほかのマージと同じようにコンフリクトし得るので、 リゾルバ に着地します。
git subtreeは contrib のスクリプト であり、git の組み込みコマンドではありま せん。切り詰められた git のインストールには入っていないことがあります。Gitcito は 「'subtree' is not a git command」をそのまま渡すのではなく、はっきりそう伝えます。- スカッシュした履歴はあとから戻せません。 それらのコミットは、そもそも取り込ま れていないからです。
- Gitcito はサブモジュールをサブツリーに変換しませんし、その逆もしません。
関連項目: マージとリベース · UI 付きの配管コマンド