Lỗi này là gì
Bạn chạy lệnh git status, git pull, hay thậm chí chỉ git log thì đột nhiên gặp phải:
error: object file .git/objects/ab/cdef1234567890abcdef is empty
fatal: loose object abcdef1234567890 (stored in .git/objects/ab/cdef1234567890) is corrupt
Git dừng hoàn toàn. Commit, pull, push — không lệnh nào hoạt động. Đôi khi bạn không thể chạy được cả git status. Nguyên nhân thường gặp: tắt máy đột ngột khi Git đang ghi dữ liệu, ổ đĩa hết dung lượng giữa chừng, hoặc mất điện trong lúc chạy git gc. Bất kỳ trường hợp nào trong số này đều có thể để lại các file object rỗng hoặc bị ghi dở, và Git sẽ từ chối tiếp tục cho đến khi chúng được xử lý.
Bước 1 — Chạy fsck để xem toàn bộ thiệt hại
Chưa cần làm gì vội. Trước tiên, hãy xác định chính xác những gì bị hỏng:
git fsck --full
Lệnh này quét tất cả các object trong .git/objects/ và đánh dấu các mục bị thiếu, treo (dangling), hoặc bị hỏng. Kết quả đầu ra thường trông như thế này:
error: object file .git/objects/ab/cdef1234567890abcdef is empty
error: object file .git/objects/3f/a0b12c... is empty
dangling blob 7d3e9f...
missing tree 8c12a4...
Trong trường hợp nặng, bạn có thể thấy 5–10 hash bị hỏng được liệt kê. Hãy ghi lại tất cả — bạn sẽ cần tham chiếu đến chúng sau.
Bước 2 — Xóa các file object rỗng
File có dung lượng bằng 0 là triệu chứng phổ biến nhất. Git không thể phân tích một object rỗng và sẽ không tiếp tục. Hãy xóa chúng đi:
# Chạy thử trước — xem những gì sẽ bị xóa
find .git/objects -size 0
# Xóa tất cả file object có dung lượng bằng 0
find .git/objects -size 0 -delete
Chạy lại git fsck --full sau đó. Nếu các object đó tồn tại trên remote hoặc trong reflog, Git thường có thể khôi phục chúng ở các bước tiếp theo mà không cần bạn làm thêm gì.
Bước 3 — Fetch từ remote để khôi phục các object bị thiếu
Có remote thì việc khôi phục trở nên đơn giản. Fetch sẽ kéo các object bị thiếu trực tiếp từ GitHub, GitLab, hay bất cứ nơi nào bạn push lên:
git fetch --all
Nếu fetch bị lỗi vì HEAD hoặc ref của nhánh hiện tại cũng bị hỏng, hãy nhắm vào một nhánh cụ thể thay thế:
git fetch origin main
git fetch origin --tags
Chạy lại git fsck --full một lần nữa. Với hầu hết mọi người, chỉ một lần fetch này là đủ để xóa sạch lỗi hỏng hoàn toàn.
Bước 4 — Khôi phục từ reflog nếu fetch từ remote chưa đủ
Bên trong .git/logs/ có một nhật ký theo thứ tự thời gian của mọi lần di chuyển HEAD — đó là reflog của Git. Ngay cả khi một object đã mất, reflog vẫn biết HEAD đang trỏ đến đâu trước khi sự cố xảy ra:
git reflog
Tìm commit sạch cuối cùng (ngay trước thời điểm xảy ra lỗi hỏng) và reset về đó:
git reset --hard <commit-hash>
Nếu bản thân reflog không đọc được, hãy kiểm tra trực tiếp file thô:
cat .git/logs/HEAD
Bước 5 — Rebuild lại index nếu git status vẫn bị lỗi
File index (.git/index) đôi khi bị hỏng cùng với các object. Hãy xóa nó và để Git tái tạo lại từ cây HEAD:
rm .git/index
git reset HEAD
Các file trong thư mục làm việc của bạn vẫn không bị ảnh hưởng. Git chỉ đơn giản là xây dựng lại index từ cây của commit hiện tại, điều này thường đủ để git status hoạt động trở lại.
Bước 6 — Chạy gc để dọn dẹp và đóng gói lại
Sau khi đã xử lý xong lỗi hỏng, hãy gộp các loose object còn sót lại vào các pack file và loại bỏ các ref treo:
git gc --aggressive --prune=now
Lệnh này cũng xây dựng lại các index nội bộ và có thể giải quyết các cảnh báo nhất quán mà fsck đã đánh dấu nhưng không phân loại là lỗi nghiêm trọng.
Phương án cuối cùng — Clone mới nếu có remote sạch
Khi không có cách nào khác và vẫn còn remote sạch, hãy thôi không vật lộn với repo bị hỏng nữa và bắt đầu lại từ đầu:
# Sao lưu các thay đổi chưa commit trước
cp -r my-repo /tmp/my-repo-backup
# Clone mới
git clone git@github.com:user/my-repo.git my-repo-fresh
# Sao chép lại các file untracked bạn cần
cp /tmp/my-repo-backup/some-file.txt my-repo-fresh/
Xác nhận đã sửa xong
Chạy bốn kiểm tra này để xác nhận repo đã hoạt động bình thường:
# Không nên báo lỗi nào
git fsck --full
# Nên hiển thị trạng thái sạch
git status
# Nên in log mà không có lỗi
git log --oneline -10
# Kiểm tra một thao tác thực tế
git pull
Kết quả git fsck sạch với không có dòng error: nào có nghĩa là cơ sở dữ liệu object đã nguyên vẹn. Bạn có thể yên tâm rồi.
Ngăn chặn tái phát
- Không bao giờ buộc tắt tiến trình Git — luôn để
git gc,git clone, hoặcgit pushhoàn thành tự nhiên. - Theo dõi dung lượng ổ đĩa — việc ghi object sẽ thất bại âm thầm khi ổ đĩa hết chỗ giữa chừng. Hãy giữ ít nhất vài GB trống trên các máy có repo đang hoạt động.
- Dùng UPS cho những máy quan trọng — mất điện đột ngột trong lúc thực hiện pack operation là nguyên nhân hàng đầu gây ra lỗi này. Một chiếc UPS rẻ tiền sẽ loại bỏ hoàn toàn rủi ro này.
- Push thường xuyên — remote chính là bản sao lưu thực sự của bạn. Nếu các object tồn tại ở đó, việc khôi phục chỉ cần một lệnh
git fetch. - Chạy
git fsckđịnh kỳ trên các repo quan trọng — một object bị hỏng phát hiện sớm chỉ mất vài giây để sửa. Một chục cái phát hiện muộn có thể ngốn hàng giờ khôi phục.

