Skip to content

Thực hành: Git Internals Deep Dive

🎯 Mục tiêu

🎯 Sau bài thực hành này, bạn sẽ:

  • Hiểu 4 loại object trong Git: blob, tree, commit, tag
  • Biết cách SHA-1 hash được tính và tại sao nó đảm bảo tính toàn vẹn
  • Khám phá cấu trúc bên trong .git/ directory bằng plumbing commands
  • Hiểu refs, HEAD, và cách Git thực sự hoạt động dưới lớp porcelain

Phần 1: Trắc nghiệm

🧠 Quiz

Câu 1: Mối quan hệ giữa các Git objects là gì?

  • [ ] A) blob chứa tree, tree chứa commit
  • [x] B) commit trỏ đến tree, tree trỏ đến blobs và trees con, blob chứa nội dung file
  • [ ] C) Tất cả objects đều độc lập, không liên kết với nhau
  • [ ] D) commit chứa trực tiếp nội dung file, không cần blob

💡 Giải thích: Git dùng mô hình phân cấp: commit ghi lại metadata (author, message, parent) và trỏ đến một tree đại diện cho trạng thái thư mục gốc. Tree chứa danh sách entries — mỗi entry trỏ đến blob (file) hoặc tree con (thư mục). Blob chỉ lưu nội dung file, không lưu tên file.

🧠 Quiz

Câu 2: SHA-1 hash trong Git được tính từ đâu?

  • [ ] A) Chỉ từ nội dung file
  • [ ] B) Từ tên file và đường dẫn
  • [x] C) Từ header (loại object + kích thước) ghép với nội dung object
  • [ ] D) Từ timestamp khi object được tạo

💡 Giải thích: Git tính SHA-1 bằng công thức: SHA1("<type> <size>\0<content>"). Ví dụ một blob: SHA1("blob 13\0Hello World\n"). Điều này có nghĩa: cùng nội dung luôn cho cùng hash (content-addressable storage), và bất kỳ thay đổi nào — dù 1 byte — tạo hash hoàn toàn khác.

🧠 Quiz

Câu 3: File .git/HEAD chứa gì?

  • [ ] A) SHA-1 hash của commit đầu tiên trong repository
  • [ ] B) Danh sách tất cả các branch
  • [x] C) Reference đến branch hiện tại (ví dụ ref: refs/heads/main) hoặc trực tiếp một commit SHA
  • [ ] D) Nội dung của file mới nhất được commit

💡 Giải thích: Thông thường HEAD chứa symbolic reference: ref: refs/heads/main. Git đọc file này, theo dõi đến .git/refs/heads/main để lấy SHA-1 của commit hiện tại. Khi ở trạng thái detached HEAD, file chứa trực tiếp SHA-1 thay vì reference.

Phần 2: Tìm lỗi sai

🐛 Spot-the-Bug

Tìm lỗi: Corrupted ref gây mất branch

Developer báo cáo branch feature/payment biến mất sau khi máy tính tắt đột ngột. Kiểm tra nội dung .git/refs/heads/feature/payment:

a3f2b7c8d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7g8

Câu hỏi: Tại sao ref này bị coi là corrupted?

Đáp án: SHA-1 hash trong Git luôn có đúng 40 ký tự hexadecimal (0-9, a-f). Chuỗi trên chứa ký tự g8 — ký tự g không thuộc hệ hex (chỉ có a-f). Đây là dấu hiệu file bị corrupt khi ghi dở do mất điện.

Khôi phục: Dùng git reflog tìm SHA đúng, hoặc git fsck --lost-found tìm dangling commits, rồi git update-ref refs/heads/feature/payment <correct-sha>.

Phần 3: Bài tập khám phá

Bài tập: Khám phá Git object database

Mục tiêu: Dùng plumbing commands để hiểu cách Git lưu trữ dữ liệu bên trong.

Các bước thực hiện:

  1. mkdir internals-lab && cd internals-lab && git init
  2. echo "Hello Git Internals" > hello.txt && git add . && git commit -m "first commit"
  3. Khám phá HEAD chain: cat .git/HEADcat .git/refs/heads/main
  4. Dùng git cat-file -p <commit-sha> xem commit → tìm tree SHA
  5. git cat-file -p <tree-sha> xem tree → tìm blob SHA
  6. git cat-file -p <blob-sha> xem nội dung file gốc
  7. Tự tạo blob: echo "Manual blob" | git hash-object -w --stdin
  8. Tạo thêm 1 commit, dùng git cat-file -p xem field parent

Kết quả mong đợi: Chuỗi HEAD → branch ref → commit → tree → blob — mọi thứ trong Git đều là object được đánh địa chỉ bằng SHA-1.

Kiến thức nâng cao

Git đang chuyển dần từ SHA-1 sang SHA-256 (bắt đầu từ Git 2.29). Nguyên lý hoạt động giống hệt — chỉ khác hàm hash. Hiểu content-addressable storage là bạn đã nắm được trái tim của Git.