【问题标题】:Amending a previous commit and have it be reflected in subsequent commits?修改先前的提交并将其反映在后续提交中吗?
【发布时间】:2021-12-10 16:12:55
【问题描述】:

我在 git 中有一系列提交。假设提交 ID 是commit1, commit2, commit3。请注意,每个后续提交都包含之前的更改。

我需要修改 commit1(修改了源文件,我需要将其反映在 commit1 中),然后将修改传播到 commit2commit3。 git 中最好的工作流程是什么?

【问题讨论】:

  • 我建议您不要更改存储库的历史记录。只需修改您的树,以便您拥有所需的一切,然后作为 commit4 提交。更改历史记录是可能的,但很容易变得一团糟,通常与您使用版本控制软件的原因相悖
  • @ErniBrown 我明白了。我正在使用公司内部工具为每个提交创建一个拉取请求,这会阻止用户创建额外的提交。当审查拉取请求并需要更改时,首选方法是修改提交而不是创建新提交(从而创建新的拉取请求)。这就是我尝试这样做的原因
  • 请注意,修改后的提交新的提交。您可以通过 git rebase 的编辑功能修改提交及其所有后代,但这些也都将是新提交:原件将被删除。
  • @Quentin 哦,我明白了。使用我正在使用的这个内部工具,修改提交只会更新拉取请求;它实际上并没有创建一个新的拉取请求(除非我修改了提交消息,在这种情况下它会创建一个新的拉取请求)
  • @user5965026 我认为 Quentin 的评论虽然在技术上是正确的,但在回应您所说的“首选方法是修改提交而不是创建新提交”时可能会造成混淆。 Quentin 只是简单地指出,即使是修改也是“创建一个新的提交”。我认为尽管您的意思是“首选方法是修改提交而不是创建一个额外的提交”。您显然希望用一个更好的新提交替换该提交,而不是添加另一个仅包含修复的提交。这只是语义。

标签: git


【解决方案1】:

根据 cmets 中的讨论,我们知道贵公司的政策是重写您的提交以响应 Code Review 建议,而不是通过修复添加额外的提交:

当审查拉取请求并需要更改时,首选方法是修改提交...

有多种方法可以实现这一目标。但是,您也提到:

源文件已修改,我需要将其反映在 commit1

并且该语句表明您需要将分支重新定位到目标分支。幸运的是,每当您的公司政策是要重写时,您都可以安全地执行 rebase,只要您愿意,就不会受到伤害。我建议每天至少做一次,然后在你创建 PR 之前再做一次。所以,假设你的目标分支叫做main,你的远程叫做origin,你会经常这样做:

# Checkout (switch to) your branch if not already
git fetch
git rebase origin/main

在您从main 创建分支之后,这可能足以用已合并到main 的更改来更新您的所有提交。您可能会在您也修改过的文件上遇到冲突,在这种情况下,rebase 将暂停,您需要解决它们。如果需要,请寻求解决冲突的帮助,然后继续 rebase。

如果您有其他代码审查建议需要您修改commit1,在变基以获取最新代码后,实现此目的的一种(多种)方法是进行您需要的更改并创建一个新的临时第 4 次提交随着变化。将您的提交消息设置为:

squash into commit1: 这里是 commit1 的标题

然后你可以交互变基:

git rebase -i @~4

注意 @~4 表示 HEAD~4 表示当前分支的第 4 个父级,因为您现在有 4 个提交,所以需要它。您可以将其替换为 commit1 父级的提交 ID 哈希,顺便说一下,它也恰好是您的分支和目标分支的合并基础:git merge-base HEAD origin/main

一旦 rebase 编辑器弹出,提交按时间顺序列出,它们将被重写。将底部提交向上移动为第二次提交,如果您想重新编写提交消息,则将选择更改为“squash”(或只是“s”),如果不这样做,则更改为“fixup”(或只是“f”)不关心重写提交消息。然后保存并退出该文件,变基将继续。完成后,您将有 3 个提交而不是 4 个,并且新重写的 commit1 将根据需要进行修改。第 2 次和第 3 次提交当然也会反映更改。

请注意,每当您在分支上重新编写提交时,您都需要在之后强制推送您的分支以将其获取到远程并更新 PR:

git push --force-with-lease

旁注:任何时候你重新排序提交都可能发生冲突,如果你还在提交中修改了相同的文件,之后会被重新编写。通常您只需解决它们,但如果您有超过 3 个提交并且每个提交都存在冲突,您可能会考虑先将它们压缩为更少的提交,然后再执行重新排序。

【讨论】:

  • 谢谢。我还没有解析完你的答案,但想暂停一下,问一下git fetch git rebase origin/main是否与git pull --rebase origin main相同?
  • @user5965026 大多数时候,是的,它是一样的。请参阅this question 以了解不是的示例边缘情况。
猜你喜欢
  • 2011-04-25
  • 2018-09-21
  • 2020-04-29
  • 2021-12-31
  • 2020-12-18
  • 1970-01-01
  • 2014-06-22
  • 2021-08-30
  • 1970-01-01
相关资源
最近更新 更多