whi*_*cko 1 git merge revert git-revert 3-way-merge
当我运行时git revert
,可能会发生冲突。git 是否依赖于 3 路合并,如问题合并内部(参见下表)中所述,也适用于revert
?
恢复的合并基础是什么?在使用 git 和 meld 进行交互式变基的 3 向合并中的三个文件是什么?这很清楚,但很难想象这是一个还原。
A - B - C - D - C^-1
Run Code Online (Sandbox Code Playgroud)
(如果我想C
在最后恢复。)
是的,有一个基地。(旁注:自从我几年前查看以来,此代码已发生了很大变化。我为最近的樱桃选择答案挑选了其中的一些,您已将其链接到此处。)
双方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 {
Run Code Online (Sandbox Code Playgroud)
[这是樱桃挑选的情况,包括在内只是为了完整性]
const char *p;
base = parent;
base_label = msg.parent_label;
next = commit;
next_label = msg.label;
Run Code Online (Sandbox Code Playgroud)
当我们在这里输入时,commit
指向data forC
和parent
指向data for B
。对变量的赋值base
是设置合并基础的内容,而next
-vs-base
是要引入的内容。对于cherry-pick,提交的父级(可能通过 选择-m
)是合并基础。对于还原,提交本身是合并基础,而父项(同样可能来自-m
)是要引入的内容。
获得相同效果的另一种方法(多年前就是这样做的,直到最近,我认为这仍然在使用)是反向应用由git format-patch
. 在这种情况下,构造的基本版本是第二个哈希(B
来自A..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);
Run Code Online (Sandbox Code Playgroud)
reverse_patches
在将文本提取到一系列补丁中之后调用该函数,即在从index
行中提取散列的代码之后,将A
和B
部分放入旧的和新的前缀字段中。然后(之后reverse_patches
),当实际应用每个补丁时,git 使用保存的旧的和新的 sha1 值来伪造 3 路合并(如果git am
给出--3way
)。因此,通过反向应用文本补丁,我们将获得新文件作为基础,原始文件作为目标,就像sequencer.c
代码一样。
归档时间: |
|
查看次数: |
324 次 |
最近记录: |