このテキストは元々、git diff コマンドの動作に関する議論の脚注でした。
私はよく、面倒な開発履歴を書き換えながら、[HEAD以外に対するdiffの実行]をしていることに気づきます。 例えば、どこがどうなっているのかよくわからないまま作業を始めてしまい、以下のような履歴になってしまったとします:
"master"
o---o
\ "topic"
o---o---o---o---o---o
この時点で、「topic」には私が欲しいと思っているものが含まれていますが、完全に独立していることが判明した2つの概念が含まれています。 そして、多くの場合、あるトピックの構成要素が他よりも大きくなっています。 2つ以上のトピックを含んでいることもあります。
この混乱をより扱いやすくするために、最初に「diff master..topic」を実行して、変更を1つのパッチに抽出し、そこから断片を選択して論理的に自己完結型のユニットを取得し、 master 上に構築を開始します:
$ git diff master..topic >P.diff
$ git checkout -b topicA master
... pick and apply pieces from P.diff to build
... commits on topicA branch.
o---o---o
/ "topicA"
o---o"master"
\ "topic"
o---o---o---o---o---o
「topicA」のHEADで各コミットを実行する前に、影響を受けるパスの update-index の前に「diff HEAD」を実行するか、その後に「diff --cached HEAD」を実行します。 また、「diff --cached master」を実行して、変更が「topicA」に関連するものだけであることを確認します。 通常、私は小さなトピックから順番にこれを行います。
その後、元の「topic」の残りの部分を実行しますが、そのために、最初に使用した「master」と「topic」を比較して抽出したパッチファイルからは開始しません。 いまだ「topicA」にいて、そこで、「diff topic」を抽出し、それを使用してもう一つのトピックを再構築します:
$ git diff -R topic >P.diff ;# --cached also would work fine
$ git checkout -b topicB master
... pick and apply pieces from P.diff to build
... commits on topicB branch.
"topicB"
o---o---o---o---o
/
/o---o---o
|/ "topicA"
o---o"master"
\ "topic"
o---o---o---o---o---o
完了したら、「topicA」と「topicB」の間で擬似的にマージ(pretend-merge)をして、何も見逃していないことを確認します:
$ git pull . topicA ;# merge it into current "topicB"
$ git diff topic
"topicB"
o---o---o---o---o---* (pretend merge)
/ /
/o---o---o----------'
|/ "topicA"
o---o"master"
\ "topic"
o---o---o---o---o---o
最後のdiffは、クリーンアップするがらくた以外のものは表示しない方がよいでしょう。 そして、最後に、あなたは物事をクリーンアップすることができます:
$ git branch -D topic
$ git reset --hard HEAD^ ;# nuke pretend merge
"topicB"
o---o---o---o---o
/
/o---o---o
|/ "topicA"
o---o"master"