是的,这是不可能的。我会给你四种方法来重写历史以从中删除文件...
⚠️ 如果出于安全原因需要从 git 历史记录中删除文件,则应按照Remove sensitive files and their commits from Git history 中的步骤操作。
交互式变基
如果你还不是 git pro,我建议你使用这种方法,即使有更多的手动步骤。
既然你想重写 10 个提交,你可以这样做:
git rebase -i HEAD~10
这将打开一个“待办事项列表”,列出从 HEAD~10 开始的提交,这将是最后 10 个提交。如果您将文件保持原样并关闭它,git rebase 将按照显示的顺序重播这 10 次提交,并且没有任何改变。但是通过编辑待办事项列表,您可以完全控制发生的事情。您可以重新排序任何行,从而重新排序提交。您可以删除一行或将pick 替换为skip 以跳过提交。或者您可以将“pick”替换为另一条指令。所有这些都在 todo 文件本身中进行了解释,因此您不必记住所有选项。
在您的情况下,您希望修改每个提交以删除一个文件。将每个pick 替换为edit 或只是e。关闭文件。然后 Git rebase 将重播这些提交,但会在每个提交后停止并允许您对其进行修改。
在第一个上,您将git rm 要删除的文件,然后git commit --amend。 new 第一次提交将不再包含该文件。您现在可以继续下一个。
ℹ️ 在交互式 rebase 期间,您始终可以输入 git status,它会向您显示 rebase 的当前状态,并提示您可能接下来要做什么。 p>
继续下一个提交:git rebase --continue。 Rebase 将尝试重播下一次提交,但会因为冲突而停止:在您新重写的分支上,该文件不再存在,但在第二次重播时,该文件已被修改。
在这种情况下,您只需再次删除文件,然后git add . 以使用此选择的冲突解决方案更新暂存索引即可解决冲突。然后git rebase --continue 告诉 rebase 重试提交第二次提交,然后继续进行第三次提交。
ℹ️ 如果您认为自己犯了错误或改变主意,请运行git rebase --abort,一切都会恢复到以前的状态。
对于所有剩余的提交,同样的冲突将再次发生,您对所有提交执行相同的操作:
- 删除文件
-
git add .记录你的决心
-
git rebase --continue 继续前进。
rebase 完成后,您当前的分支 HEAD 现在将指向一系列新的 10 次提交,而没有您想要删除的文件。原始提交仍然存在,但如果没有 refs 指向它们,它们最终会从 git 数据库中删除。
将 10 个提交压缩成一个没有文件的提交
如果您将 10 次提交压缩为 1 次,您可以跳过修改它们。如果您不需要历史记录来反映 10 次单独的编辑,如果您不关心历史记录是否只有一次提交以及所有组合更改,那么这是给你的票:
git reset HEAD~10
这会将当前分支的HEAD 移回 10 个提交。您在这 10 次提交中所做的所有更改仍将保留在工作树中,但不再提交到 git。您现在可以删除您不想要的文件和git add . 其余的文件,然后提交。 或,如果您不想删除该文件,只需将其保留在 git 之外,只需 git add <the other 9 files> 并提交即可。
git 过滤器分支
这是高级用户方式。它更加自动化。但我建议所有非 git-guru 都使用上面的git rebase,因为这是成为大师的好方法。
git docs for filter-branch 提供了从每次提交中删除文件的说明,因此请遵循这些说明。
git-filter-repo
我从未使用过git-filter-repo(还),但它非常推荐(显然是 git 维护者)。它本质上是一个对用户更友好的git filter-branch 版本。 @LeGEC 在评论中提供了特定命令,所以我在这里添加它:
git filter-repo --invert-paths --path file/to/ignore
祝你好运!