首页 > 解决方案 > 什么时候 2 个补丁在 git 中被认为是相等的?

问题描述

当我阅读git rebase doc时出现了我的问题,即

如果上游分支已经包含您所做的更改(例如,因为您邮寄了一个应用于上游的补丁),那么该提交将被跳过。例如,在以下历史记录上运行 git rebase master(其中 A' 和 A 引入了相同的更改集,但具有不同的提交者信息):

      A---B---C topic
     /
D---E---A'---F master will result in:

               B'---C' topic
              /
D---E---A'---F master

一种方法是使用git patch-id查看补丁 ID ,但这不是我想要的。

让我有2个分支。主题和大师,我只更改其中的一个文件。

Inserted 2  ->  T2     M2 <--  Inserted 2 in new line
                |      |       
Inserted 1  ->  T1     M3 <-- Inserted 3 in new line
                  \   /
                   \ /
                    * <--  Contents similar here 

2现在在 T2 和 M2 ,虽然我们在文件的两个版本中添加了相同的新行(发现这是 git patch-id),但补丁并不被认为是相同的。这个发现让我很惊讶。我认为如果将同一行上的相同内容应用于文件的 2 个不同版本,则补丁将是相同的。

这让我觉得那个补丁,因此也取决于之前的提交,我在哪里应用补丁。所以,当我们说 (patch1 on some branch) = (patch2 on some other branch) ,那么他们的祖先也需要相同吗?如果是,我们可以递归地应用它,两个分支将是相同的,这是不合逻辑的。

所以,我的问题是,我们什么时候说 2 个补丁相等(不考虑补丁 ID)?

使用此脚本在本地重现上述内容:

#!/bin/bash

git init .
echo "10" >> 1.txt && git add . && git commit -m "1"

# Add 2 commits to master
echo "3" >> 1.txt && git commit -am "m3"
echo "2" >> 1.txt && git commit -am "m2"


#checkout topic branch
git checkout -b topic HEAD~2
echo "1" >> 1.txt && git commit -am "t1"
echo "2" >> 1.txt && git commit -am "t2"

#Show graph
git log --oneline --all --decorate --graph

标签: git

解决方案


那么,当我们说 (patch1 on some branch) = (patch2 on some other branch) 时,他们的祖先也需要相同吗?

不为git rebase,不。Rebase 使用与 相同的计算git patch-id,这纯粹是对精简(行号和空格删除)差异文本进行散列处理的结果。

git rev-list命令也执行此操作。查看它的--left-right--right-only--cherry-mark--cherry-pick选项,它们必须与对称差分三点表示法提交选择器一起使用。

事实上,git rebase用来git rev-list做工作。在过去,git rebase主要是 shell 脚本,很容易看出这是如何完成的。现在它都是作为 C 代码构建的,所以它没有运行,而是编译git rev-list了相同的位。git rev-list

...如果同一行上的内容相同,则认为补丁将相同...

不,行号被删除。这是故意的:例如,一个补丁可能就像用一个通过的调用替换一个通过的调用一样简单falsetrue对于 Git 来说是:

-    foo(false)
+    foo(true)

(在 的情况下git diff,一些周围的上下文 - 尚不清楚补丁 ID 是否包含上下文,但我会假设它包含)。假设上游接受了此修复,而您正在处理可能与修复相关或不相关的功能......但是上游,第 42 行对 的调用foo现在在第 47 行,因为有五个不相关的行被添加到远高于这一点?

Rebase 应该并且确实忽略了这个补丁,因为它存在于你要变基的上游,这是--left-right通过将上游参数的对称差异传递给 rebase 来确定的,并且HEAD. 所有左侧提交都计算了它们的补丁 ID。所有右侧提交都计算了它们的补丁 ID。如果补丁 ID 匹配,则该提交被视为重复,并从要复制的提交集中删除。


推荐阅读