はい、ベースがあります。 (サイドノート:このコードは数年前に見たときから大きく変わってきましたが、ここでリンクしている私の最近のチェリーピックの答えのいくつかを取り上げました)。
git cherry-pick
とgit revert
は両方とも同じソースファイル(builtin/revert.c
とsequencer.c
)。
あなたが言うように、トリッキーな部分は、マージベースのために何を偽造するかを決めることです。あなたの例では、B
-to-C
の差分を元に戻しています。ここでは、実際のソースコードが(sequencer.c
中)ですが、多少のストリップダウン:
if (opts->action == REPLAY_REVERT) {
base = commit;
base_label = msg.label;
next = parent;
next_label = msg.parent_label;
strbuf_addstr(&msgbuf, "Revert \"");
strbuf_addstr(&msgbuf, msg.subject);
strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit ");
strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
if (commit->parents && commit->parents->next) {
strbuf_addstr(&msgbuf, ", reversing\nchanges made to ");
strbuf_addstr(&msgbuf, oid_to_hex(&parent->object.oid));
}
strbuf_addstr(&msgbuf, ".\n");
} else {
が
const char *p;
base = parent;
base_label = msg.parent_label;
next = commit;
next_label = msg.label;
私たちはここに入力し、commit
ポイントへ[これはチェリーピックケースで、ちょうど万全を期すために含ま] C
およびparent
のデータは、B
のデータを示しています。変数base
への代入はマージベースを設定するもので、next
-vs-base
は何を持ってくるかです。チェリーピックの場合、コミットの親(おそらく-m
で選択)がマージベースです。復帰の場合、コミット自体はマージベースであり、親(おそらく-m
から)は何をもたらすかです。
これとは別のやり方は、これが何年も前に行われた方法であり、最近まで私はこれがまだ使用されていたと考えています。git format-patch
によって生成されたコミットを逆適用することです。構築ベースのバージョンが第2のハッシュ(テキスト差分のA..B
部分からB
部)である。この場合には、:
/*
* This represents a "patch" to a file, both metainfo changes
* such as creation/deletion, filemode and content changes represented
* as a series of fragments.
*/
struct patch {
[snip]
char old_sha1_prefix[41];
char new_sha1_prefix[41];
static void reverse_patches(struct patch *p)
{
[snip]
swap(p->old_sha1_prefix, p->new_sha1_prefix);
reverse_patches
機能、すなわち、一連のパッチにテキストを抽出した後に呼び出され、 index
行からハッシュを抽出するコードの後に、A
とB
部分を古いプレフィックスフィールドと新しいプレフィックスフィールドに入れます。そして、(reverse_patches
の後に)実際に各パッチを適用するとき、gitは保存された古いsha1値と新しいsha1値を使って、3ウェイマージ(git am
が--3way
の場合)を偽造します。したがって、テキストパッチを逆適用すると、sequencer.c
コードの場合と同様に、新しいファイルをベースとして、オリジナルをターゲットとして取得します。