問題の根底にあるのは、git (および一般的にはバージョン管理) によって一連の変更を考えるように強制されることですが、変更セットや機能ブランチ、または関連する変更のまとまりのあるグループと呼ばれるものは、一般的に論理的に連続的ではありません。 . コードが書かれた順序は付随的なものであり、必ずしもコードを読むべき順序とは関係ありません。
私はそれに対する解決策を持っていませんが、履歴を書き換えるプロセスを自動化するのに役立つPerl スクリプトを作成しました。@MikaEloranta さんの Python スクリプトに似ていて、私が書いたときには見たこともありませんでした。
commit --fixup
素晴らしいですが、十分ではありrebase --autosquash
ません。一連のコミットがA-B-C
あり、それらの既存のコミットの 1 つまたは複数に属する作業ツリーにさらにいくつかの変更を書き込む場合、手動で履歴を見て、どの変更がどのコミットに属するかを判断し、それらをステージングして作成する必要があります。fixup!
コミットします。しかし、git はすでに、そのすべてを実行できる十分な情報にアクセスできます。
git diff
スクリプト内のハンクごとgit blame
に、関連する行に最後に触れたコミットを見つけるために使用しgit commit --fixup
、適切なコミットを書き込むように呼び出しますfixup!
。基本的に、以前に手動で行っていたのと同じことを行います。
スクリプトがハンクを単一の明確なコミットに解決できない場合、失敗したハンクとして報告され、そのハンクについては手動のアプローチに戻る必要があります。2 つの別々のコミットで行を 2 回変更した場合、スクリプトはその行の変更をそれらのコミットの最新のものに解決しますが、これは必ずしも正しい解決策ではない可能性があります。「通常の形式」機能ブランチの私見では、2 つの異なるコミットで行を 2 回変更するべきではありません。各コミットは、レビュアーを支援するために、それが触れる行の最終バージョンを提示する必要があります。ただし、バグ修正ブランチで発生する可能性があります。たとえば、foo(bar());
コミット A (名前foo
を に変更fox
) およびコミット B (名前bar
を に変更) によって行が変更される可能性がありますbaz
。
スクリプトが有用であると思われる場合は、お気軽に改善と反復を行ってください。いつの日か、そのような機能がgit
適切に実装される可能性があります。インタラクティブなリベースによってマージの競合が発生した場合に、その競合を解決する方法を理解できるツールがあればいいのにと思います。