滥用 git 编辑不正确的提交消息而不进行变基或过滤

abusing git to edit an incorrect commit message without rebasing or filtering

我问的是故意不正确版本的How to modify existing, unpushed commits? , and I've read the canon response on commit ids depending on the commit message content in git: How to change the commit message of an already made commit non-interactively without changing the commit ID?

仅针对那些可能会说 "no, you're going to do it the correct way" 的人:这些回复是 "the only good way",我知道。只是,我的处境是,以正确的方式做事对我来说并不是真正有用,因为现在的成本太高了;我想我知道可能会发生混乱,并且我准备稍后为不一致的 git 回购副本付出代价。我还知道,从项目管理的角度来看,这不是 "proper" 方法,问题是我也必须考虑当前的项目时间。 "correct" 现在会导致失败。

问题: 敏感信息最终出现在已推送多年的提交消息中,随后该存储库被大量克隆和分支。我们稍后会更正主要的 repo 和克隆(例如,重新定位提交,然后在我们有时间时尽快重新定位后续开发),但我必须从 Origin 中删除信息 - 现在。

我想: - 在不改变id的情况下改变或删除commit message内容;如果导致不一致应该无关紧要,因为该提交非常旧并且非常非常不可能 rebased/cherrypicked/filter-branched。 要么 - 或者核对提交,将其父项重新连接为子提交的父项,而不重写后者的 id(同样的不一致问题,是的)。

或类似的东西。

我偶然发现了 git-replace 手动输入,但我不完全清楚它是否需要原始提交(内容)来保留,或者如果它可以 "nuked"(或对后续克隆操作隐藏)。

提前致谢;)

ps:你可能会想我为什么不继续 post 原来的话题;那是因为我要问的绝对是 "non-canon",我不想 "deceive" 不属于我特殊情况的用户做非常危险的事情。

是的,我们将保留原始存储库的多个备份ps以防万一。

简单地说:不,这是不可能的。你将重写历史,当你重写历史时,你会生成一个新的 SHA。随后,所有引用现在替换的提交或提交的提交都将挂起。

有一些工具可以减轻这种操作的痛苦,例如 BFG Repo Cleaner,但最终仍然涉及:

  • 访问包含具有敏感信息的文件的提交
  • 正在编辑文件
  • 提交更改
  • 强制更改通过它的所有子项传播

这样做本身不会丢失任何数据;你只需摆脱有毒的提交。

您不能简单地替换提交内容的原因是 SHA is computed for a commit - 它不仅包括文件内容,还包括时间和日期创建时间。

最后,删除信息仍然是一项耗时的操作,因为您必须协调从其他人的盒子中删除信息。在任何情况下,考虑该秘密已泄露并更改任何使用它的系统。

有趣 - 我不知道 git replace。以下 可能 有效,但我不确定是否存在某些命令会被它抛出。假设错误提交的哈希是 66ba4c10a3d85f33c1123b5107d5857d646c13eb.

git checkout 66ba4c10a3d85f33c1123b5107d5857d646c13eb
git commit --amend -m "Safe message."
git replace 66ba4c10a3d85f33c1123b5107d5857d646c13eb `rev-parse HEAD`
rm .git/objects/66/ba4c10a3d85f33c1123b5107d5857d646c13eb

前三个命令创建清理后的提交并进行替换。最后一个命令物理删除原始提交对象(注意散列前两个字符后的斜杠)。我运行 git fsck 之后,它没有抱怨,所以看起来是安全的。

但是,这仅在提交尚未包含在 packfile 中时有效,而您的提交很可能已包含在其中。您应该查看 git prunegit repack。此外,我不确定此替换是否会通过 git pushgit pull 传播。即使是,删除也不会,所以rm/prune/repack需要重复(after替换)所有其他回购协议。仍然不确定如何确认提交对象是否完全消失。