ตรวจสอบและแก้ไข Git Repository ที่เสียหาย (Corrupted)

Git Repository อาจเสียหายได้จากข้อผิดพลาดในระบบ การปิดเครื่องแบบไม่ปกติ หรือการตัดการเชื่อมต่อที่กระทันหัน บทความนี้จะให้คำแนะนำวิธีตรวจสอบและแก้ไข Git Repository ที่เสียหาย รวมถึงวิธีป้องกันการเกิดปัญหาซ้ำในอนาคต ซึ่งเป็นความรู้ที่สำคัญสำหรับผู้ที่ใช้ ผู้ให้บริการโฮสติ้ง Cloud VPS หรือเซิร์ฟเวอร์ Linux

สัญญาณของ Repository ที่เสียหาย

เมื่อ Git Repository เสียหาย คุณจะพบกับข้อผิดพลาดต่างๆ ที่ป้องกันการทำงานตามปกติ การรู้จำสัญญาณเหล่านี้จะช่วยให้คุณตรวจสอบปัญหาได้เร็วขึ้น

  • Error “packfile is corrupted” – เกิดจากการถ่ายโอนไฟล์ที่ไม่สมบูรณ์ หรือตัดการเชื่อมต่อระหว่าง Clone หรือ Fetch
  • ไม่สามารถ Checkout หรือ Pull ได้ – เนื่องจาก Git ไม่สามารถเข้าถึง Object ที่จำเป็น เช่น Tree หรือ Blob ที่ขาดหาย
  • Error “object file is empty” – เกิดจากการลบ Object ที่จำเป็น หรือการเขียน Object ที่ไม่สมบูรณ์
  • Error “loose object is corrupted” – เกิดจากการเก็บข้อมูลที่ไม่สมบูรณ์ หรือ Hardware Issues
  • SHA1 Mismatch Error – บ่งชี้ว่า Object ถูกเขียนหรือรับส่งข้อมูลอย่างไม่ถูกต้อง
  • Cannot read from object database – Error ทั่วไปบ่งชี้ว่า Objects ใน .git/objects ถูกเสียหาย

ขั้นที่ 1: ตรวจสอบสถานะด้วย git fsck

คำสั่ง fsck (file system check) เป็นเครื่องมือแรกที่ควรใช้เมื่อสงสัยว่า Repository มีปัญหา โดยจะสแกน Object ทั้งหมดและตรวจสอบความสมบูรณ์

# ตรวจสอบความสมบูรณ์ Repository
git fsck --full

# ตรวจสอบแบบละเอียด และแสดง Object ที่สูญหาย
git fsck --full --verbose

# ตรวจสอบและแสดง Object ที่ไม่สามารถเข้าถึงได้
git fsck --full --unreachable

# ตรวจสอบแบบละเอียดสำหรับ Repository ขนาดใหญ่
git fsck --full --progress

ขั้นที่ 2: ดูข้อผิดพลาดและหา Object ที่เสีย

ผลลัพธ์ของคำสั่ง fsck จะบอกคุณว่ามี Object ใดที่เสียหายหรือไม่สามารถเข้าถึงได้

# ตัวอย่างผลลัพธ์ปกติ (ไม่มีปัญหา)
$ git fsck --full
Checking object directories: 100% (256/256), done.

# ตัวอย่างผลลัพธ์ที่มีปัญหา
$ git fsck --full
error: sha1 mismatch 5d41402abc4b2a76b9719d911017c592
error: object file is empty: .git/objects/5d/41402abc4b2a76b9719d911017c592
Missing blob 5d41402abc4b2a76b9719d911017c592
Broken link from commit abc123 to tree def456

ขั้นที่ 3: วิธีแก้ไขจาก Backup

หากคุณมี Backup ของ Repository หรือ Remote Repository ที่สะอาด วิธีที่ง่ายที่สุดคือ Clone ใหม่จาก Remote

# Clone ใหม่จาก Remote Repository
cd ..
rm -rf myproject          # ลบ Repository ที่เสียหาย
git clone  myproject

# หรือ Restore จาก Backup
cd myproject
rm -rf .git
tar -xzf backup/.git.tar.gz

4.1 ลองใช้ git repack และ git prune

วิธีนี้มีประสิทธิภาพสูงในการแก้ไขปัญหาจำนวนมาก

# Repack Repository (รวม Objects ใหม่)
git repack -Ad

# ลบ Objects ที่ไม่ได้ Reference
git prune

