`git rebase` 如何跳过它的更改已经在上游进行的提交?
How does `git rebase` skip the commit which its change already has in upstream?
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.
但是 Git 是怎么做到的呢?
假设任何提交 X
是提交 Y
的父级,并且 diffXY
是 git diff X Y
命令的结果。我有以下提交:
o---o---o <- master
\
o---o---o---o <- test <- HEAD
如果我做一个git rebase master
。然后我猜 Git 通过跳过 diffXY
已经在 master
中的 test
中的任何提交 Y
来跳过 master
中已经存在的跳过提交。
我有 运行 一些例子,它们和我猜的一样。
这只是我的猜测,对吗?
此外,Git 是否会在 Git 将 test
的提交重新应用到 master
之前执行此跳过任务?
first versions of git rebase
(1.4.4, Oct. 2006) were using git format --ignore-if-in-upstream
This will examine all patches reachable from <since>
but not from <until>
and compare them with the patches being generated, and any patch that matches is ignored.
所以它正在查看 patch ids: See commit 9c6efa3 for the implementation。
if (ignore_if_in_upstream &&
!get_patch_id(commit, &patch_id_opts, sha1) &&
lookup_object(sha1))
continue;
A "patch ID" is nothing but a sum of SHA-1 of the file diffs associated with a
patch, with whitespace and line numbers ignored.
As such, it's "reasonably stable", but at the same time also reasonably unique, i.e., two patches that have the same "patch ID" are almost guaranteed to be the same thing.
后来 delegated to git rebase-am
(Git 1.7.6,2011 年 2 月)
并且commit b6266dc, Git 2.1.0, Jul. 2014使用了--cherry-pick
而不是--ignore-if-in-upstream
When using git format-patch --ignore-if-in-upstream
we are only allowed to give a single revision range.
In the next commit we will want to add an additional exclusion revision in order to handle fork points correctly, so convert git-rebase--am
to use a symmetric
difference with --cherry-pick --right-only
.
(Further improved in Git 2.18)
这不会改变“跳过相同提交”机制。
如上所述,“git rebase
"(man) 默认情况下会跳过与历史记录中已经存在的提交等同的更改,分支将重新基于该更改;
但是在 Git 2.34 中,这现在更清楚了,因为它会在发生这种情况时发出消息,让用户知道跳过的提交,并教他们如何告诉“rebase”保留重复的更改.
参见 commit 767a4ca (30 Aug 2021) by Josh Steadmon (steadmon
)。
(由 Junio C Hamano -- gitster
-- in commit 6c083b7 合并,2021 年 9 月 10 日)
sequencer
: advise if skipping cherry-picked commit
Signed-off-by: Josh Steadmon
Silently skipping commits when rebasing with --no-reapply-cherry-picks
(currently the default behavior) can cause user confusion.
Issue warnings when this happens, as well as advice on how to preserve the skipped commits.
These warnings and advice are displayed only when using the (default) "merge" rebase backend.
Update the git-rebase
(man) docs to mention the warnings and advice.
git config
现在包含在其 man page 中:
skippedCherryPicks
Shown when git rebase
skips a commit that has already
been cherry-picked onto the upstream branch.
git rebase
现在包含在其 man page 中:
will be skipped and warnings will be issued (if the merge
backend is used).
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):
git rebase
现在包含在其 man page 中:
When using the merge
backend, warnings will be issued for each dropped commit (unless --quiet
is given).
Advice will also be issued unless advice.skippedCherryPicks
is set to false (see git config
).
现在您将看到:
skipped previously applied commit xxx
use --reapply-cherry-picks to include skipped commits
gives the history. The mechanism is what Git calls a patch ID. Git's patch ID concept is documented (albeit a bit lightly) in the git patch-id
manual page,总结起来就是:
... you can use this thing to look for likely duplicate commits.
这就是 git rev-list --cherry-mark
(使用对称差异 ...
表示法)和 git format-patch --ignore-if-in-upstream
(使用简单的排除 ..
操作)检测重复提交的方法。如果根据定义,其哈希值不同于要复制的提交(至少可能被复制)的提交具有与要复制的提交相同的 补丁 ID,则 Git 假定该提交已被复制,因此无需复制它。
您还问过:
Plus, does Git do this skipping task before Git do the reapplying test
's commits onto the master
?
是:首先生成要复制的提交列表——在此期间丢弃等效补丁 ID 的提交,以及 所有 合并提交,除非您使用-p
或 -r
选项——然后变基过程开始。
(如果您使用使用 git am
的非自动 git rebase
,变基过程仍然使用 git format-patch
输出作为 git am
的输入。否则提交哈希要复制的文件存储在文件中,或者存储在可能会或可能不会将它们存储在文件中的排序器中,然后提交由 运行 git cherry-pick
或直接由排序器挑选. 详细信息取决于您的特定 Git 年份。)
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.
但是 Git 是怎么做到的呢?
假设任何提交 X
是提交 Y
的父级,并且 diffXY
是 git diff X Y
命令的结果。我有以下提交:
o---o---o <- master
\
o---o---o---o <- test <- HEAD
如果我做一个git rebase master
。然后我猜 Git 通过跳过 diffXY
已经在 master
中的 test
中的任何提交 Y
来跳过 master
中已经存在的跳过提交。
我有 运行 一些例子,它们和我猜的一样。
这只是我的猜测,对吗?
此外,Git 是否会在 Git 将 test
的提交重新应用到 master
之前执行此跳过任务?
first versions of git rebase
(1.4.4, Oct. 2006) were using git format --ignore-if-in-upstream
This will examine all patches reachable from
<since>
but not from<until>
and compare them with the patches being generated, and any patch that matches is ignored.
所以它正在查看 patch ids: See commit 9c6efa3 for the implementation。
if (ignore_if_in_upstream &&
!get_patch_id(commit, &patch_id_opts, sha1) &&
lookup_object(sha1))
continue;
A "patch ID" is nothing but a sum of SHA-1 of the file diffs associated with a patch, with whitespace and line numbers ignored.
As such, it's "reasonably stable", but at the same time also reasonably unique, i.e., two patches that have the same "patch ID" are almost guaranteed to be the same thing.
后来 delegated to git rebase-am
(Git 1.7.6,2011 年 2 月)
并且commit b6266dc, Git 2.1.0, Jul. 2014使用了--cherry-pick
而不是--ignore-if-in-upstream
When using
git format-patch --ignore-if-in-upstream
we are only allowed to give a single revision range.
In the next commit we will want to add an additional exclusion revision in order to handle fork points correctly, so convertgit-rebase--am
to use a symmetric difference with--cherry-pick --right-only
.
(Further improved in Git 2.18)
这不会改变“跳过相同提交”机制。
如上所述,“git rebase
"(man) 默认情况下会跳过与历史记录中已经存在的提交等同的更改,分支将重新基于该更改;
但是在 Git 2.34 中,这现在更清楚了,因为它会在发生这种情况时发出消息,让用户知道跳过的提交,并教他们如何告诉“rebase”保留重复的更改.
参见 commit 767a4ca (30 Aug 2021) by Josh Steadmon (steadmon
)。
(由 Junio C Hamano -- gitster
-- in commit 6c083b7 合并,2021 年 9 月 10 日)
sequencer
: advise if skipping cherry-picked commitSigned-off-by: Josh Steadmon
Silently skipping commits when rebasing with
--no-reapply-cherry-picks
(currently the default behavior) can cause user confusion.
Issue warnings when this happens, as well as advice on how to preserve the skipped commits.These warnings and advice are displayed only when using the (default) "merge" rebase backend.
Update the
git-rebase
(man) docs to mention the warnings and advice.
git config
现在包含在其 man page 中:
skippedCherryPicks
Shown when
git rebase
skips a commit that has already been cherry-picked onto the upstream branch.
git rebase
现在包含在其 man page 中:
will be skipped and warnings will be issued (if the
merge
backend is used).
For example, runninggit rebase master
on the following history (in whichA'
andA
introduce the same set of changes, but have different committer information):
git rebase
现在包含在其 man page 中:
When using the
merge
backend, warnings will be issued for each dropped commit (unless--quiet
is given).
Advice will also be issued unlessadvice.skippedCherryPicks
is set to false (seegit config
).
现在您将看到:
skipped previously applied commit xxx
use --reapply-cherry-picks to include skipped commits
git patch-id
manual page,总结起来就是:
... you can use this thing to look for likely duplicate commits.
这就是 git rev-list --cherry-mark
(使用对称差异 ...
表示法)和 git format-patch --ignore-if-in-upstream
(使用简单的排除 ..
操作)检测重复提交的方法。如果根据定义,其哈希值不同于要复制的提交(至少可能被复制)的提交具有与要复制的提交相同的 补丁 ID,则 Git 假定该提交已被复制,因此无需复制它。
您还问过:
Plus, does Git do this skipping task before Git do the reapplying
test
's commits onto themaster
?
是:首先生成要复制的提交列表——在此期间丢弃等效补丁 ID 的提交,以及 所有 合并提交,除非您使用-p
或 -r
选项——然后变基过程开始。
(如果您使用使用 git am
的非自动 git rebase
,变基过程仍然使用 git format-patch
输出作为 git am
的输入。否则提交哈希要复制的文件存储在文件中,或者存储在可能会或可能不会将它们存储在文件中的排序器中,然后提交由 运行 git cherry-pick
或直接由排序器挑选. 详细信息取决于您的特定 Git 年份。)