1

私は今ではかなりの歴史を持つ git リポジトリを持っています。初期のコミットでいくつかの変更を加えようとしていたところ、奇妙な競合が見つかりました。

git rebase COMMIT^ を実行して初期のものの 1 つを選択すると、すべてのコミットを選択するなど、リストに何も触れずに、まだモーションを通過し、すべてのコミットをリプレイし、説明できないことがわかりました。私には、いくつか失敗します。

これはどのように可能ですか?すべてのコミットが選択されたために履歴が変更されていない場合、どうして失敗するのでしょうか?

4

1 に答える 1

3

リベースは、各差分の変更を「再生」し、新しいコミットを作成することによって機能します (古いコミットはそのまま残りますが、非表示になり、最終的に期限切れになります)。コミットを「再生」する方法は、 としてより直接的に利用できるgit cherry-pickため、最初にこれについて説明します。

チェリーピックを行うには、コミットで行われた変更を抽出する必要があります。結果の差分は、差分に含まれるコンテキストを使用して、他の (異なる) コミットに適用 (「パッチ」) できます。ただし、コミットは変更として保存されないため、<a href="https://stackoverflow.com/a/8198276/1256452">各コミットはソースの完全な「スナップショット」であり、cherry-pick で計算する必要があります。コミットによって提供される変更。これは、コミットをその親コミットと比較することによって行われます。

これは線形履歴ではうまく機能しますが、マージがある場合はうまくいきません。特に、マージ コミットには、定義上、少なくとも 2 つの親があります (3 つ以上の親を持つマージは珍しいですが、git では許可されています)。2 つの親を持つコミットがあり、diff を作成するときにどちらgit cherry-pickの親を考慮するかを選択する明白な方法がない場合、単純に不満を持って停止します。-mオプションを使用して、マージコミットをチェリーピックするときに気になる親を提供できます。

rebase コマンドは別のアプローチを採用しています。デフォルトでは、マージが不要であることを期待して、マージを完全に排除します。マージが重要な場合 (明らかにここでそうであるように)、これはチェリーピックの失敗につながります。

rebase コマンドには-p(aka --preserve-merges) オプションがあります。この場合、マージを維持しようとします。この特定のケースでは、元のベース コミットに対してコミット シーケンスを再生している場合、マージを維持するリベースが機能するはずです。

詳細については、ドキュメントを参照してください。

于 2015-09-27T19:20:46.287 に答える