51

git worktree最近、次のコマンドを発見しました。

新しい作業ディレクトリは現在のリポジトリにリンクされ、HEAD、インデックスなどの作業ディレクトリ固有のファイルを除くすべてを共有します。

しかし、ドキュメントも示しています

… サブモジュールのサポートは不完全です。スーパープロジェクトを複数回チェックアウトすることはお勧めしません。

何がうまくいかないかについてのさらなる説明なし。

予想される問題について誰かが教えてくれますか? たとえば、サブモジュールに影響を与えない変更に対してのみ、この方法で生成された個別のワークツリーを使用しても問題ありませんか?

4

1 に答える 1

42

コミット a83a66aはそれについて非常に明確です:

git-submodule.sh$GIT_DIR/config、少なくともsubmodule.* part.
ここで、2 つのオプションがあると思います。

  • ワークツリー固有の変数を(共有)に加えて(ワークツリーごとに) config.c読み取り 、新しい場所に保存するように更新するか、$GIT_DIR/config.worktree$GIT_DIR/config
  • または(ワークツリーごとに)から直接git-submodule.sh読み書きするように更新します。submodule.*$GIT_DIR/config.submodule

これらは適切に対処するのに時間がかかります。その間、サブモジュールのコンテキストで複数のワークツリーを使用しないようにユーザーに注意してください。

より一般的には、これらのサブモジュールをどこに配置するのですか?

いくつかのオプションがあります。

  • $SUB外部の別の場所 (おそらく中央の場所) にリポジトリを保持したい場合があり$SUPERます。これは、スーパープロジェクトが別のスーパープロジェクトのサブモジュールであるネストされたサブモジュールにも当てはまります。
  • $SUBすべてのリポジトリを$SUPER/modules(または の他の場所$SUPER)に保持したい場合があります。
  • さらにプッシュして、すべての$SUBリポジトリを$SUPER 個別に保存する代わりにマージすることもできます。ただし、少なくとも ref 名前空間を有効にする必要があります。

このコミットは、コミット df56607に対する回答でした。


git ユーザーの観点からは、サブモジュールをチェックアウトする場所git submodule update --init --recursiveが正確にわからないことを意味します。 それらはすべてのワークツリーで複製されていますか、それともどこかに集中していますか? これはまだ正式に指定されていません。


1年後(そしてgit 2.9で)、clackeはコメントに追加します

混乱は解決されましたが、最適な方法ではありません。
私が見る限り、サブモジュールは正常に動作しますが、各ワークツリーには独自のサブモジュールリポジトリのセット (の下motherrepo.git/worktree/<worktreename>/modules/<submodule>)があるため、大きなサブモジュールがある場合は、深刻なディスク使用量に直面しています。


サブツリー内のサブモジュールを処理するための Git エイリアス:

エイリアスは、グローバルに、または少なくとも関連するすべてのリポジトリに対して定義されgit wtasていることを期待しています。git wta保証は含まれていません。パス名にスペースが含まれていると、お気に入りのペットが痛みを伴う感染症にかかる可能性があります。

サブモジュールが開始されたベアでないレポのようなレポの構造を想定しているため、ベアのレポがある場合は、その設定を模倣する必要があります。(パスではない)という名前のサブモジュールが入りfooます<your-.git-directory>/modules/foo(ではない.../foo.git)。一部のモジュールがリポジトリに存在しない場合、クラッシュすることはありません。スキップするだけです。

改善の余地があります。サブモジュール内のサブモジュールは処理せず、1 レベル下がるだけです。サブモジュール呼び出しを呼び出しに変更するだけでうまくいくかもしれませんが、まだ確認していません。git wtagit wtas

--クラッケ


git worktree move(Git 2.17 以降、2018 年第 2 四半期)も参照してください。


実際、Git 2.21 (2019 年第 1 四半期) より前は、" git worktree remove" と " git worktree move" は、サブモジュールが含まれていると動作を拒否していました。
これは、初期化されていないサブモジュールを無視するように緩和されました

Nguyễn Thái Ngọc Duy ( )によるcommit 00a6d4d (2019 年 1 月 5 日)を参照してください。( 2019 年 1 月 18 日コミット 726f89cJunio C Hamanoによってマージされました)pclouds
gitster

worktree: 初期化されていないサブモジュールを含むワークツリーを (再) 移動できるようにします

初期化されていないサブモジュールには、心配する価値はありません。それらは単なるSHA-1です。
この場合、 " worktree remove" と " " を続けて、スクリプトでチェックアウトしたときのようにworktree move、オプションのサブモジュールが設定されていないリポジトリで複数のワークツリーを引き続き使用できるようにします。sha1collisiondetectiongit.gitdoc-diff

