git - 什么时候 2 个补丁在 git 中被认为是相等的?

标签 git

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

If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will be skipped. For example, running git rebase master on the following history (in which A' and A introduce the same set of changes, but have different committer information):

      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 

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

这让我想到补丁,因此也依赖于我应用补丁的前一次提交。那么,当我们说 (patch1 on some branch) = (patch2 on some other branch) 时,他们的祖先也需要相同吗?如果是,我们可以递归地应用它,结果 2 个分支将是相同的,这是不合逻辑的。

所以,我的问题是,我们什么时候说 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

最佳答案

So, when we say (patch1 on some branch) = (patch2 on some other branch) , then their ancestors also need to be same?

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

git rev-list 命令也可以做到这一点。查看它的--left-right, --right-only, --cherry-mark, and --cherry-pick 选项,必须与对称差异三点符号提交选择器一起使用。

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

... thought patch will be same if same contents on same line ...

不,行号被删除了。这是有目的的:例如,一个补丁可能就像将传递 false 的调用替换为传递 true 的调用一样简单,这对 Git 来说是:

-    foo(false)
+    foo(true)

(在 git diff 的情况下,有一些周围的上下文——不清楚 patch-ID 是否包含上下文,但我认为它包含)。假设此修复上游接受,而您正在处理可能与修复相关或不相关的功能......但是上游,调用foo 位于第 42 行,现在位于第 47 行,因为在此点之上添加了五行不相关的代码?

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


1在 Git 2.39 中,补丁 ID 计算代码发生了变化,部分是为了修复一些错误,部分是为了允许保留与缩进相关的空白。请特别查看新的 --verbatim 选项,以及 the detail in this answer from VonC .

关于git - 什么时候 2 个补丁在 git 中被认为是相等的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58695585/

相关文章:

git - Git项目中的子文件夹?

git - 如何忽略 NetBeans merge 工具中的空格

r - 如何在 RStudio 中 merge git 分支

eclipse - 如何在 Eclipse 中为 Gradle 项目的本地依赖项指定源附件、Javadoc 位置和 native 库位置?

macos - 我无法卸载 Git

git - 在给定 merge 提交 SHA1 的情况下,您如何查看/显示已完成的 git merge 冲突解决方案?

git - Visual Studio Code 如何解决与 git 的 merge 冲突?

git diff 不会打印错误文件名的错误

git - 在开始使用 Git 之前,我应该了解什么?

php - Aptana 3.1.1(2012 年 4 月 17 日)不使用 Git 跟踪更改