Git
日本語 ▾ トピック ▾ 最新バージョン ▾ 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>

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

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

ただし、トピックブランチが長期間にわたる場合、トピックブランチには多くのこのような「マスターからのマージ」コミットが発生し、開発履歴が不必要に乱雑になります。Linuxカーネルメーリングリストの読者は、サブシステムメンテナが「役に立たないマージ」でいっぱいのブランチからプルするように要求したときに、Linusがそのような頻繁すぎるテストマージについて不平を言ったことを覚えているかもしれません。

代替手段として、テストマージのトピックブランチをクリーンに保つために、テストマージを吹き飛ばし、テストマージ前の先端の上に構築し続けることができます。

	$ 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 rerere は、このコンフリクトを解決するために git rebase によって実行されます。

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

GIT

git[1] スイートの一部

scroll-to-top