18

我需要一个提交才能不再出现在提交的 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 中删除对提交的引用,但它不包括查找提交所在的所有分支,也不包括过期和清除一旦它成为一个悬空提交,就提交。

我将如何实现这一目标?

4

2 回答 2

16
  1. 列出所有包含提交的分支:

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

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

    如果在任何远程跟踪更改的分支,请使用覆盖将其推送到那里:

    git push --force REMOTE BRANCH
    

    例如:

    git push --force origin master
    

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

  3. 清除提交,使其无法从本地存储库中恢复:

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

    请注意,您还必须在具有此提交的所有远程存储库上运行此命令。如果您无权访问远程仓库,则必须双手合十——提交最终将自行过期并被git gc.

    请注意,上述命令将从 Git 存储库中删除所有悬空对象以及所有分支更改的历史记录——因此您将无法恢复(通过非取证方式)在其运行之前丢失的任何内容。

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

    git fetch REMOTE      
    

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

    git checkout BRANCH
    git rebase REMOTE/BRANCH
    git reflog expire --all BRANCH
    

    完成后:

    git prune --expire now
    
于 2012-06-30T06:51:56.640 回答
2
  1. 确保没有 refs 需要该提交(重置回它之前,或者重新设置它)
  2. 从中删除对象.git/objects(它将位于以哈希的前两个字符命名的文件夹中,文件名将是哈希的其余部分)。

但是请注意,如果您将此提交推送到公共存储库,则在本地将其删除不会将其从远程删除。

于 2012-06-30T03:59:17.220 回答