Miałem awarię dysku twardego, która spowodowała uszkodzenie niektórych plików repozytorium Git. Podczas pracy git fsck --full
otrzymuję następujące dane wyjściowe:
error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted
Mam kopie zapasowe repozytorium, ale jedyna kopia zapasowa zawierająca plik pakietu ma już uszkodzony. Myślę więc, że muszę znaleźć sposób na pobranie pojedynczych obiektów z różnych kopii zapasowych i jakoś poinstruować Git, aby utworzył nowy pakiet z tylko poprawnymi obiektami.
Czy możesz mi podpowiedzieć, jak naprawić moje repozytorium?
git
corruption
data-recovery
chrześcijanin
źródło
źródło
.git
folderu oczywiście) do świeżo sklonowanego repozytorium ... a potemgit status
w nowym repozytorium ... git poprawnie wykrywa wszystkie zmiany w moich plikach i mogę ponownie rozpocząć pracę.Odpowiedzi:
W niektórych poprzednich kopiach zapasowych złe obiekty mogły być spakowane w innych plikach lub mogą być jeszcze luźnymi obiektami. Więc twoje obiekty mogą zostać odzyskane.
Wygląda na to, że w twojej bazie danych jest kilka złych obiektów. Możesz więc zrobić to ręcznie.
Z powodu
git hash-object
,git mktree
agit commit-tree
nie pisać, ponieważ obiekty znajdują się w opakowaniu, a potem zacznij to robić:(Twoje paczki są przenoszone z repozytorium i ponownie w nim rozpakowywane; tylko dobre obiekty są teraz w bazie danych)
Możesz to zrobić:
i sprawdź typ obiektu.
Jeśli typ to blob: pobierz zawartość pliku z poprzednich kopii zapasowych (za pomocą
git show
lubgit cat-file
lubgit unpack-file
; wtedy możeszgit hash-object -w
przepisać obiekt w bieżącym repozytorium.Jeśli typ to drzewo: możesz użyć
git ls-tree
do odzyskania drzewa z poprzednich kopii zapasowych; następniegit mktree
zapisać go ponownie w bieżącym repozytorium.Jeśli typ jest popełnić: to samo z
git show
,git cat-file
igit commit-tree
.Oczywiście wykonałbym kopię zapasową oryginalnej kopii roboczej przed rozpoczęciem tego procesu.
Zobacz też, jak odzyskać uszkodzony obiekt blob .
źródło
.git/objects/pack/
jest pustyBanengusk stawia mnie na właściwej drodze. W celu uzyskania dalszych informacji chcę opublikować kroki, które podjąłem, aby naprawić uszkodzenie repozytorium. Miałem szczęście znaleźć wszystkie potrzebne obiekty albo w starszych paczkach, albo w kopiach zapasowych repozytorium.
# Unpack last non-corrupted pack $ mv .git/objects/pack .git/objects/pack.old $ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack $ git log fatal: bad object HEAD $ cat .git/HEAD ref: refs/heads/master $ ls .git/refs/heads/ $ cat .git/packed-refs # pack-refs with: peeled aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master $ git fsck --full error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1 error: refs/heads/master does not point to a valid object! missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919 missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc # Copy HEAD object from backup of repository $ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa # Now copy all missing objects from backup of repository and run "git fsck --full" afterwards # Repeat until git fsck --full only reports dangling objects # Now garbage collect repo $ git gc warning: reflog of 'HEAD' references pruned commits warning: reflog of 'refs/heads/master' references pruned commits Counting objects: 3992, done. Delta compression using 2 threads. fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232) error: failed to run repack # Check reflogs... $ git reflog # ...then clean $ git reflog expire --expire=0 --all # Now garbage collect again $ git gc Counting objects: 3992, done. Delta compression using 2 threads. Compressing objects: 100% (3970/3970), done. Writing objects: 100% (3992/3992), done. Total 3992 (delta 2060), reused 0 (delta 0) Removing duplicate objects: 100% (256/256), done. # Done!
źródło
Najpierw wypróbuj następujące polecenia (w razie potrzeby uruchom ponownie):
A potem nadal masz problemy, spróbuj:
usuń wszystkie uszkodzone obiekty, np
usuń wszystkie puste przedmioty, np
sprawdź wiadomość „uszkodzony link”:
Dzięki temu dowiesz się, z jakiego pliku pochodzi uszkodzony obiekt blob!
aby odzyskać plik, możesz mieć naprawdę szczęście i może to być wersja, którą już wypisałeś w swoim drzewie roboczym:
ponownie, a jeśli wyprowadza brakujący SHA1 (4b945 ..), wszystko gotowe!
zakładając, że zepsuta była jakaś starsza wersja, najłatwiej to zrobić:
a to pokaże ci cały dziennik dla tego pliku (pamiętaj, że drzewo, które miałeś, może nie być drzewem najwyższego poziomu, więc musisz samodzielnie dowiedzieć się, w którym podkatalogu się znajduje), a następnie możesz teraz odtworzyć ponownie brakuje obiektu z hash-object.
aby uzyskać listę wszystkich referencji z brakującymi zatwierdzeniami, drzewami lub blobami:
Może nie być możliwe usunięcie niektórych z tych referencji za pomocą zwykłych poleceń branch -d lub tag -d, ponieważ zginą, jeśli git zauważy uszkodzenie. Zamiast tego użyj polecenia hydraulicznego git update-ref -d $ ref. Zauważ, że w przypadku lokalnych gałęzi, to polecenie może pozostawić nieaktualną konfigurację gałęzi w .git / config. Można go usunąć ręcznie (poszukaj sekcji [branch "$ ref"]).
Po tym, jak wszyscy sędziowie są czyste, w reflogu nadal mogą być zepsute zatwierdzenia. Możesz wyczyścić wszystkie reflogi za pomocą git reflog expire --expire = now --all. Jeśli nie chcesz stracić wszystkich swoich reflogów, możesz przeszukać poszczególne referencje pod kątem uszkodzonych reflogów:
(Zwróć uwagę na dodaną opcję -g do git rev-list.) Następnie użyj git reflog expire --expire = now $ ref na każdym z nich. Kiedy wszystkie zepsute referencje i reflogs znikną, uruchom git fsck --full, aby sprawdzić, czy repozytorium jest czyste. Wiszące obiekty są w porządku.
Poniżej możesz znaleźć zaawansowane użycie poleceń, które potencjalnie mogą spowodować utratę danych w repozytorium git, jeśli nie są używane mądrze, więc zrób kopię zapasową, zanim przypadkowo wyrządzisz dalsze szkody swojemu gitowi. Spróbuj na własne ryzyko, jeśli wiesz, co robisz.
Aby przeciągnąć bieżącą gałąź na gałąź upstream po pobraniu:
Możesz także spróbować wyewidencjonować nowy oddział i usunąć stary:
Aby znaleźć uszkodzony obiekt w git do usunięcia, wypróbuj następujące polecenie:
W przypadku OSX użyj
sed -E
zamiastsed -r
.Innym pomysłem jest rozpakowanie wszystkich obiektów z plików paczek w celu ponownego wygenerowania wszystkich obiektów w .git / objects, więc spróbuj uruchomić następujące polecenia w swoim repozytorium:
Jeśli powyższe nie pomoże, możesz spróbować rsync lub skopiować obiekty git z innego repozytorium, np
Aby naprawić uszkodzoną gałąź podczas próby płatności w następujący sposób:
Spróbuj go usunąć i ponownie wyewidencjonuj z upstream:
W przypadku, gdy git wprowadzi cię w stan odłączony, wyewidencjonuj
master
i połącz z nim odłączoną gałąź.Innym pomysłem jest rekurencyjne przebudowanie istniejącego wzorca:
Zobacz też:
źródło
Oto kroki, które wykonałem, aby odzyskać dane z uszkodzonego obiektu typu blob.
1) Zidentyfikuj uszkodzony obiekt BLOB
Uszkodzony obiekt BLOB to 241091723c324aed77b2d35f97a05e856b319efd
2) Przenieś uszkodzoną kroplę w bezpieczne miejsce (na wszelki wypadek)
3) Zdobądź rodzica uszkodzonego obiektu blob
Hash nadrzędny to 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180 .
4) Pobierz nazwę pliku odpowiadającą uszkodzonemu obiektowi BLOB
Znajdź ten konkretny plik w kopii zapasowej lub w głównym repozytorium git (w moim przypadku jest to dump.tar.gz ). Następnie skopiuj go gdzieś w swoim lokalnym repozytorium.
5) Dodaj wcześniej uszkodzony plik do bazy danych obiektów git
6) Świętuj!
źródło
git ls-tree 9504a07fb803edfdf0c1dd99c5d561274af87982 error: Could not read 19505205fd1f219993da9b75846fff3cf432152d
, a ja również spróbowałem tego wszystkiego jeszcze raz bez kroku 2, a to zaowocowałogit ls-tree 9504a07fb803edfdf0c1dd99c5d561274af87982 error: inflate: data stream error (invalid stored block lengths) fatal: failed to read object 19505205fd1f219993da9b75846fff3cf432152d: Invalid argument
Git Checkout może faktycznie wybrać pojedyncze pliki z wersji. Po prostu nadaj mu skrót zatwierdzenia i nazwę pliku. Więcej szczegółowych informacji tutaj.
Myślę, że najłatwiejszym sposobem na bezpieczne rozwiązanie tego problemu jest przywrócenie najnowszej niezatwierdzonej kopii zapasowej, a następnie selektywne wybranie nieuszkodzonych plików z nowszych zatwierdzeń. Powodzenia!
źródło
Oto dwie funkcje, które mogą pomóc, jeśli kopia zapasowa jest uszkodzona lub masz kilka częściowo uszkodzonych kopii zapasowych (może się to zdarzyć, jeśli utworzysz kopię zapasową uszkodzonych obiektów).
Uruchom oba w repozytorium, które próbujesz odzyskać.
Standardowe ostrzeżenie: używaj tylko wtedy, gdy jesteś naprawdę zdesperowany i utworzyłeś kopię zapasową (uszkodzonego) repozytorium. To może niczego nie rozwiązać, ale powinno przynajmniej podkreślić poziom korupcji.
fsck_rm_corrupted() { corrupted='a' while [ "$corrupted" ]; do corrupted=$( \ git fsck --full --no-dangling 2>&1 >/dev/null \ | grep 'stored in' \ | sed -r 's:.*(\.git/.*)\).*:\1:' \ ) echo "$corrupted" rm -f "$corrupted" done } if [ -z "$1" ] || [ ! -d "$1" ]; then echo "'$1' is not a directory. Please provide the directory of the git repo" exit 1 fi pushd "$1" >/dev/null fsck_rm_corrupted popd >/dev/null
i
unpack_rm_corrupted() { corrupted='a' while [ "$corrupted" ]; do corrupted=$( \ git unpack-objects -r < "$1" 2>&1 >/dev/null \ | grep 'stored in' \ | sed -r 's:.*(\.git/.*)\).*:\1:' \ ) echo "$corrupted" rm -f "$corrupted" done } if [ -z "$1" ] || [ ! -d "$1" ]; then echo "'$1' is not a directory. Please provide the directory of the git repo" exit 1 fi for p in $1/objects/pack/pack-*.pack; do echo "$p" unpack_rm_corrupted "$p" done
źródło
Rozwiązałem ten problem, dodając zmianę, taką jak git add -A i ponownie git commit.
źródło