" worktree remove" については、ユーザーがサブモジュール ( *) を初期化し、いくつかのコミット (ただし、プッシュは行わない) を行ってから、それを初期化解除する可能性があることに注意してください。
その時点で、サブモジュールは取り込まれていませんが、貴重な新しいコミットはまだ次の場所にあります。

$GIT_COMMON_DIR/worktrees/<worktree>/modules/<submodule>

ワークツリーの削除を許可しないと、それらのコミットが永久に失われます。
これを防ぐために、新しいディレクトリ チェックが追加されました。

( *) はい、「 」は複数のワークツリー間で共有される をgit submodule追加するsubmodule.*ため、とにかくこれを行うことで彼らは台無しになります。 しかし、それは彼らをさらにねじ込むことを許すという意味ではありません。$GIT_COMMON_DIR/config


Git 2.25 (2020 年第 1 四半期) より前では、構成submodule.recurseオプションが設定されている場合git worktree add、初期化されたサブモジュールを含むスーパープロジェクトでの発行は失敗していました。

Philippe Blain ( )によるcommit 4782cf2ab6 (2019 年 10 月 27 日)を参照してください。( 2019 年 12 月 1 日コミット 726f89cJunio C Hamanoによってマージされました)phil-blain
gitster

worktree: " " に構成addを無視するように教えるsubmodule.recurse

" worktree add" は内部的に " " を呼び出しますが、設定されreset --hardている場合 、初期化されたサブモジュールへの再帰を試みます。これにより、存在しないサブモジュール パスへの cd が試行され、終了します。submodule.recurseresetstart_command

resetin " worktree add" の呼び出しが再帰しないことを確認して、これを修正してください。

以前のバージョンの回避策は、構成を一時的に無効にすることです。

git -c submodule.recurse=0 worktree add ...

Git 2.26 (2020 年第 2 四半期) より前は、初期化されたサブモジュールを含むリポジトリのリンクされたワークツリーでgit checkout --recurse-submodules(またはresetまたはread-tree) を発行すると、サブモジュールの HEAD がメインワークツリーの git リポジトリに誤って移動.gitし、リンクされたワークツリー内のサブモジュールの作業ディレクトリ:

Philippe Blain ( )によるcommit a9472afb63 (2020 年 1 月 21 日)を参照してください。( 2020 年 2 月 5 日コミット ff5134b2Junio C Hamanoによってマージされました)phil-blain
gitster

submodule.c:get_git_dir()の代わりに使用get_git_common_dir()

df56607 (git-common-dir: make " modules/" per-working-directory directory、2014-11-30) 以来、リンクされたワークツリーのサブモジュールは に複製され$GIT_DIR/modulesます$GIT_COMMON_DIR/worktrees/<name>/modules

ただし、worktree updater コマンドがサブモジュールに再帰することを学習したとき、この規則は守られません checkoutでしたresetread-tree具体的には submodule.c::submodule_move_head、6e3c159 で導入された (サブモジュールの更新: submodule_move_head を追加、2017-03-14) および 898c2e6submodule.c::submodule_unset_core_worktreeで (再) 導入された (サブモジュール: 作業ツリーが存在しない場合は core.worktree を設定解除、2018-12-14)get_git_common_dir()の代わりに使用get_git_dir() サブモジュール リポジトリのパスを取得します。

これは、たとえば、git checkout --recurse-submodules <branch>リンクされたワークツリー内の ' ' が を正しくチェックアウト<branch>し、 に記録されたコミットでサブモジュールの HEAD を切り離し、サブモジュールの<branch>作業ツリーを更新することを意味しますが、移動されるサブモジュール HEAD は 内のもの$GIT_COMMON_DIR/modules/<name>/、つまりサブモジュール リポジトリです。メインのスーパープロジェクト作業ツリーの。また、リンクされた作業ツリーのサブモジュール作業ツリー内の gitfile を、 を指すように書き換え$GIT_COMMON_DIR/modules/<name>/ます。これにより、メインのスーパープロジェクトの作業ツリーのサブモジュールの作業ツリーで、正しくない (そして紛らわしい!) 状態が発生します。

さらに、サブモジュールが存在しないコミットに切り替えると、 submodule_unset_core_worktreeが呼び出さcore.wortreeれ、メインのスーパープロジェクト ワークツリー $GIT_COMMON_DIR/modules/<name>/config.

get_git_dir() と の両方submodule_move_headを使用してサブモジュール リポジトリへのパスを作成することで、これを修正しますsubmodule_unset_core_worktree

于 2015-08-07T07:33:52.290 に答える