重写 git 历史记录,重写添加和删除提交

Rewriting git history, rewrite addition and removal commits

我有一个本地分支,我在其中进行了一些开发,提交历史非常糟糕,所以我要返回并重新设置以整理并在推送之前将其保持在合理的状态。

假设我有提交 A、B、C、D、E。在提交 B 中,我添加了一些我想保留的有用代码,但我也添加了一些调试代码。后来我删除了 D 中的调试代码。从历史记录中完全删除它的最佳方法是什么(该代码没有任何用处,所以如果可能的话我不希望它出现在历史记录中)?

我试过在 A 处变基,在没有代码的情况下重写 B 处的提交,但是 C 和 D 需要在每个变基步骤中进行手动干预。 最好将 B,D 拆分为 B-keep 和 B-remove 以及 D-keep 和 D-remove 然后删除这两个提交吗?是否有其他方法可以在添加然后删除代码后进行清理?

我想以看起来像 A、B(有用)、C、D(有用)、E 的历史结束,然后我可能会将其压缩为 A、B、E,例如,在这个阶段我只想从历史记录中删除调试代码。

正在应用您的 Q 更新:

您可以使用此工具遍历提交并删除不需要的提交。 https://rtyley.github.io/bfg-repo-cleaner/

阅读示例部分了解如何使用它。

git filter-branch快很多,但效果一样。


一些其他选项:

阅读此处详细了解每个选项:

git rebase -i

编辑您要清理的每个提交并从中删除您的代码。如果你没有太多提交,这很有用,如果你这样做 - 使用 filter-branch 或 'bfg-repo-cleaner'

git checkout

git checkout <commit_id>

git reflog

您也可以随时使用 reflog

git reflog
git checkout HEAD@{...}

这会让你回到你想要的提交


git reset HEAD --hard <commit_id>

"Move" 你的头回到想要的提交。

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • 注:(Since Git 2.7)
    您也可以使用 git rebase --no-autostash

git checkout

git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

这将签出指向所需提交的新分支

通常的修复方法是使用 git filter-branch, combine with sed, to delete line matching a pattern:

# find out the desired file and execute sed on it to find out
# where is the debug code inside the file
git filter-branch --tree-filter "find . -type f -exec sed -i -e 's/pattern with debug/d' {} \;" -- A~..

您可以细化查找条件,以仅查找具有特定扩展名的文件 (--name '*.java')

这将从历史记录中删除调试代码,无需对中间提交进行手动干预。
当然,这将重写所有相关提交的 SHA1,迫使你做一个 git push --force,所以如果你不是一个人在做那个 repo,请务必将你的分支即将发生的重置传达给其他合作者。

如果提交 D 它只是从提交 B 中删除调试代码,那么您可以使用 rebase -i 重新排序提交和压缩,例如,当您开始变基时,您会看到这里:

pick c9a8ee8 B
pick f533903 C
pick c66cc92 D
pick 647ab90 E

现在你需要在提交B之后移动提交D,你只需要编辑文本内容:

pick c9a8ee8 B
pick c66cc92 D
pick f533903 C
pick 647ab90 E

最后您需要将 pick 更改为 squash 以提交 D,这是它的外观:

pick c9a8ee8 B
squash c66cc92 D
pick f533903 C
pick 647ab90 E

完成变基后,提交 D 将成为提交 B 的一部分。