2013-02-10 47 views
3

注意:我沒有任何此存儲庫的損壞前克隆。我相信我的情況與這裏描述的其他人不同,因爲我錯過了一棵樹,而不是一個blob。Git恢復:「目標文件爲空」。如何重新創建樹木?

發生了什麼事:

當我試圖克隆了LAN(通過SSH)存儲庫,Git會返回一個錯誤,指出該庫已損壞:

remote: error: object file ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4 is empty 
remote: fatal: loose object 2e223ce259e9e33998d434acc778bc64b393d5d4 (stored in ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4) is corrupt 
error: git upload-pack: git-pack-objects died with error. 
fatal: git upload-pack: aborting due to possible repository corruption on the remote side. 
remote: aborting due to possible repository corruption on the remote side. 

我在什麼地方發現git fsck可用於診斷腐敗,但它並沒有告訴我任何新的東西:

git fsck --full 
error: object file ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4 is empty 
fatal: loose object 2e223ce259e9e33998d434acc778bc64b393d5d4 (stored in ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4) is corrupt 

我試圖克隆reposito本地(使用--no-hardlinks)查看會發生什麼,但我得到的結果完全相同。

然後我在this question迷迷糊糊的,誰回答的傢伙剛剛刪除的空文件(步驟3),所以我這樣做(即我已經刪除了子目錄​​文件223ce259e9e33998d434acc778bc64b393d5d4)。

git fsck一遍,我看到:

Checking object directories: 100% (256/256), done. 
broken link from tree 838e437f371c652fa4393d25473ce21cbf697d7a 
       to tree 2e223ce259e9e33998d434acc778bc64b393d5d4 
dangling commit 54146bc0dc4eb3eede82a0405b749e05c11c5522 
missing tree 2e223ce259e9e33998d434acc778bc64b393d5d4 
dangling commit 864864feec207786b84158e526b2faec7799fd4e 
dangling blob d3cfd7cc7718d5b76df70cf9865db01c25181bfb 

所以,現在有樹木838e437f37問題。這不是上面提到的那個傢伙發生的事情,所以我去谷歌搜索,發現some information from Linus

所以,我做了git ls-tree 838e437f371c652fa4393d25473ce21cbf697d7a和輸出有這樣一行:

040000 tree 2e223ce259e9e33998d434acc778bc64b393d5d4 moje 

現在,「moje」是目錄(不像萊納斯解釋說,這是一個文件中的示例)。我想這就是爲什麼Linus建議下一步,git hash-object moje返回fatal: Unable to hash moje

但無論如何,這只是一個小的機會,這是我所需要的,所以我進一步尋找。我跑了git log --raw --all --full-history -- moje/,根據Linus的指南,應該有一個提交列出2e223作爲一些內容的SHA-2散列,但沒有。並且列表以

fatal: unable to read source tree (2e223ce259e9e33998d434acc778bc64b393d5d4) 

我試着查看錯誤之前列出的最後一個提交,但是我沒有找到這個哈希。我見過this,但它沒有幫助我,可能是因爲有問題的版本和工作樹的當前狀態之間的一些變化。

有一件事情可能很重要:在moje/裏面有一個目錄cli/,它是一個Git倉庫本身(一個子模塊)。我已經在那裏尋找有問題的SHA-2哈希,但還沒有找到它。

我該怎麼辦?

+1

很好的意見,但你也可以將它張貼作爲自己的回答你的問題。你甚至可以接受你自己的答案,但不要這樣做;)Chronial的答案贏得了公平和正確的「刻度標記」。 – VonC 2013-02-13 11:45:49

+1

當然,Chronial的答案將保持公認的答案:)我已經將解決​​方案移至單獨的答案中,正如所建議的那樣。 – 2013-02-14 09:21:27

回答

2

使用此命令來獲取包含丟失的樹提交列表:

git rev-list --all | xargs -l -I '{}' sh -c 'if git ls-tree -rt {} > /dev/null 2>&1 ; then true; else git log --oneline -1 {}; git ls-tree -r -t {} | tail -1; fi' 

現在,您需要重新創建丟失的樹,通過將完全相同的內容,在那裏你必須在那裏返回然後再將該樹添加到回購。最簡單的方法是重新創建內容,然後將它們提交到回購站(之後您可以刪除該提交)。

+0

謝謝,它工作!我發現了有問題的提交,查看了它的父代和未損壞的第一個後代之間的差異,並設法重新創建樹。我將編輯我的問題以詳細顯示解決方案。 – 2013-02-13 09:51:29

