`git rebase`如何跳过它在上游已经发生变化的提交?

Mes*_*ssi 3 git git-rebase

git-rebase文件说:

如果上游分支已包含您所做的更改(例如,因为您邮寄了上游应用的补丁),则将跳过该提交.

但Git是如何做到的呢?

假设任何提交X都是commit 的父级Y,并且diffXYgit diff X Y命令的结果.我有以下提交:

o---o---o        <- master
 \
  o---o---o---o  <- test <- HEAD
Run Code Online (Sandbox Code Playgroud)

如果我做了git rebase master.那么我想的Git做跳绳承诺已经在master通过跳过任何承诺YtestdiffXY已经在master.

我做了一些例子,它们就像我猜想的那样.

这只是我的猜测,我是对的吗?

另外,在Git重新应用test提交之前,Git是否会执行此跳过任务master

Von*_*onC 6

(1.4.4,2006年10月)的第一个版本git rebase正在使用git format --ignore-if-in-upstream

这将检查可从<since>但不可从中获取的所有修补程序<until>,并将其与正在生成的修补程序进行比较,并忽略任何匹配的修补程序.

所以它正在查看补丁ID:请参阅提交9c6efa3进行实施.

 if (ignore_if_in_upstream &&
    !get_patch_id(commit, &patch_id_opts, sha1) &&
     lookup_object(sha1))
     continue;
Run Code Online (Sandbox Code Playgroud)

"补丁ID"只不过是与补丁关联的文件差异的SHA-1的总和,忽略了空格和行号.
因此,它"相当稳定",但同时也相当独特,即具有相同"补丁ID"的两个补丁几乎保证是相同的.

后来被委托给了git rebase-am(Git 1.7.6,2011年2月)

提交b6266dc,Git 2.1.0,2014年7月使用 --cherry-pick而不是--ignore-if-in-upstream

使用时,git format-patch --ignore-if-in-upstream我们只允许提供一个修订版本范围.
在下一次提交中,我们将要添加一个额外的排除修订,以便正确处理fork点,因此转换git-rebase--am为使用对称差异--cherry-pick --right-only.

(在Git 2.18中进一步改进)

这不会改变"跳过相同提交"机制.


tor*_*rek 5

VonC的答案给出了历史.该机制是Git称之为补丁ID机制.Git的补丁ID概念证明(虽然有点轻)在git patch-id手册页,总结这样说:

...你可以使用这个东西来寻找可能的重复提交.

这是git rev-list --cherry-mark(使用对称差异...符号)和git format-patch --ignore-if-in-upstream(使用简单的排除..操作)来检测重复提交.如果提交(其定义与提交的哈希不同,至少可能被复制)具有与要复制的提交相同的修补程序ID,则Git假定提交已被复制,因此无需复制它.

你还问:

另外,在Git重新应用test提交之前,Git是否会执行此跳过任务master

是:首先生成要复制的提交列表 - 在此期间将丢弃与patch-ID等效的提交以及所有合并提交,除非您使用-p-r选项 - 然后开始使用rebase进程.

(如果使用非自动化git rebase使用git am,该底垫过程中仍然使用git format-patch作为输入到输出git am,否则提交要复制存储在文件哈希,或在定序器,其可以或可以不将它们存储在一个文件中,并然后通过运行git cherry-pick或直接通过顺控程序挑选提交.详细信息取决于您特定的Git年份.)