完全从git数据库中删除提交


Completely remove commit from git database

本问题已经有最佳答案,请猛点这里访问。

我需要一个commit,它不再位于commits的git数据库中。我需要能够删除commit abc123...,以便git checkout abc123...返回error: pathspec 'abc123...' did not match any file(s) known to git.

QA如何删除一个"git commit"部分地回答了这一点,例如如何从头部删除对commit的引用,但是它不包括查找提交存在的所有分支,也不包括在提交完成后过期和清除提交。

我怎样才能做到这一点?


  • 列出包含提交的所有分支:

    1
    git branch --contains COMMITSHA
  • 从这些分支中删除提交:

    1
    2
    3
    git checkout BRANCH
    git rebase -i COMMITSHA^
    # delete line with commit and save

    如果在任何远程中跟踪已更改的分支,请将其推到该分支并进行覆盖:

    1
    git push --force REMOTE BRANCH

    例如:

    1
    git push --force origin master

    (注意,根据您的开发过程,提交也可能出现在未跟踪的远程分支中。)

  • 清除提交,使其无法从本地回购中恢复:

    1
    2
    git reflog expire --all BRANCH1 BRANCH2 # list all branches you changed
    git prune --expire now

    请注意,您还必须在所有具有此提交的远程存储库上运行此命令。如果您无法访问远程回购,则必须交叉处理--提交最终将自行到期,并由git gc清除。

    请注意,上述命令将删除git repo中的所有悬空对象以及分支更改的所有历史记录,因此您将无法恢复(通过非法医手段)运行前丢失的任何内容。

  • 告诉所有合作者获取更改的分支并更新他们可能基于它们的任何工作。他们应该这样做:

    1
    git fetch REMOTE

    对于基于您在上面更改的分支的每个分支(如果分支在本地拥有它,则包括分支本身):

    1
    2
    3
    git checkout BRANCH
    git rebase REMOTE/BRANCH
    git reflog expire --all BRANCH

    完成后:

    1
    git prune --expire now

  • 确保没有引用需要提交(重新设置为提交前的状态,或重新设置为退出状态)
  • .git/objects中删除对象(它将位于以哈希前两个字符命名的文件夹中,文件名将是哈希的其余部分)。
  • 但是,请注意,如果将此提交推送到公共存储库,则在本地删除它不会从远程删除它。