在Git中编辑根提交?

407

有几种方法可以更改之后提交的提交的消息:

git commit --amend                    # for the most recent commit
git rebase --interactive master~2     # but requires *parent*

如何更改没有父提交记录的第一个提交记录的提交信息?


请参见https://dev59.com/m2ct5IYBdhLWcg3wk-Rq。 - fork0
特别是:在“git filter-branch --msg-filter”脚本中使用GIT_COMMIT环境变量。 - fork0
1
请参考以下链接:https://dev59.com/pXE95IYBdhLWcg3wlu6z#2309391 - BlackICE
5个回答

690

从Git版本 1.7.12 开始,您现在可以使用

git rebase -i --root

文档


2
使用这个命令可以将所有分支的根重新定位吗?看起来这会将当前分支分离到新的根上,而所有其他分支将保留在旧的根上。 - woojoo666
@woojoo666,你需要像往常一样将分支变基到新的根上。 - berkus
@Atcold 如果没有上游根,它就无法工作。 - Kai
警告:我错误地假设这将执行我签出分支的根,但加载所有提交需要一段时间,然后重新设置它们。 - Leo
2
顺便说一句:我也希望看到这个回答被采纳,特别是因为它与我在开发初期清理新项目历史记录时最喜欢的 git 命令完全匹配,即:git rebase --interactive --autosquash --autostash --root - pvandenberk
2
@Leo,你的评论是什么意思?我看不出第一部分和第二部分之间的联系 - 花费时间与此有什么关系? - boycy

321

假设你的工作目录是干净的,你可以执行以下操作。

# checkout the root commit
git checkout <sha1-of-root>

# amend the commit
git commit --amend

# rebase all the other commits in master onto the amended root
git rebase --onto HEAD HEAD master

28
我认为应该使用git rebase --onto HEAD <sha1-of-root> master命令。 - Andrew
5
没问题,但你想要git rebase的<upstream>的_原始_根提交记录。 git rebase应用<分支>(master)中不在<upstream>的提交记录; HEAD不在master中,所以你的版本尝试应用所有master的提交记录。 - Andrew
8
请确认命令为 git rebase --onto HEAD <sha1-of-root> master,其中 <sha1-of-root>git checkout <sha1-of-root> 中使用的相同。否则,您将会有两个“first commit”。 - Andy
3
@Cupcake:你测试了旧版本的命令吗?它应该能正常工作。修改只是更改提交消息,因此旧根提交和新根提交引入的更改完全相同,因此旧根提交会被自动跳过。第二个“HEAD”确保考虑所有提交,并且我们可以使用双参数版本的rebase回到主分支。请注意,这个答案是在--root选项出现之前给出的。 - CB Bailey
11
下面的 ecdpalma 的回答 更加简单易懂,并且得到了更多的赞同票,向下滚动吧! - Flimm
显示剩余16条评论

76

ecdpalma的回答的基础上,现在你可以使用--root选项告诉rebase你想要重写根/第一个提交:

git rebase --interactive --root

然后根提交将会在重新基于的TODO列表中显示,您可以选择编辑或者改写:

reword <root commit sha> <original message>
pick <other commit sha> <message>
...

这是来自Git rebase文档--root的解释(强调是我的):
重新定义所有可以从<branch>到达的提交,而不是将它们限制在一个<upstream>中。这使您可以在分支上重新定义根提交(或根提交)。

只更改一个分支内根提交的提交消息,如何在所有25个分支上执行此操作? - PirateApp

17

仅提供一个与评分较高答案不同的选择:

如果您正在创建一个存储库,并且事先知道将来会在其“第一个”真正提交的顶部进行变基,那么您可以在开头进行明确的空提交以完全避免此问题:

git commit --allow-empty -m "Initial commit"

只有在那之后才开始进行“真正”的提交。然后你可以按照标准的方式在该提交之上进行简单的变基,例如 git rebase -i HEAD^


7
这是否意味着为了让它生效,你需要有先见之明(或者是超能力),在项目一开始就做一个空提交?这对我来说似乎非常情境化,并且通常并不实际。你认为呢?如果我已经做了100个提交,突然需要编辑根提交,那么在这种情况下,如果我没有在一开始就做那个空提交,这个方法还有效吗? - user456814
4
在拥有上百个根提交后修改消息可能不是你会做的事情。有时候我只是想要一个 Git 存储库,进行一些垃圾提交,知道一旦达到某种可用状态,我会将它们压缩成一个提交,并重新定义其消息。无论如何,现在我改变了主意,我认为第一个提交最有用的事情是放置 .gitattributes 文件,而不是进行空提交。 - jakub.g
回复第一个评论者:你不必每次都有远见地进行空提交。你可以(1)创建带有此空提交的存储库(2)将其放置在某个“git存储库模板”目录中(3)每当需要新存储库时复制它。 - Guildenstern

4
你可以使用 `git filter-branch` 命令:
cd test
git init

touch initial
git add -A
git commit -m "Initial commit"

touch a
git add -A
git commit -m "a"

touch b
git add -A
git commit -m "b"

git log

-->
8e6b49e... b
945e92a... a
72fc158... Initial commit

git filter-branch --msg-filter \
"sed \"s|^Initial commit|New initial commit|g\"" -- --all

git log
-->
c5988ea... b
e0331fd... a
51995f1... New initial commit

我正在使用filter-branch更改作者/提交者,而-- --all选项确实是在这种情况下处理根提交的关键。 - sschuberth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接