2014-06-12 22 views
7

Posiadam repozytorium git z wartością null sha1 dla pozycji zatwierdzenia w drzewie, uniemożliwiając programowi FishEye indeksowanie repozytorium.Jak usunąć wpis z wartością null sha1 w drzewie Git

$ git fsck 
Checking object directoriies: 100%(256/256), done. 
warning in tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9: 
    contains entries pointing to null sha1 
Checking objects: 100% (416532/416532), done. 
Checking connectivity: 416532, done. 

Szukasz danego drzewa dają mi następujący wynik:

$ git ls-tree db22a6 
100644 blob e615f18b55a39f2719112ce209c2505dd92d8e75 .gitignore 
100644 blob ac852f06c5a04420356c1d5efca44d9a864e78b0 .project 
160000 commit 0000000000000000000000000000000000000000 SomeDirectory 
100644 blob 631c17e28026261a2ccf6bc570842cf4af9f181c GoDeploy.bat 
100644 blob 40e992ab5c3868af2910135c3ac4610c3646e7f8 pom.xml 

patrząc w historii, znalazłem, że SomeDirectory był początkowo modułem git i że zobowiązują się, że wydaje się powodować jest to problem, który usunął zarówno .gitmodules i. Teraz istnieje prawdziwy katalog o nazwie SomeDirectory w dokładnie tym samym miejscu, w którym był winowajca.
I chociaż mogę jeszcze spróbować naprawić uruchomić git filter-branch aby zobaczyć, co chciałbym skończyć, ale to nie działa:

$ git filter-branch --force --index-filter \ 
$ 'git rm --cached --ignore-unmatch SomeDirectory' \ 
$ --prune-empty --tag-name-filter cat -- --all 
[... striped out for clarity] 
Rewrite c571a3ec94e9f84471577bac41ac7375c729ef08 (76/18522)error: 
    cache enttry has null sha1: SomeDirectory 
fatal: unable to write new index file 
Could not initialize the index 
[... striped out for clarity] 

Co mam próbować dalej, wiedząc, że nie ma kopii zapasowej, że "Jestem świadomy wcześniejszego zatwierdzenia, które powoduje problem.

Odpowiedz

13

Otrzymana wiadomość sugeruje, że było tylko jedno drzewo ze złym modułem częściowym. W takim przypadku trzeba bardzo niewiele posprzątać. Można utworzyć nową stałą drzewo, które nie mają tego problemu:

 
$ git ls-tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 | 
> sed -e '/0\{40\}/d' | 
> git mktree 
(new tree SHA1 here) 

Twoje pytanie pokazuje już wyjście git ls-tree. sed usuwa linię ze złym modułem częściowym i tworzy z obiektu nowy obiekt drzewa.

Gdy masz stały drzewa, można utworzyć stałą popełnić przy użyciu tego drzewa:

 
$ git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08 | 
> sed 's/db22a67df70dc4ff90ec4cd666da91e9c2cb0d9/(new tree SHA1 here)/' | 
> git hash-object -t commit -w --stdin 
(new commit SHA1 here) 

git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08 drukuje problematyczne popełnić obiektu w formie tekstowej. Zacznie się od tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 i będzie kontynuowane z resztą informacji o zatwierdzeniu (rodzic, autor, przekazujący, komunikat zatwierdzenia). Numer sed zastępuje odniesienie do starego drzewa przez nowe. git hash-object -t commit -w --stdin tworzy nowy obiekt commit z wyniku, zapisuje go w repozytorium i wypisuje jego identyfikator.

Kiedy już ustalona popełnić, można użyć git replace:

 
$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here) 

To nie zmienia jednak niczego, ale mówi, że gdy Git byłoby czytać popełnić c571a3ec94e9f84471577bac41ac7375c729ef08, powinien przeczytać nowy obiekt popełnić zamiast.

I na koniec użyj git filter-branch, aby stał się stały. To przechodzi przez wszystkie zatwierdzenia, czyta je i zapisuje je. Zwykle, bez żadnych opcji modyfikowania zatwierdzeń, nie będzie to miało większego wpływu, ale z powodu wcześniejszego git replace powoduje to, że wszystkie zatwierdzenia z c571a3ec94e9f84471577bac41ac7375c729ef08 jako rodzicem zostaną ponownie zapisane, aby odwoływać się do nowego zatwierdzenia zamiast, wszystkie zatwierdzenia, które odnoszą się również do tych, które zostały ponownie napisane itp.

+0

Próbowałem tego na podobnym repozytorium, ale nie działało. Po uruchomieniu 'git filter-branch', mówi mi, że nie można go wykonać z powodu uszkodzonego wpisu w pamięci podręcznej. 'git rev-parse HEAD' pokazuje, że GIT nie zwrócił uwagi na operację wymiany i nadal ma HEAD ustawiony na niezamierzone złamane zatwierdzenie. I nie mogę sprawdzić innej gałęzi bez utraty zmian w katalogu roboczym. –

+0

@MarkGreen Podejrzewam, że jest tam trochę szczegółów, które sprawiają, że na tyle różni się od tego pytania, że ​​potrzebuje zmienionego lub nawet innego podejścia, a jeśli tak, to może to być dobre nowe pytanie. Jeśli możesz opublikować to jako takie (oczywiście z wystarczającą ilością szczegółów, aby można było samodzielnie odpowiadać), z przyjemnością przyjrzę się temu. – hvd

+0

Byłoby fantastycznie, gdyby to miało również jakieś wyjaśnienie, co robią polecenia. Ja [czuję się tak] (https://xkcd.com/1597/) za każdym razem, gdy mam problem z gitem i kończę w SO –

0

Być może będzie działać z interaktywnym rebase, aby zmodyfikować zatwierdzenie, które zawiera kłopotliwe odniesienie do zatwierdzenia SomeDirectory, np.

$ git branch backup_branch  # To be able to revert if not satisfied 
$ git rebase -i db22a6^   # From parent to db22a6 
... 
# You then select Edit for commit db22a6 in the editor 
... 
$ git reset HEAD^    # Reset the commit db22a6 but not its changes 
$ git status 
... 
# should list as modified: .gitignore .project SomeDirectory GoDeploy.bat pom.xml 
... 
$ git checkout SomeDirectory  # Cancel the troublesome change 
$ git add .gitignore .project GoDeploy.bat pom.xml 
$ git commit -m "your commit message" 
$ git rebase --continue 
+0

db22a6 jest SHA1 obiektu drzewa, a nie wadliwym zatwierdzeniem. W każdym razie próbowałem zrobić to z c571a3, ale bez powodzenia. Nie wykona zmiany i oznaczy ją jako konflikt z następnym zatwierdzeniem. – gizmo