【问题标题】:What difference does `.git/CHERRY_PICK_HEAD` make when committing?提交时`.git/CHERRY_PICK_HEAD`有什么区别?
【发布时间】:2017-06-24 17:02:55
【问题描述】:

注意:这是对我之前的帖子(现已删除)的改写。重新措辞旨在使帖子具有不同的重点。


在运行git cherry-pick 时,git 报告存在冲突。我解决了冲突,然后运行git cherry-pick --continue。此时,$GIT_EDITOR 弹出了一个 COMMIT_EDITMSG 缓冲区,其中预先填充了精选提交的原始消息以及一些附加信息,其中包括警告:

# It looks like you may be committing a cherry-pick.
# If this is not correct, please remove the file
#   .git/CHERRY_PICK_HEAD
# and try again.

我检查了如果我“删除”(实际上只是暂时重命名).git/CHERRY_PICK_HEAD 文件会发生什么。这产生的直接外部影响是从我的git-aware 提示中删除了|CHERRY-PICKING 指示。

除了提示中的这种变化,以及COMMIT_EDITMSG 缓冲区中预先填充的信息可能存在一些差异之外,在有或没有.git/CHERRY_PICK_HEAD 文件的情况下执行提交会有什么不同?


更准确地说,我在这里尝试比较两种情况。

在第一个场景中,我运行

% git cherry-pick --continue

...并且(忽略前面引用的警告)我照常进行提交。

在第二种情况下,我运行

% rm .git/CHERRY_PICK_HEAD
% git commit

...然后像往常一样继续提交。

(假设我在两种情况下使用相同的提交消息。)

这两种情况的最终结果有何不同?

【问题讨论】:

    标签: git cherry-pick git-cherry-pick


    【解决方案1】:

    答案取决于你在做什么。使用--continue 完成序列——但如果序列只是一个精选的序列,那么无论如何都没有真正的序列。

    无论如何,删除 .git/CHERRY_PICK_HEAD 肯定还有一个额外的显着效果:完成一个有冲突的cherry-pick 会重新使用原始提交的作者姓名-电子邮件和日期信息。您始终是任何新提交的提交者,但所有提交都不仅仅是一个人员和时间戳:每个新提交都有两个条目,一个用于“提交者”(您,刚刚进行提交),一个用于“作者"(无论是谁编写了原始提交,以及他们何时这样做)。 Cherry-pick 保留原始提交中的作者信息。

    音序器

    git cherry-pickgit revert 两者在内部实际上是相同的命令; revert 只是“向后工作”——使用 Git 所谓的 sequencer。也就是说,您可以一次选择多个提交:

    git cherry-pick notthis..that thistoo
    

    挑选“在”notthis 之后的所有提交,包括that,以及一个特定的提交thistoo。例如,您可能决定挑选从develop 增长的feature/X 上的每个提交,以及一个错误修复提交fix-1234,用于测试目的:

    git checkout master
    git checkout -b testbranch
    git cherry-pick develop..feature/X fix-1234
    

    无论如何,这里的重点是,这可能会挑选十几个或更多提交,并且在此过程中的某个地方可能会发生合并冲突,这需要 git cherry-pick 停止并寻求帮助。

    另外:这里的模型——Unix/Linux 命令行——是你将一个命令输入到一个叫做 shell 的命令解释器中。 shell 将人机界面的控制权传递给新命令,新命令将保留它,直到命令完成并退出。一旦命令退出,命令本身就不会留下任何痕迹:任何永久都必须保存在文件中。

    那么:如果cherry-pick 必须停止,它怎么知道从哪里恢复?答案是将信息保存在文件中。如果您正在挑选单个提交,Git 只保存 CHERRY_PICK_HEAD 文件,该文件记录了被挑选的提交的 ID。但是,如果您选择 多个 提交,Git 会将冲突的提交保存为单个提交, 并且 将剩余信息保存在排序目录中(其位置已随着时间的推移移动了一些)。

    运行git cherry-pick --continue 指示(新的、单独的)cherry pick 命令从前一个停止的地方继续。 Git 将首先为您运行git commit,然后找到排序信息并尽可能多地完成序列,在下一次冲突时再次停止,或者完成所有的挑选。

    运行git commit,Git 会注意到CHERRY_PICK_HEAD 文件并使用它,如您所见。提交完成后,该命令将退出并且对排序器不执行任何操作。如果 留下了排序器数据,您现在可以git cherry-pick --continue:Git 会注意到提交已经完成,只需继续/完成排序器操作。

    请注意,您可以使用git cherry-pick --abort,而不是完成操作。这将终止操作并将事情恢复到您开始之前的状态。从 Git 2.19 开始,您可以改为使用 git cherry-pick --quit 停止(类似于 --abort),但不能将事情恢复到开始之前的状态。也就是说,它会停止任何未来的樱桃采摘操作,而不会撤消您迄今为止所做的那些操作。 (2.19之前没有这个操作。)

    git status 命令现在会注意到是否有正在进行的序列,并报告您正在执行的任何操作中。 (与 Git 1.7 时代相比,这是一个很大的改进,当时它没有。)

    【讨论】:

    • 哇,太棒了!谢谢。
    • 您现在拥有 git cherry-pick --quit,但它仅适用于 Git 2.19(2018 年第三季度):请参阅“How to Conclude a Git Cherry-Pick?”。
    • 此外,.git/CHERRY_PICK_HEAD 的存在还有另一个不同之处,即使在挑选单个提交时也是如此。当 git cherry-picking 时,git 会保留原始提交的作者日期(可能还有作者姓名/电子邮件)。
    • @Alex35:是的——我会稍微改一下上面的说法。 (我在较长的部分中有详细信息,但需要在顶部提及。)
    【解决方案2】:

    正如我评论的那样,git cherry-pick --quit 也会删除 .git/CHERRY_PICK_HEAD,但是,此外,消息“如果这不正确,请删除文件 .git/CHERRY_PICK_HEAD”将随着 Git 2.29(2020 年第四季度)发生变化:访问已更新两个伪引用以正确使用 ref API。

    参见Han-Wen Nienhuys (hanwen)commit b8825efcommit b6d2558commit c8e4159commit 3f9f1ac(2020 年 8 月 21 日)。
    (由 Junio C Hamano -- gitster -- 合并到 commit e699684,2020 年 8 月 31 日)

    builtin/commit: 建议 update-ref 删除伪引用

    签字人:Han-Wen Nienhuys

    当伪引用移至不同的引用存储机制时,伪引用不能再使用'rm'删除。
    相反,建议使用“update-ref -d”命令,无论 ref 存储后端如何,该命令都可以工作。

    新消息会提示:git update-ref -d CHERRY_PICK_HEAD

    【讨论】:

      猜你喜欢
      • 2011-10-09
      • 1970-01-01
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 2017-10-01
      • 2010-10-02
      • 2013-11-06
      • 2023-02-09
      相关资源
      最近更新 更多