rebase
后端目前在处理空提交信息时表现不同,这在很大程度上是基于它们所基于的不同底层命令的副作用。
基于 am
的 rebase 应用带有空提交消息的提交而不会停止或要求用户指定额外的标志。
(有趣的是,基于 am
的 rebase 是默认的 rebase 类型,没有人要求使用 --no-allow-empty-message
标志来更改此行为。)
基于合并和交互式的 rebase(最终基于 git commit
),当前将在任何此类提交上停止,并要求用户手动指定如何处理提交并继续。
差异行为的一个可能理由是,"am
" 基础的 rebase 的目的仅仅是移植现有的历史记录,而 "交互式" rebase 的目的是在使其可发布之前对系列进行修整。
因此,在后者的情况下停止并询问可能存在的问题更加合适。
然而,这种理由存在两个问题:
-
- 基于合并的 rebase 也是非交互式的,并且有多种类型的 rebase 使用交互式机制,但并不是显式交互的(例如,当指定
--rebase-merges
或 --keep-empty
而没有使用 --interactive
时)。
这些 rebase 也仅用于移植现有的历史记录,因此也应默认为 --allow-empty-message
。
-
- 这种理由仅表示用户在显式交互式 rebase 的情况下更容易接受停止,而不是停止出于这种特定原因实际上是有意义的。
探索是否有意义需要倒退并分析基础命令......
如果 git-commit
默认不对空提交报错,那么意外创建带有空消息的提交将是非常常见的情况(这个检查已经抓住了我很多次)。
此外,几乎所有这样的空提交消息都被认为是意外错误(这可以从版本控制系统和各种博客文章中的大量文档证明提交消息的重要性)。
因此,对于本来可能是常见错误的简单检查就显得非常有意义,git-commit
增加了一个 --allow-empty-message
标志,以进行特殊情况的覆盖。
这使得带有空消息的提交非常罕见。
rebase(和 cherry-pick)带有空消息的提交有两个来源:
- (a) 在 git 中创建的提交,用户以前指定了
--allow-empty-message
给 git-commit,和
- (b) 从其他版本控制系统导入到 git 中的提交。
在情况 (a) 中,用户已经明确指定此提交存在某些特殊之处,使他们不想指定提交消息;强制他们在每次 cherry-pick 或 rebase 时重新指定似乎更可能引起愤怒而不是帮助。
在情况 (b) 中,提交极不可能由导入历史记录并执行 rebase 或 cherry-pick 的人编写,因此
注意:Git 2.19 中的 "git rebase
" 等操作在编辑后出现空提交日志消息时无法中止,这个问题已在 Git 2.20(2018年第四季度)得到修复。
序列化器
:修复 --allow-empty-message
行为,使其更智能化
In commit b00bf1c ("git-rebase
: make --allow-empty-message
the
default", 2018-06-27, Git v2.19.0-rc0), several arguments were given for transplanting empty commits without halting and asking the user for confirmation on each commit.
These arguments were incomplete because the logic clearly assumed the only cases under consideration were transplanting of commits with empty messages (see the comment about "There are two sources for commits with empty messages).
It didn't discuss or even consider rewords, squashes, etc. where the user is explicitly asked for a new commit message and provides an empty one.
(My bad, I totally should have thought about that at the time, but just didn't.)
Rewords and squashes are significantly different, though, as described
by SZEDER:
Let's suppose you start an interactive rebase, choose a commit to
squash, save the instruction sheet, rebase fires up your editor, and
then you notice that you mistakenly chose the wrong commit to
squash. What do you do, how do you abort?
Before [that commit] you could clear the commit message, exit the editor, and then rebase would say "Aborting commit due to empty commit message.", and you get to run 'git rebase --abort
', and start over.
But [since that commit, ...] saving the commit message as is would let rebase continue and create a bunch of unnecessary objects, and then you would have to use the reflog to return to the pre-rebase state.
Also, he states:
The instructions in the commit message template, which is shown for 'reword
' and 'squash
', too, still say...
These are sound arguments that when editing commit messages during a sequencer operation, that if the commit message is empty then the operation should halt and ask the user to correct.
The arguments in commit b00bf1c (referenced above) still apply when transplanting previously created commits with empty commit messages, so the sequencer should not halt for those.
Furthermore, all rationale so far applies equally for cherry-pick as for rebase.
Therefore, make the code:
- default to
--allow-empty-message
when transplanting an existing commit, and to
- default to halting when the user is asked to edit a commit message and provides an empty one -- for both rebase and cherry-pick.
注意,当处理空提交时,请确保使用Git 2.25+(2020年第二季度)。请参见“ 如何填写空提交消息?”(最后一节)。
在 Git 2.26(2020年第一季度)中,文档已经更新。
请看提交 10cdb9f, 提交 2ac0d62, 提交 8295ed6, 提交 76340c8, 提交 980b482, 提交 c2417d3, 提交 6d04ce7, 提交 52eb738, 提交 8af14f0, 提交 be50c93, 提交 befb89c, 提交 9a70f3d, 提交 93122c9, 提交 55d2b6d, 提交 8a997ed, 提交 7db00f0, 提交 e98c426, 提交 d48e5e2 (2020年2月15日), 以及提交 a9ae8fd, 提交 22a69fd (2020年1月16日) 由Elijah Newren (newren
)完成。
(由Junio C Hamano -- gitster
--于2020年3月2日合并至提交 8c22bd9)
git-rebase.txt
: 更新 --allow-empty-message 的描述
署名:Elijah Newren
提交b00bf1c9a8dd("git-rebase
: make --allow-empty-message the default",2018-06-27,Git v2.19.0-rc0 -- merge列在批次#4中)将--allow-empty-message设置为默认值,因此将--allow-empty-message变成了无操作,但未更新文档以反映此更改。
现在更新文档,并从正常的-h输出中隐藏该选项,因为它没有用。
git rebase man page现在包括:
--allow-empty-message
:
无操作。
以前,具有空消息的提交会失败,此选项将覆盖该行为,允许重新提交具有空消息的提交。
现在,具有空消息的提交不会导致重新提交停止。
使用Git 2.26(2020年第一季度),"git rebase
"默认使用合并后端(即驱动"rebase -i
"的机制),同时允许"--apply
"选项使用"apply
"后端(例如,道德等效的"format-patch piped to am
")。(可以设置rebase.backend
配置变量进行自定义。)
它更好地管理空提交:
请查看 提交记录10cdb9f, 提交记录2ac0d62, 提交记录8295ed6, 提交记录76340c8, 提交记录980b482, 提交记录c2417d3, 提交记录6d04ce7, 提交记录52eb738, 提交记录8af14f0, 提交记录be50c93, 提交记录befb89c, 提交记录9a70f3d, 提交记录93122c9, 提交记录55d2b6d, 提交记录8a997ed, 提交记录7db00f0, 提交记录e98c426, 提交记录d48e5e2(2020年2月15日),以及提交记录a9ae8fd, 提交记录22a69fd (2020年1月16日)由Elijah Newren (newren
)提交。
(由Junio C Hamano -- gitster
--合并于提交记录8c22bd9,2020年3月2日)
签名作者:Elijah Newren
在之前的提交和提交b00bf1c9a8dd("git-rebase
: make --allow-empty-message the default",2018-06-27,Git v2.19.0-rc0 -- 合并列在批次#4中),在各种边缘或特殊情况下,使用不同后端进行变基的行为往往更多是偶然而非设计。
这个提交解决了另一个边角情况:变为空的提交。仔细阅读者可能会注意到,由于变基,有两种类型的提交会变为空:
[干净的樱桃拣选]
是清洁的樱桃拣选上游提交的提交,由 git log --cherry-mark ...
确定。重新应用这些提交将导致一组空更改和重复的提交消息;即这些提交在上游已经被“应用”了。
[变为空]
是不是空的开始,不是干净的樱桃拣选上游提交的提交,但在被变基后仍然变为空。
例如,当一个提交具有严格子集中的更改时,或者当一个提交的更改可以在几个上游提交之间分散或分布时,就会发生这种情况。
显然,在这两种情况下,所讨论的提交中的更改已经在上游找到了,但在后一种情况下,提交消息可能不在。
当樱桃标记能够确定提交已经在上游时,由于樱桃标记的工作方式,这意味着上游提交消息与完全相同的更改。
因此,可以假设提交消息是完全可互换的(实际上很可能完全相同)。
因此,清洁的樱桃拣选案例表示在保留额外提交时没有信息可以获得。
所有变基类型始终会删除这些提交,据我所知,从未有人要求我们做出其他处理。
对于许多变为空的情况(很可能是大多数情况),我们也将能够在不丢失信息的情况下删除提交--但并非总是如此。
由于这些提交代表了不干净的樱桃拣选的情况,因此没有上游提交消息解释相同的更改。
具有良好提交消息卫生的项目可能会将我们的提交消息说明包含在相关上游提交中或分散其中,但并非所有项目都运行该方式。
因此,正在变基的提交消息可能具有建议适应新基础的其他更改的推理,或者可能具有某人想要添加为另一个提交的注释的信息,或者甚至可能有人想要创建一个空提交,其中提交消息不变。
Junio 对“变为空”的提交发表了评论如下:
关于最终为空的更改(而不是从一开始就为空的更改),我认为当前的行为是期望的。基于“am”的变基仅是移植现有历史,并且希望停止比“交互式”的变基更少,从工作流程的角度来看,“询问(“这已经变为空了--你要删除它吗?”)更合适。
我只想补充说,他对于基于“am”的变基的论点实际上适用于所有非明确交互的变基。
此外,由于我们声明不同情况应该具有不同的默认值,因此可能值得提供一个标志,以允许用户选择他们想要的行为。
引入一个新的命令行标志来选择所需的行为:
--empty={drop,keep,ask}
其定义如下: