git还会使用3路合并吗?

编程入门 行业动态 更新时间:2024-10-24 04:37:40
本文介绍了git还会使用3路合并吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

运行 git revert 时,可能会发生冲突。 git是否依赖于3-way-merge,正如 p>

回复的合并基础是什么?在使用git和meld进行交互式重新绑定的三种合并方式中的三个文件是什么?这很清楚,但很难想象这种方式会被还原。

A - B - C - D - C ^ -1

(如果我想在最后还原 C )。 >

是的,有一个基地。 (注意:自从我多年前看了这段代码后,这段代码已经发生了很大的变化,我选择了一些关于我最近挑选的答案,你已经链接到这里了。)

git cherry-pick 和 git revert 由相同的源文件( builtin / revert.c 和 sequencer.c )。

说,棘手的部分是决定什么假合并基地。在你的例子中,我们正在撤消 B --to - C diffs。下面是实际的源代码(在 sequencer.c 中),稍微剥离了一下:

if(opts-> action == REPLAY_REVERT){ase = commit; base_label = msg.label; next = parent; next_label = msg.parent_label; strbuf_addstr(& msgbuf,Revert \); strbuf_addstr(& msgbuf,msg.subject); strbuf_addstr(& msgbuf,\\\\ \\\This恢复提交); strbuf_addstr(& msgbuf,oid_to_hex(& commit-> object.oid)); if(commit-> parents&& commit-> parents-> next){ strbuf_addstr(& msgbuf,reverseing \\\changes made to) ; strbuf_addstr(& msgbuf,oid_to_hex(& parent-> object.oid)); } strbuf_addstr(& msgbuf,.\); }其他{

[这是樱桃挑选的案例,仅供参考)

const char * p; base = parent; base_label = msg.parent_label; next = commit; next_label = msg.label;

当我们在这里输入时, commit 指向 C 和父母的数据指向 B 的数据。对变量 base 的赋值是设置合并基的内容,并且 next -vs - base 是带入的内容。对于樱桃挑选,提交的父项(可能通过 -m 选择)是合并基础。为了回复,提交本身就是合并基础,并且父母(可能从 -m )可以带入。

获得相同效果的另一种方式(多年前是这样做的,直到最近,我还认为它仍在使用中)是反向应用由 git format-patch 。在这种情况下,构建的基本版本是第二个散列(来自 A..B 部分的 B 部分)一个文本差异):

/ * *这表示一个文件的补丁,元信息变化为 *如创建/删除,文件模式和内容更改以 *表示为一系列片段。 * / 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 文本转换为一系列补丁,即在从索引行中提取哈希的代码之后,将 A 和 B 部分放入旧的和新的前缀字段中。然后(在 reverse_patches 之后),当实际应用每个补丁时,git使用保存的旧的和新的sha1值来伪造3路合并(如果 git am 给出 - 3way )。因此,通过反向应用文本补丁,我们将获取新文件作为基准,原始文件作为目标,就像 sequencer.c 代码一样。

When I run git revert, it can happen, that a conflict occurs. Does git rely on the 3-way-merge, as it is depicted in the question merge internals (cf. table below) also for revert?

What is the merge base for a revert? In What are the three files in a 3-way merge for interactive rebasing using git and meld? it is quite clear, but its hard to imagine this for a revert.

A - B - C - D - C^-1

(If I want to revert C at the end.)

解决方案

Yes, there is a base. (Side note: this code has changed a lot since I looked at it years ago. I picked up some of this for my recent cherry-pick answer, which you have linked here.)

Both git cherry-pick and git revert are implemented by the same source files (builtin/revert.c and sequencer.c).

As you say, the tricky part is deciding what to fake up for the merge base. In your example, we're undoing the B-to-C diffs. Here's the actual source code (in sequencer.c), stripped down somewhat:

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 {

[this is the cherry-pick case, included just for completeness]

const char *p; base = parent; base_label = msg.parent_label; next = commit; next_label = msg.label;

When we enter here, commit points to data for C and parent points to data for B. The assignment to variable base is what sets the merge base, and next-vs-base is what to bring in. For cherry-pick, the commit's parent (possibly chosen via -m) is the merge base. For revert, the commit itself is the merge base and the parent (again possibly from -m) is what-to-bring-in.

The other way to get the same effect (which is how this was done many years ago, and until recently, I thought this was still being used) is to reverse-apply a commit as produced by git format-patch. In this case, the constructed base version is the second hash (the B part from the A..B part of a textual diff):

/* * 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);

The reverse_patches function is called after extracting the text into a series of patches, i.e., after the code that extracts the hashes from the index lines, putting the A and B parts into the old and new prefix fields. Then (after reverse_patches), when actually applying each patch, git uses the saved old and new sha1 values to fake a 3-way merge (if git am is given --3way). So by reverse-applying a text patch, we would get the new file as the base and the original as the target, just as with the sequencer.c code.

更多推荐

git还会使用3路合并吗?

本文发布于:2023-11-06 01:27:40,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:还会   git

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!