我合并了两个分支:
master
向文件config_dev.yml
添加了行report
没有碰到它(因此该文件没有冲突)。我将report
合并到master
中,结果是:线条消失了。
1 2 3 4 5 6 7 8 9 10
master: ---O--O--O-----O--O-----O--O--O----
report: -------\----O--------O-------/
changes on master__^ ^__merge that silently removes changes
为什么?我可以信任git merge
吗?
可能相关的其他信息:
master
上的提交3开始,被“合并”(实际上是一个空白合并,“仅我的”)到{{1 }}提交7 答案 0 :(得分:0)
这并不是真正的答案(应该是评论),但是它需要格式化并且不适合评论空间。取而代之的是,这是有关如何找到答案的说明,或者至少是提出正确的输入内容以导致答案的方法。
运行时:
git checkout master
git merge report
Git首先找到合并基础提交。很少(这里可能不是这种情况),Git会发现多个合并基础提交,但我们将确保不是这种情况。
可以说这次合并会出错,但是-重要的-还没有完成。如果已经完成,那么我们需要一个技巧或一个尚未完成的单独存储库:两者就足够了。诀窍是创建一个 new 分支(未命名为master
),该分支指向master
在合并之前将指向的提交:
git checkout -b test-the-merge <hash-ID>
(我们稍后可以丢弃此分支。或者,使用另一种技巧,我们甚至根本无法创建该分支,但是为简单起见,使用测试分支更加容易。)
现在我们处于尚未完成合并的状态,我们首先运行:
git merge-base --all HEAD report
理想情况下,这会产生一个哈希ID。如果它产生个以上的哈希ID,那么我们将遇到一种罕见的情况,即存在多个合并基数,并且我们需要省略一个过程,因为该过程很长,而且很无聊。 :-)
现在,我们知道了一个作为合并基础的哈希ID,这是当Git进行合并时我们如何看到Git会看到的内容:
git diff --find-renames <hash> HEAD # what does Git think *we* changed?
git diff --find-renames <hash> report # what does Git think *they* changed?
您可能希望将这两个git diff
发送到文件,以便您可以随意和/或并行阅读它们。如果有很多差异可以正确合并,而您只想关注无法正确合并的特定文件,那么您也可以将输出限制为特定文件。
请注意,git diff
发现的不一定是某人所做的更改。 git diff
发现的是产生相同效果的最小指令集。通常这已经足够了。例如,假设在左侧提交(由哈希ID指定的合并基数)和右侧提交之间,有人删除了 second 行,即a的第一个单词the
。多余的段落:
Paris in
the
the
spring
然后Git选择产生指令:删除第二个the
(第三行)。
有关系吗?可能不是,但有时确实如此。如果左侧和右侧显示为:
some vaguely C like code {
with redundant stuff
}
more vaguely C like code {
with redundant stuff
}
和:
some vaguely C like code {
with redundant stuff
}
still vaguely C like code {
with redundant stuff
}
more vaguely C like code {
with redundant stuff
}
和Git错误地在右花括号上同步,并产生语法无效的diff?好吧,即使通常仍然可以使用,但有时会产生不适当的冲突。在极少数情况下(尽管确实会发生,但很难说明),由于Git进行了最少的编辑,您可能 发生了应该发生的冲突在语法上是正确的,但在语义上是错误的。
无论如何,在生成了两个差异列表之后,Git现在要做的是提出合并后的源文件集。为此,Git从所有文件的 merge base 版本开始。然后:
对于您更改过的每个文件,或它们都更改了...
您更改文件了吗?他们没有更改文件吗?如果是这样,请获取您的文件。
他们是否更改了文件,而您没有更改?如果是这样,请获取其文件。
否则,您都更改了文件。尝试组合更改,逐行通过差异。无论您在哪里添加了几行,都请添加几行。无论他们在哪里添加一些内容,都请添加他们的行。无论您或他们在哪里删除了几行,都请删除。如果您都对完全相同的行进行了完全相同的更改,请复制一份更改。如果您对同一行或邻接(相互触摸)或碰到文件末尾的行进行了不同的更改,请声明合并冲突。
对于您或它们已被完全删除,创建为全新文件或重命名的文件,请执行适当的操作。 (恰恰是适当的意味着什么变得复杂,在这里似乎不是您的情况,所以我不再赘述。)
现在,Git已将所有内容尽力地结合在一起:
--no-commit
),或者如果Git进行了合并提交,或者如果它停止并允许您进行合并,并且您确实进行了合并,则合并提交会将当前分支的旧提示提交作为其第一父提交,新提示提交本身就是合并提交,并合并提交具有另一个分支的技巧提交作为其第二父级。也就是说,在master
或test-the-merge
(无论我们在哪个分支)上合并之后,我们有:
git rev-parse <branch>^1 => hash ID of the previous branch tip
git rev-parse <branch>^2 => same hash ID as git rev-parse report
您可以查看两个输入,这是从三个提交(合并基础HEAD
和它们的/尖端report
)得出的两个差异中看到的,Git看到了什么,将解释为什么Git进行了合并。
在任何情况下,这都是{em> git merge
所做的事情:它找到一个合并基础,进行两个比较,然后组合这些差异并将组合的差异应用于合并基础合并结果。 (当然,这会忽略所有特殊情况,例如由于各种原因未进行实际合并:-s ours
,快速前进,或不相关的历史记录或合并冲突等。)差异本质上是面向行的并且无法重建某人真正做到的事情:他们只会产生一组指令,这些指令将带有相同的最终文本。结合使用这些指令通常可以与大多数编程语言一起使用,但是绝对不是完美的。
如果该过程适用于您的文件,则可以信任它。如果该过程不能用于您的文件,则您不能信任它,您必须仔细检查并在需要时进行更正,每次合并。