# ลบ Objects ที่ไม่ได้ใช้อย่างเด็ดขาด
git prune --expire=now

# ตรวจสอบอีกครั้ง
git fsck --full

4.2 ใช้ git reflog เพื่อ Recover Commits

Git Reflog บันทึกทุกครั้งที่ HEAD เปลี่ยนแปลง ซึ่งสามารถใช้เพื่อ Recover Commits ที่หลุดหายได้

# ดูประวัติ Reflog
git reflog

# ผลลัพธ์ตัวอย่าง:
# a1b2c3d (HEAD -> main) HEAD@{0}: checkout: moving from feature to main
# e4f5g6h (feature) HEAD@{1}: commit: Add new feature
# i7j8k9l HEAD@{2}: reset: moving to HEAD~1

# Recover Commit ที่หลุดหายไป
git checkout a1b2c3d

# สร้าง Branch ใหม่จาก Reflog Entry
git checkout -b recovery-branch e4f5g6h

4.3 ลอง fsck –lost-found

คำสั่งนี้จะหา Objects ที่ไม่ได้ Reference และพยายาม Recovery

# ลอง Recovery Objects ที่หลุดหาย
git fsck --lost-found

# ดู Objects ที่ recovery ได้
ls .git/lost-found/commit/
ls .git/lost-found/other/

# ดูเนื้อหา Commit ที่ recovery ได้
for file in .git/lost-found/commit/*; do
    echo "=== Commit: $(basename $file) ==="
    git log -1 --format="%H %s" $file
done

ขั้นที่ 5: Advanced Recovery ด้วย Object Inspection

# ดูข้อมูล Object โดยตรง
git cat-file -p 

# ตรวจสอบประเภท Object
git cat-file -t 

# ตรวจสอบขนาด Object
git cat-file -s 

# ลบ Objects ที่เสียหายด้วยตนเอง (ใช้อย่างระวัง)
rm .git/objects//

# Rebuild Index
rm .git/index
git reset --hard HEAD

สร้าง Backup ประจำ

# สร้าง Bare Repository สำรอง
git clone --bare /path/to/repository /backup/myproject.git

# Backup .git Directory
tar -czf backup-$(date +%Y%m%d).tar.gz /path/to/.git/

# ตั้ง Cron Job สำหรับ Backup ประจำวัน
# เพิ่มลงใน crontab:
# 0 2 * * * tar -czf /backups/myproject-$(date +\%Y\%m\%d).tar.gz /home/user/myproject/.git/

ตรวจสอบสถานะประจำ

# ตั้ง Cron Job เพื่อตรวจสอบสถานะทุกสัปดาห์
# 0 3 * * 0 git -C /path/to/repository fsck --full

# Manual Check
git fsck --full
git gc --aggressive --prune=now

ใช้ Remote Repository

เก็บ Repository บน Remote Server (เช่น GitHub, GitLab) เพื่อป้องกันการสูญหาย

# Push ไปยัง Remote บ่อยๆ
git push origin main
git push origin --all
git push origin --tags

# ตั้ง Git Hooks เพื่อ Push โดยอัตโนมัติ
echo '#!/bin/bash
echo "Pushing to remote..."
git push origin main' > .git/hooks/post-commit
chmod +x .git/hooks/post-commit
# ตั้งค่า Git Server บน ผู้ให้บริการโฮสติ้ง Cloud VPS

# 1. สร้าง Bare Repository สำหรับ Central Repository
sudo mkdir -p /var/git/myproject.git
cd /var/git/myproject.git
sudo git init --bare

# 2. ตั้ง Permissions
sudo chown -R git:git /var/git/myproject.git
sudo chmod -R 755 /var/git/myproject.git

# 3. ตั้งค่า Automated Backup
# เพิ่ม Cron Job:
# 0 3 * * * tar -czf /backups/myproject-$(date +\%Y\%m\%d).tar.gz /var/git/myproject.git/

# 4. Clone ลงมาที่เครื่องท้องถิ่น
git clone ssh://[email protected]:/var/git/myproject.git myproject

สรุป

Repository ที่เสียหายสามารถแก้ไขได้ในหลายกรณี โดยใช้ git fsck, reflog และ repack แต่ Backup ประจำยังคงสำคัญที่สุด การทำงานกับ ผู้ให้บริการโฮสติ้ง Cloud VPS สำหรับเก็บ Git Repository ให้ติดตามการป้องกันและการจัดเตรียม Backup เพื่อป้องกันการสูญหายข้อมูลที่ไม่คาดคิด