Trước tiên, hãy thử các lệnh sau (chạy lại nếu cần):
$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase
Và sau đó bạn vẫn gặp sự cố, hãy thử có thể:
loại bỏ tất cả các đối tượng bị hỏng, ví dụ:
fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
$ rm -v .git/objects/06/91c5...51e5
loại bỏ tất cả các đối tượng trống, ví dụ:
error: object file .git/objects/06/91c5...51e5 is empty
$ find .git/objects/ -size 0 -exec rm -vf "{}" \;
kiểm tra thông báo "liên kết bị hỏng" bằng cách:
git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
Điều này sẽ cho bạn biết tệp bị hỏng đến từ đâu!
để khôi phục tệp, bạn có thể thực sự may mắn và nó có thể là phiên bản mà bạn đã kiểm tra trong cây làm việc của mình:
git hash-object -w my-magic-file
một lần nữa, và nếu nó xuất ra SHA1 bị thiếu (4b945 ..) thì bây giờ bạn đã hoàn tất!
giả sử rằng đó là một số phiên bản cũ hơn đã bị hỏng, cách dễ nhất để làm điều đó là:
git log --raw --all --full-history -- subdirectory/my-magic-file
và điều đó sẽ hiển thị cho bạn toàn bộ nhật ký cho tệp đó (vui lòng nhận ra rằng cây bạn có có thể không phải là cây cấp cao nhất, vì vậy bạn cần phải tự mình tìm ra thư mục con nào của nó), sau đó bạn có thể tạo lại thiếu đối tượng với đối tượng băm một lần nữa.
để có được danh sách tất cả các giới thiệu bị thiếu cam kết, cây hoặc đốm màu:
$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
Có thể không xóa được một số ref đó bằng cách sử dụng các lệnh branch -d hoặc tag -d thông thường, vì chúng sẽ chết nếu git nhận thấy lỗi. Vì vậy, hãy sử dụng lệnh ống nước git update-ref -d $ ref để thay thế. Lưu ý rằng trong trường hợp các nhánh cục bộ, lệnh này có thể để lại cấu hình nhánh cũ trong .git / config. Nó có thể được xóa theo cách thủ công (tìm phần [nhánh "$ ref"]).
Sau khi tất cả các ref đã sạch, vẫn có thể có các cam kết bị hỏng trong reflog. Bạn có thể xóa tất cả các nhật ký bằng git reflog expire --expire = now --all. Nếu bạn không muốn mất tất cả các bản trích dẫn của mình, bạn có thể tìm kiếm các bản giới thiệu riêng lẻ để tìm các bản ghi bị hỏng:
$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
(Lưu ý rằng tùy chọn -g được thêm vào danh sách git rev.) Sau đó, sử dụng git reflog expire --expire = now $ ref trên mỗi cái đó. Khi tất cả refs và reflog bị hỏng biến mất, hãy chạy git fsck --full để kiểm tra xem kho lưu trữ có sạch không. Đối tượng nguy hiểm là Ok.
Dưới đây, bạn có thể tìm thấy cách sử dụng nâng cao của các lệnh có khả năng gây mất dữ liệu trong kho lưu trữ git của bạn nếu không được sử dụng một cách khôn ngoan, vì vậy hãy sao lưu trước khi bạn vô tình làm hỏng thêm git của mình. Hãy tự mạo hiểm nếu bạn biết mình đang làm gì.
Để kéo nhánh hiện tại lên trên nhánh ngược dòng sau khi tìm nạp:
$ git pull --rebase
Bạn cũng có thể thử kiểm tra chi nhánh mới và xóa chi nhánh cũ:
$ git checkout -b new_master origin/master
Để tìm đối tượng bị hỏng trong git để xóa, hãy thử lệnh sau:
while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done
Đối với OSX, hãy sử dụng sed -E
thay vì sed -r
.
Ý tưởng khác là giải nén tất cả các đối tượng từ các tệp gói để tạo lại tất cả các đối tượng bên trong .git / objects, vì vậy hãy thử chạy các lệnh sau trong kho lưu trữ của bạn:
$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak
Nếu cách trên không hữu ích, bạn có thể thử rsync hoặc sao chép các đối tượng git từ một repo khác, ví dụ:
$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects
Để khắc phục nhánh bị hỏng khi thử kiểm tra như sau:
$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625
Hãy thử xóa nó và thanh toán lại từ ngược dòng:
$ git branch -D master
$ git checkout -b master github/master
Trong trường hợp nếu git đưa bạn vào trạng thái tách rời, hãy kiểm tra master
và hợp nhất vào nó nhánh tách rời.
Một ý tưởng khác là căn cứ lại đệ quy cái hiện có một cách đệ quy:
$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master
Xem thêm:
.git
tất nhiên là ngoại trừ thư mục) vào kho mới được nhân bản ... và sau đó thực hiệngit status
trong repo mới ... git phát hiện chính xác tất cả các thay đổi bị ảnh hưởng đối với tệp của tôi và tôi có thể bắt đầu lại công việc của mình.