当我运行git revert时,可能会发生冲突。git是否依赖于问题merge internals中所描述的三向合并(参见下表)也适用于revert

恢复的合并基础是什么?在What are the three files in a 3-way merge for interactive rebasing using git and meld?中,这一点非常清楚,但很难想象这是一种还原。
A - B - C - D - C^-1(如果我想在最后恢复C。)
发布于 2016-05-11 08:34:23
是的,有一个基地。(旁注:这段代码自从我几年前看过以来已经发生了很大的变化。我在最近的精挑细选的答案中选择了其中的一些,您已经在这里链接到了。)
git cherry-pick和git revert都由相同的源文件(builtin/revert.c和sequencer.c)实现。
正如您所说,棘手的部分是决定为合并基础伪装什么。在您的示例中,我们将撤消B到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用于引入。对于cherry-pick,提交的父级(可能通过-m选择)是合并基础。对于revert,提交本身是合并基,而父对象(也可能来自-m)是引入的内容。
获得相同效果的另一种方法(这是很多年前的方法,直到最近,我还认为这种方法仍然在使用)是反向应用git format-patch产生的提交。在这种情况下,构造的基础版本是第二个散列(文本diff的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值来伪造三向合并(如果git am被赋予--3way)。因此,通过反向应用文本补丁,我们将获得新文件作为基础,原始文件作为目标,就像sequencer.c代码一样。
https://stackoverflow.com/questions/37150543
复制相似问题