从 git 数据库中完全删除提交 [重复]
Posted
技术标签:
【中文标题】从 git 数据库中完全删除提交 [重复]【英文标题】:Completely remove commit from git database [duplicate] 【发布时间】:2012-07-01 13:04:09 【问题描述】:我需要一个提交才能不再出现在提交的 git 数据库中。我需要能够删除提交 abc123...
以便 git checkout abc123...
返回 error: pathspec 'abc123...' did not match any file(s) known to git.
QA Delete commits from a branch in Git 部分回答了这个问题,例如如何从 HEAD 中删除对提交的引用,但它不包括查找提交所在的所有分支,也不包括过期和清除提交一旦它被做了一个悬空提交。
我将如何实现这一目标?
【问题讨论】:
提交中做了什么?您是否希望这种情况仍然发生,但在以下提交中?或者做到了,例如添加要完全删除的文件?无论哪种方式,您都必须使用某种形式的历史重写。 我通过在网上搜索“git obliterate”找到了this useful post。 【参考方案1】:列出所有包含该提交的分支:
git branch --contains COMMITSHA
从这些分支中删除提交:
git checkout BRANCH
git rebase -i COMMITSHA^
# delete line with commit and save
如果在任何远程跟踪更改的分支,则使用覆盖将其推送到那里:
git push --force REMOTE BRANCH
例如:
git push --force origin master
(请注意,根据您的开发过程,提交也可能出现在未跟踪的远程分支中。)
清除提交,使其无法从本地存储库中恢复:
git reflog expire --all BRANCH1 BRANCH2 # list all branches you changed
git prune --expire now
请注意,您还必须在具有此提交的所有远程存储库上运行此命令。如果您无权访问远程仓库,则必须双手合十——提交最终会自行过期,并被git gc
清除。
请注意,上述命令将从 Git 存储库中删除 所有 悬空对象以及分支更改的所有历史记录 - 因此您将无法恢复(通过非取证方式)之前丢失的任何内容运行。
告诉所有协作者获取更改的分支并更新他们可能基于它们所做的任何工作。他们应该这样做:
git fetch REMOTE
对于基于您在上面更改的分支的每个分支(包括分支本身,如果他们在本地拥有它):
git checkout BRANCH
git rebase REMOTE/BRANCH
git reflog expire --all BRANCH
完成后:
git prune --expire now
【讨论】:
如果存储库启用了 reflogs,这实际上不会删除有问题的提交对象。 This 也包括删除 reflogs。 在答案中添加了非手动 reflog 清理(虽然没有尝试过......) @AlexanderGladysh 你不应该使用git rebase -i --preserve-merges COMMITSHA^
来避免提交图的扁平化吗?【参考方案2】:
-
确保没有 refs 需要该提交(重置回它之前,或将其变基)
从
.git/objects
中删除对象(它将位于以哈希的前两个字符命名的文件夹中,文件名将是哈希的其余部分)。
但是请注意,如果您将此提交推送到公共存储库,则在本地将其删除不会将其从远程删除。
【讨论】:
哎哟。手动触摸.git/objects
可能不是一个好主意——考虑到这种情况下有git prune
命令。
@AlexanderGladysh git prune
涉及更多步骤以确保实际删除对象(例如确保清除 reflog 等)。直接删除目标文件不需要这些步骤,只要您不依赖任何提交,通常是安全的。
git reflog expire --all BRANCH
应该这样做,不是吗?以上是关于从 git 数据库中完全删除提交 [重复]的主要内容,如果未能解决你的问题,请参考以下文章