+0

很高興我能幫到你。不過,我認爲您應該將解決方案的細節移至單獨的答案。 (是的,你可以回答你自己的問題)。 – Chronial 2013-02-13 11:45:20

+0

更新:根據Chronial的建議,我將解決方案移至[單獨的答案](http://stackoverflow.com/a/14871420/2058424)。 – 2013-02-14 11:21:24

5

命令(由Chronial建議的)

git rev-list --all | xargs -l -I '{}' sh -c 'if git ls-tree -rt {} > /dev/null 2>&1 ; then true; else git log --oneline -1 {}; git ls-tree -r -t {} | tail -1; fi' 

返回的第一提交其依賴於丟失2e223ce對象 - 其SHA-2的散列是499b8fb。它的父母是沒事的(我可以看到它的內容,檢查出來等等),並且我也能夠在破壞後的下一個提交(89b0fc4)後檢查下一個提交。

現在我需要看到之間發生了什麼樣的變化這兩個「好」的承諾 - 這很簡單:git diff 499b8fb~ 89b0fc4返回

diff --git a/somefile b/somefile 
deleted file mode 100644 
index f5d1e1e..0000000 
--- a/somefile 
+++ /dev/null 
@@ -1,79 +0,0 @@ 
[ contents of the deleted "somefile"... ] 
diff --git a/moje/cli b/moje/cli 
index 640a825..c0b1a24 160000 
--- a/moje/cli 
+++ b/moje/cli 
@@ -1 +1 @@ 
-Subproject commit 640a825cd671dfba83601d6271e7e027665eaca8 
+Subproject commit c0b1a24aa246289831ec7db3a8596376db1f625a 

現在我知道了不好的父母之間的承諾和良好的提交文件somefile已刪除,子模塊的HEAD從640a825更改爲c0b1a24。我去了子模塊庫,並要求之間發生了什麼事的提交這兩個:

git log --oneline 640a825..c0b1a24 
其返回

c0b1a24 <commit message> 
8be9433 <commit message> 
02564e1 <commit message> 

現在我知道四件事499b8fb~89b0fc4之間發生

  • somefile被刪除
  • /moje/cli HEAD被更改爲fr OM 640a82502564e1
  • /moje/cli HEAD從02564e1變更爲8be9433
  • /moje/cli HEAD從8be9433改爲c0b1a24

我不知道在哪一部分499b8fb發生(壞提交),以及在89b0fc4。但幸運的是沒有那麼多的可能性,所以我只嘗試了其中的每一種。對於每個組合,我都進行了一次提交,以便Git計算適當的對象並將它們存儲在數據庫中。原來,當/moje/cli HEAD在8be9433,git commit導致創建缺少2e223ce對象 - 萬歲!注意:如果你有類似的情況,並且你正在四處尋找哪些提交是好的以及Git可以告訴你關於它們的信息,請記住,能夠提交checkout和提交show這是兩個不同的事情。例如,我最初認爲,如果git show somesha引發錯誤,則意味着somesha提交已損壞,並且我無法將其用於任何操作。原來這是錯誤的:雖然git show 89b0fc4返回一個錯誤,我可以git checkout 89b0fc4git diff 499b8fb~ 89b0fc4工作。

我想這是因爲git show somesha顯示somesha引入的變化,因爲Git需要讀取先前提交(在這種情況下是損壞的)的內容。顯然,Git不需要看以前的提交來檢查一個。

(我設法這得益於做Chronial's answer - !榮譽給他有人勸我張貼這是我自己的答案。)

+1

優秀的反饋。 +1 – VonC 2013-02-14 09:23:33

+0

非常感謝您爲解決問題而制定的步驟!幫助我保存損壞的回購的歷史。 – ramiro 2014-06-11 13:08:42

+0

感謝您的答覆,但對我來說確實返回了同樣的錯誤: ''' 錯誤:目標文件的.git /反對/ 9C/e0546f12bffd80d73f648586a9d399b27ad201是EMP TY 錯誤:目標文件的.git /對象/ 9C/e0546f12bffd80d73f648586a9d399b27ad201是EMP TY 致命:鬆散對象9ce0546f12bffd80d73f648586a9d399b27ad201(存儲在的.git/OBJ 學分/ 9C/e0546f12bffd80d73f648586a9d399b27ad201)已損壞 ''' – 2014-07-29 06:29:02