2012-06-30 178 views
10

我需要一個提交不再在提交的git數據庫。我需要能夠去除犯abc123...這樣git checkout abc123...返回error: pathspec 'abc123...' did not match any file(s) known to git.完全刪除git數據庫提交

的QA How to delete a 'git commit'回答了這個部分,如如何刪除一個引用從HEAD提交,但不包括查找所有分支中的提交是存在的,也不包括提交和清除提交後一旦作出了懸而未決的承諾。

我該怎麼做到這一點?

+0

什麼是在犯呢?你是否希望這種情況仍然發生,但是在下面的提交中呢?或者是,例如添加一個你想完全刪除的文件?無論哪種方式,你都必須使用某種形式的歷史重寫。 –

+0

我發現[這個有用的帖子](https://wincent.com/wiki/Obliterating_a_Git_commit)通過在網上搜索「git obliterate」。 –

回答

10
  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 
    
+0

如果存儲庫啓用了reflog,這實際上不會移除提交對象。 – Amber

+0

[This](https://wincent.com/wiki/Obliterating_a_Git_commit)包括刪除reflog。 –

+0

添加了非手動引用日誌清理到答案(雖然沒有嘗試過) –

2
  1. 確保沒有裁判需要犯下(之前重置回,或重訂出來)
  2. 刪除.git/objects對象(這將是一個的頭兩個字符命名的文件夾中散列,文件名將是散列的其餘部分)。

但是請注意,如果您將此提交推送到公共存儲庫,則將其從本地刪除將不會將其從遠程刪除。

+0

哎。考慮到這種情況下有'git prune'命令,手動觸摸'.git/objects'可能不是一個好主意。 –

+0

@AlexanderGladysh'git prune'涉及更多步驟以確保對象實際上被刪除(例如確保清除reflog等)。直接刪除目標文件不需要這些步驟,只要不依賴於提交任何內容,通常都是安全的。 – Amber

+0

'git reflog expire --all BRANCH'應該這樣做,不是嗎? –