日本語 ▾ トピック ▾ 最新版 ▾ git-rerere は 2.39.0 で最終更新されました。

名前

git-rerere - 競合したマージの記録された解決策を再利用する

概要

git rerere [clear | forget <pathspec>…​ | diff | status | remaining | gc]

説明

比較的寿命の長いトピックブランチを使用するワークフローでは、開発者は、トピックブランチが完了するまで(「リリース」ブランチにマージされるか、アップストリームに送信されて受け入れられるか)、同じ競合を何度も解決する必要がある場合があります。

このコマンドは、競合した自動マージの結果と、最初の手動マージでの対応する手動解決の結果を記録し、以前に記録された手動解決を対応する自動マージの結果に適用することで、開発者がこのプロセスを支援します。

このコマンドを有効にするには、設定変数 rerere.enabled を設定する必要があります。

コマンド

通常、git rerere は引数なしで、またはユーザーの介入なしで実行されます。ただし、その動作状態とやり取りできるいくつかのコマンドがあります。

clear

マージ解決を中止する場合に rerere が使用するメタデータをリセットします。git am [--skip|--abort] または git rebase [--skip|--abort] を呼び出すと、このコマンドが自動的に呼び出されます。

forget <pathspec>

rerere が <pathspec> の現在の競合に対して記録した競合解決をリセットします。

diff

解決の現在の状態の差分を表示します。ユーザーが競合を解決している間に何が変更されたかを追跡するのに役立ちます。追加の引数は、PATH にインストールされているシステム diff コマンドに直接渡されます。

status

rerere がマージ解決を記録する、競合のあるパスを表示します。

remaining

rerere によって自動解決されていない競合のあるパスを表示します。これには、競合するサブモジュールなど、rerere が解決を追跡できないパスが含まれます。

gc

かなり前に発生した競合したマージの記録を整理します。デフォルトでは、15日以上前の未解決の競合と60日以上前の解決済みの競合は整理されます。これらのデフォルトは、それぞれ gc.rerereUnresolved および gc.rerereResolved 設定変数によって制御されます。

考察

トピックブランチがマスターブランチ (またはアップストリーム) と重なる領域を変更し、それがトピックブランチがフォークした後にマスターブランチ (またはアップストリーム) が触れた場合、トピックブランチがアップストリームにプッシュされる準備ができていなくても、最新のマスターブランチでテストしたい場合があります。

              o---*---o topic
             /
    o---o---o---*---o---o master

このようなテストには、マスターブランチとトピックブランチを何らかの方法でマージする必要があります。その1つの方法は、マスターブランチをトピックブランチにプルすることです。

	$ git switch topic
	$ git merge master

              o---*---o---+ topic
             /           /
    o---o---o---*---o---o master

* でマークされたコミットは、同じファイルの同じ領域に触れています。 + でマークされたコミットを作成するときに競合を解決する必要があります。次に、結果をテストして、進行中の作業が最新のマスターに含まれるものとまだ機能することを確認できます。

このテストマージの後、トピックでの作業を継続するには2つの方法があります。最も簡単なのは、テストマージコミット + の上に構築し、トピックブランチでの作業が最終的に完了したときに、トピックブランチをマスターにプルするか、アップストリームにあなたからプルするように依頼することです。ただし、その時までに、マスターまたはアップストリームはテストマージ + 以降に進んでいる可能性があり、その場合、最終的なコミットグラフは次のようになります。

	$ git switch topic
	$ git merge master
	$ ... work on both topic and master branches
	$ git switch master
	$ git merge topic

              o---*---o---+---o---o topic
             /           /         \
    o---o---o---*---o---o---o---o---+ master

しかし、トピックブランチが長期間使用されると、その上に多くの「masterからのマージ」コミットができてしまい、開発履歴が不必要にごちゃごちゃになります。Linuxカーネルのメーリングリストの読者なら、サブシステムのメンテナが「不要なマージ」でいっぱいのブランチからプルを要求したときに、リーナスがそのような頻繁すぎるテストマージについて不平を言っていたのを覚えているかもしれません。

代替案として、テストマージでトピックブランチをきれいに保つために、テストマージを破棄し、テストマージ前の先端の上に構築を続けることができます。

	$ git switch topic
	$ git merge master
	$ git reset --hard HEAD^ ;# rewind the test merge
	$ ... work on both topic and master branches
	$ git switch master
	$ git merge topic

              o---*---o-------o---o topic
             /                     \
    o---o---o---*---o---o---o---o---+ master

これにより、トピックブランチが最終的に準備され、マスターブランチにマージされたときに、マージコミットが1つだけ残ります。このマージでは、* でマークされたコミットによって導入された競合を解決する必要があります。しかし、この競合は、破棄したテストマージを作成したときに解決した競合とよく同じです。git rerere は、以前の手動解決からの情報を使用して、この最終的な競合したマージを解決するのに役立ちます。

競合した自動マージの直後に git rerere コマンドを実行すると、競合した作業ツリーファイルが記録され、通常の競合マーカー <<<<<<<=======、および >>>>>>> が含まれます。その後、競合の解決が完了した後、再度 git rerere を実行すると、これらのファイルの解決された状態が記録されます。マスターからトピックブランチへのテストマージを作成したときにこれを行ったとします。

次回、同じ競合した自動マージを見た後、git rerere を実行すると、以前の競合した自動マージ、以前の手動解決、および現在の競合した自動マージの3者間マージが実行されます。この3者間マージがクリーンに解決されると、結果は作業ツリーファイルに書き出されるため、手動で解決する必要はありません。git rerere はインデックスファイルをそのままにしておくため、git diff (または git diff -c) と git add で最終的な健全性チェックを行う必要があることに注意してください。

利便性のために、git merge は自動マージが失敗して終了するとすぐに git rerere を呼び出し、git rerere は新しい競合の場合は手動解決を記録し、そうでない場合は以前の手動解決を再利用します。git commit もマージ結果をコミットするときに git rerere を呼び出します。これは、あなた自身が特別なことをする必要がないことを意味します(rerere.enabled 設定変数を有効にする以外は)。

私たちの例では、テストマージを行うと、手動解決が記録され、記録された解決が引き続き適用可能である限り、後で更新されたマスターとトピックブランチで実際のマージを行うときに再利用されます。

git rerere が記録する情報は、git rebase を実行するときにも使用されます。テストマージを破棄し、トピックブランチでの開発を続けた後

              o---*---o-------o---o topic
             /
    o---o---o---*---o---o---o---o   master

	$ git rebase master topic

				  o---*---o-------o---o topic
				 /
    o---o---o---*---o---o---o---o   master

トピックがアップストリームに送信される準備が整う前に最新の状態にするために、git rebase master topic を実行できます。これにより、3者間マージに戻り、以前に解決したテストマージと同じ方法で競合します。git rereregit rebase によって実行され、この競合を解決するのに役立ちます。

[注] git rerere はファイルの競合マーカーに依存して競合を検出します。ファイルにすでに競合マーカーのある行と同じように見える行が含まれている場合、git rerere は競合解決を記録できない場合があります。これを回避するには、gitattributes[5]conflict-marker-size 設定を使用できます。

GIT

git[1]スイートの一部

scroll-to-top