我可以使用 Git 以两种方式更改提交历史记录吗?

Posted

技术标签:

【中文标题】我可以使用 Git 以两种方式更改提交历史记录吗?【英文标题】:Can I change the commit history in two ways using Git? 【发布时间】:2021-12-14 06:32:11 【问题描述】:

我问这个问题是因为我正在研究Pro Git一书,其中有一章重写历史解释了如何更改最后一次提交$ git commit --amend,更改多个提交消息 $ git rebase -i HEAD~3,使用 $ git filter 删除所有提交中的特定文件或文件夹-branch --tree-filter.

这是我的问题:这本书没有提到在所有提交历史中通过多次检查来完成这项工作的可能性。所以我移动我的 HEAD,逐个提交,然后用 $ git commit --amend 一个一个地更改这个特定的提交。

我知道就花费的时间而言,它真的(真的!)昂贵,但它真的可能吗(即它有效)? 如果是,在哪些情况下这可能有用?

【问题讨论】:

请注意,从技术意义上讲,您并没有更改任何提交。相反,您是在进行 新的和应该改进的 提交,然后从使用旧的(而且很糟糕?)切换到新的(和改进的?)提交。新提交的哈希 ID 与旧提交的哈希 ID 不同,如果使用旧的哈希 ID,您可以看到旧提交仍然存在。 除了 VonC 与新奇的 git filter-repo 的链接之外,旧的(名义上已弃用)git filter-branch 也做同样的事情。我们只需使用git rev-list 或类似方法来枚举所有要复制的提交的所有原始哈希 ID,然后开始复制。完成后,我们将用于引用旧提交的所有名称切换过来,以便它们引用新改进的提交。 【参考方案1】:

对于所有次提交,您可以使用newren/git-filter-repo,它可以重写您需要的任何内容(作者、提交消息、文件或文件内容,...)

例如,关于提交消息,using message-callback:

消息回调与前三个回调非常相似,但它操作的字节串可能不止一行:

git-filter-repo --message-callback '
 if b"Signed-off-by:" not in message:
   message += b"\nSigned-off-by: Me My <self@and.eye>"
 return re.sub(b"[Ee]-?[Mm][Aa][Ii][Ll]", b"email", message)'

【讨论】:

换句话说,应该使用git-filter-repo 而不是git filter-branch 以获得相同的结果。但是我不明白我是否可以使用天真的“我使用$ git commit --amend手动更改所有提交”。 @Filippo 是的,git filter-branch 已过时。并且您可以使用提交修改方法,但是当您有数百个要更改的提交时,它不容易扩展。 谢谢,我需要对此进行确认。

以上是关于我可以使用 Git 以两种方式更改提交历史记录吗?的主要内容,如果未能解决你的问题,请参考以下文章

SVN和GIT提交历史记录和代码差异

使用 Git 版本控制查看文件的更改历史记录

git revert 回到某个提交而不更改历史记录并创建一个新的提交,如 git revert

如何拆分隐藏在历史中的 Git 提交?

如何拆分隐藏在历史中的 Git 提交?

git:清理 git 历史记录并仅在 master 中保留合并的提交