Git 2.30 (2021 年第 1 四半期) では、ORT (「表向きは再帰的なツイン」)という新しいマージ戦略が導入されます。
git merge -s ort
これは、Elijah Newrenのこのスレッドから来ています。
今のところ、私はそれを「表向きは再帰的なツイン」、または略して「ort」と呼んでいます。> 最初は、(特に大きなリポジトリの場合) もう少し速くできると思うという事実を除いて、人々はそれと現在の再帰戦略の違いに気付かないはずです。
しかし、現在の設計では処理が難しいいくつかの (確かにまれなケースですが) バグを修正できるはずです。また、マージを行わないか、いくつかの楽しい新機能が可能になると思い$GIT_WORK_TREE
ます$GIT_INDEX_FILE
。
とにかくそれが希望です。
問題:
理想的な世界では、次のことを行う必要があります。
「 」なしで「 」を実行するよう依頼unpack_trees()
します。read-tree -m
-u
すべてのマージ再帰計算をコア内で実行し、現在のインデックスをそのまま維持しながら、結果のインデックスを準備します。
現在のインコア インデックスと結果のインコア インデックスを比較し、作業ツリーで追加、更新、または削除する必要があるパスを確認し、変更が作業ツリーに反映されたときに情報が失われないことを確認します。木;
たとえば、結果は作業ツリーに現在削除できない内容のディレクトリがあるファイルを作成したい場合や、作業ツリー ファイルがローカルで変更されているファイルを削除したい場合などです。
そして最後に
作業ツリーの更新を実行して、結果のコア内インデックスがどのように見えるべきかを一致させます。
結果:
コミット 14c4586 ( 2020 年 11 月 2 日)、コミット fe1a21d (2020 年 10 月 29 日)、コミット 47b1e89、コミット 17e5574 (newren
2020 年 10 月 27 日) を参照してください。
( 2020 年 11 月 18 日、コミット a1f9595でJunio C Hamanoによってマージされました)gitster
merge-ort
: 実装が空の新しいマージ戦略のベアボーン API
署名者: Elijah Newren
これは、新しい統合戦略の始まりです。
いくつかの API の違いがあり、実装にはいくつかの動作の違いがありますが、基本的には の最終的なドロップイン置換として意図されていmerge-recursive.c
ます。
ただし、マージ再帰と並行して存在するように構築されているため、人々がマージ再帰にフォールバックできる一方で、これらの違いが現実の世界でどのように機能するかを調べる十分な時間があります。
(また、安定性を保つために、このプロセス中にマージ再帰を変更することは避けるつもりです。)
ここで注目すべき主な違いは、作業ツリーとインデックスの更新がマージ アルゴリズムと同時に行われるのではなく、別個の後処理ステップであるということです。
新しい API は、マージを繰り返し (リベースやチェリー ピックなどで) 実行できるように設計されており、中間結果ごとに更新するのではなく、最後に 1 回だけインデックスと作業ツリーを更新できます。
また、インデックスまたは作業ツリーを壊すことなく、どちらもインデックスまたは作業ツリーに一致しない 2 つのブランチ間でマージを実行できます。
と:
commit 848a856、commit fd15863、commit 23bef2e、commit c8c35f6、commit c12d1f2、commit 727c75b、commit 489c85f、commit ef52778、commit f06481f (2020 年 10 月 26 日) by Elijah Newren ( newren
)を参照してください。
( 2020 年 11 月 18 日、コミット 66c62eaでJunio C Hamanoによってマージされました)gitster
t6423, t6436
: ダーティ ファイルでの ort 処理の改善に注意してください
署名者: Elijah Newren
unpack_trees()
「再帰的」バックエンドは、ステージングされていない変更がマージによって上書きされるかどうかを確認するために依存していますが、名前のunpack_trees()
変更を理解していません。また、戻ると、作業ツリーとインデックスにすでに多くの更新が書き込まれています。
そのため、「再帰的」には特別な 4 方向のマージを行う必要があり、作業コピーを追加の相違点として扱う必要があり、競合を避けるためにファイルを上書きして新しい場所に移動することを慎重に回避する必要がありました。
対照的に、「ort」バックエンドはメモリ内で完全なマージを行い、後処理ステップとしてインデックスと作業コピーのみを更新します。
途中でダーティ ファイルがある場合は、単純にマージを中止できます。
t6423
: ort バックエンドで改善された競合マーカー ラベルが期待されます
署名者: Elijah Newren
競合マーカーには、REF-OR-COMMIT:FILENAME という形式の追加の注釈が含まれており、コンテンツがどこから来ているかを区別するのに役立ちます。:FILENAME
履歴の両側で同じである場合、その部分は除外されます (したがって、コンテンツ競合のある名前変更のみが保持されます)。注釈のその部分)。
ただし、:FILENAME
merge-recursive の every-codepath-needs-a-copy-of-all-special-case-code 形式が原因で、誤って注釈が省略される場合がありました。
t6404, t6423
: ort バックエンドでの名前変更/削除処理の改善が期待されます
署名者: Elijah Newren
ファイルの名前が変更され、コンテンツの競合がある場合、マージ再帰には、インデックス内の古いファイル名のステージと新しいファイル名のステージがありません。代わりに、古いファイル名に対応するすべてのステージを新しいファイル名に対応する場所にコピーするため、新しいファイル名に対応する 3 つの上位ステージがすべて存在します。
このようにすることで、ユーザーが異なるバージョンにアクセスしやすくなり、競合を解決しやすくなります (古いバージョンと新しいバージョンを手動で ' ' ( man git rm
)する必要はありません)。git add
名前の変更/削除も同様に処理する必要があります。名前を変更するファイルには、1 つだけではなく 2 つの段階が必要です。
マージ再帰を今すぐ不安定にしたくないので、代わりに関連するテストを更新して、 " recursive
" または " ort
" マージ戦略が使用されているかどうかに応じて異なる期待を持たせます。
Git 2.30 (2021 年第 1 四半期)、新しいマージ戦略の準備。
commit 848a856、commit fd15863、commit 23bef2e、commit c8c35f6、commit c12d1f2、commit 727c75b、commit 489c85f、commit ef52778、commit f06481f (2020 年 10 月 26 日) by Elijah Newren ( newren
)を参照してください。
( 2020 年 11 月 18 日、コミット 66c62eaでJunio C Hamanoによってマージされました)gitster
merge tests
: ort でのディレクトリ/ファイルの競合処理の改善が期待されます
署名者: Elijah Newren
merge-recursive.c
unpack_trees()
結果を得るために、実行してから「マイナータッチアップを行う」という考えに基づいて構築されています。
残念なことに、unpack_trees()
は随時更新モードで実行されていたため、merge-recursive.c
それに続き、すぐに評価して随時修正する設計になってしまいました。
ディレクトリ/ファイルの競合のようなものは、インデックス データ構造ではうまく表現できず、処理するために特別な追加コードが必要でした。
しかし、その後、名前変更/削除の競合がディレクトリ/ファイルの競合にも関係している可能性があることが判明したとき、特別なディレクトリ/ファイル競合処理コードを名前変更/削除コードパスにコピーする必要がありました。
...そして、変更/削除、および名前変更/名前変更(1to2)の競合のためにコピーする必要がありました...それでも、まだ一部を見逃していました。
さらに、ファイル/サブモジュールの競合とサブモジュール/ディレクトリの競合もあることが判明したとき、コードベース全体のすべての特殊ケースに特別なサブモジュール処理コードをコピーする必要がありました。
そして、ディレクトリ/ファイルの競合の処理が最適ではないことが判明しました。これは、競合するファイルの内容を格納するために追跡されていないファイルが作成され、誰かが ' git merge --abort
' ( man )または ' git rebase --abort
'を実行してもクリーンアップされないためです。 (男) .
また、インデックス内のディレクトリ/ファイルの競合が原因で、これらのファイルに対応するインデックス エントリを追加または削除しようとすることも困難でした。
しかし、merge-recursive.c
これらを正しく処理するように変更することは非常に困難でした。ディレクトリ/ファイル/サブモジュールの競合をすべて更新する必要がある、似ているが同一ではないコードを持つサイトがコード内に非常に多くあったためです。
私は、単一のコードパスを介して、merge-ort ですべてのディレクトリ/ファイル/サブモジュールの競合処理をプッシュし、追跡されたコンテンツを保存するための追跡されていないファイルを作成しないように懸命に取り組んできました (代替パスで物事を記録しますが、より高次の段階があることを確認します)。索引で)。
Git 2.31 (2021 年第 1 四半期) では、「正しく行われた」マージ バックエンドが出現し始めています。
例:
Junio C Hamano ( )によるcommit 6d37ca2 (2020 年 11 月 11 日)を参照してください。コミット89422D2
、コミットEF2B369 、コミット70912F6 、コミット6681CE5 、コミット9FEFCE6 、 BB470F4のコミット、 EE4012Dのコミット、コミットA9945BB、コミット6A02DD9、コミットメント9884のコミットメントのコミットメントを参照してください。c801717gitster
、コミット e4171b1、コミット 231e2dd、コミット 5b59c3d (2020 年 12 月 13 日) by Elijah Newren ( newren
)。
( 2021 年 1 月 6 日にコミット f9d29da でJunio C Hamanoによってマージされました)gitster
merge-ort
: の実装を追加record_conflicted_index_entries()
署名者: Elijah Newren
の後checkout()
、作業ツリーには適切なコンテンツがあり、インデックスは作業コピーと一致します。
つまり、変更されていない完全にマージされたすべてのファイルには正しいインデックス エントリがありますが、競合するエントリは更新する必要があります。
これを行うには、競合するエントリをループし、パスの既存のインデックス エントリを でマークし、CE_REMOVE
インデックスの最後にパス用にステージングされた新しい高次を追加し (通常のインデックスの並べ替え順序を無視)、ループの最後にCE_REMOVED-marked
キャッシュ エントリを削除し、インデックスを並べ替えます。
Git 2.31 (2021 年第 1 四半期) では、"ORT" マージ戦略に名前変更の検出が追加されました。
commit 6fcccbd、commit f1665e6、commit 35e47e3、commit 2e91ddd、commit 53e88a0、commit af1e56c ( 2020年 12 月 15 日)、commit c2d267d、commit 965a7bc、commit f39d05c、commit e1a124e、 commit 864075eij を参照してください。( 2021 年 1 月 25 日、コミット 2856089でJunio C Hamanoによってマージされました)newren
gitster
例:
署名者: Elijah Newren
通常の名前変更の処理を実装します。
このコードは、 の以下を置き換えますmerge-recurisve.c
。
RENAME_NORMAL
に関連するコードprocess_renames()
- の
RENAME_NORMAL
場合process_entry()
merge-recursive.c
また、このケース (または他の名前変更ケース) では不要になる、複数の異なる名前変更ケース用の共有コードがいくつかあります。
handle_rename_normal()
setup_rename_conflict_info()
4 つの個別のコードパスを 1 つに統合することは、設計の変更によって可能になりました。名前変更以外のすべての競合タイプ (ディレクトリ/ファイル、変更/削除など) を直交的に処理できるようにエントリをprocess_renames()
微調整します。conflict_info
opt->priv->paths
process_entry()
これは、ある種の競合タイプの組み合わせの特別な実装を見逃す可能性がはるかに低いことを意味します ( 66c62ea ("Merge branch 'en/merge-tests'", 2020-11-18, Git v2.30.0)によってもたらされたコミットを参照) -rc0 --バッチ #6に記載されているマージ)、特にコミット ef52778 (「マージ テスト: ort でのディレクトリ/ファイル競合処理の改善を期待」、2020-10-26、Git v2.30.0-rc0 --バッチ #に記載されているマージ6)詳細について)。
これは、ワークツリー/インデックスの更新を関数内で直角に処理できるようにすることと合わせて、merge_switch_to_result()
さまざまな特別な名前変更のケースのコードを劇的に簡素化します。
(公平を期すために、通常の名前変更を処理するためのコードは、以前はそれほど複雑ではありませんでしたが、今でもはるかに単純です。)
また、Git 2.31 (2021 年第 1 四半期) でも引き続き、Git 2.31 (2021 年第 1 四半期) では、oRT マージ戦略はマージ競合のサポートをさらに学習します。
commit 4ef88fc、commit 4204cd5、commit 70f19c7、commit c73cda7、commit f591c47、commit 62fdec1、commit 991bbdc、commit 5a1a1e8、commit 23366d2、commit 0ccfa4e (01 Jan 2021) by Elijah Newren ( newren
)を参照してください。
( 2021 年 2 月 5 日にコミット b65b9ffでJunio C Hamanoによってマージされました)gitster
merge-ort
: 同じパスにある異なる種類のファイルの処理を追加します
署名者: Elijah Newren
次のタイプの衝突を明示的に考慮する処理を追加します。
- ファイル/サブモジュール
- ファイル/シンボリックリンク
- submodule/symlink> それらを競合として同じパスに残すと、ユーザーが解決するのが難しくなるため、一方または両方を脇に移動して、それぞれが独自のパスを取得できるようにします。
再帰処理 (すなわち
call_depth > 0
) の場合、変更/削除の競合、バイナリ ファイル、競合するサブモジュール値などの場合と同様に、2 つのマージ ベースのマージ ベースをマージ結果として使用できることに注意してください。