Git internals: thư mục .git hoạt động như thế nào

Git là công cụ quản lý phiên bản phổ biến nhất, nhưng nhiều developer chỉ dùng các lệnh bề mặt như git add, git commit, git push. Hiểu bên trong thư mục .git giúp bạn debug lỗi, khôi phục dữ liệu mất và tối ưu repository hiệu quả. Nắm vững kiến thức này sẽ biến bạn từ người dùng cơ bản thành chuyên gia Git có thể giải quyết mọi tình huống phức tạp.

Cấu trúc thư mục .git

Thư mục .git chứa toàn bộ lịch sử và metadata của repository. Các thành phần chính:

  • HEAD: con trỏ chỉ nhánh hiện tại
  • config: cấu hình local của repository
  • objects/: lưu trữ mọi blob, tree, commit dưới dạng SHA-1
  • refs/: lưu trữ tham chiếu đến các nhánh (branches) và thẻ (tags)
  • index: vùng staging, danh sách file chuẩn bị commit

sơ đồ cấu trúc thư mục .git của Git với HEAD config objects refs index

Cách Git lưu trữ dữ liệu

Git không lưu trữ dữ liệu dạng delta so với commit trước như SVN. Thay vào đó, mỗi file được lưu dưới dạng blob có SHA-1 duy nhất. Nếu nội dung file không thay đổi, Git chỉ lưu một bản sao. Khi một commit được tạo, Git tạo:

  1. Tree object: mô tả cấu trúc thư mục và file
  2. Commit object: chứa author, message, timestamp, tham chiếu tree và cha
  3. Parent reference: kết nối commit hiện tại với commit trước đó

minh họa blob tree commit object trong Git với mũi tên liên kết

Cách Git nén dữ liệu

Git lưu trữ mọi object dưới dạng zlib nén trong .git/objects/. Trước khi ghi, Git tính SHA-1 40 ký tự. Nếu cùng một file được lưu nhiều lần trong các commit khác nhau, Git chỉ lưu một bản sao. Bạn có thể kiểm chứng bằng git cat-file -p để xem nội dung object.

Staging area hoạt động như thế nào

Khi chạy git add file.txt, Git lưu nội dung file dưới dạng blob trong objects/, sau đó cập nhật index (staging area) với đường dẫn và hash. File trong index chính là “staged”. Khi chạy git commit, Git đọc index, tạo tree object, tạo commit object, rồi di chuyển HEAD và nhánh hiện tại.

Relog và reflog giúp khôi phục

Mỗi thay đổi HEAD được lưu trong .git/logs/refs/. Lệnh git reflog liệt kê lịch sử tham chiếu, giúp tìm commit “đã mất” sau git reset hay rebase. Reflog tự động xóa sau khoảng 90 ngày theo cấu hình git gc.

Để khôi phục file bị xóa chưa commit, dùng git checkout HEAD~1 -- file.txt. Nếu đã commit, dùng git revert để tạo commit đảo ngược mà không thay đổi lịch sử. Với git reflog, bạn có thể tìm SHA của commit bị mất và khôi phục bằng git checkout .

Lệnh plumbing quan trọng

  • git cat-file: xem nội dung, loại, kích thước của một object
  • git hash-object: tính SHA-1 cho file, lưu thành blob
  • git update-index: thêm/xóa file khỏi staging area thủ công
  • git write-tree: tạo tree object từ staging area
  • git commit-tree: tạo commit object từ tree

Phân biệt .git và working tree

Working tree là thư mục bạn đang làm việc. .git là kho lưu trữ ẩn. Mọi thay đổi trong working tree chưa có trong .git cho đến khi add và commit. Hiểu khác biệt này giúp tránh mất dữ liệu khi xóa nhầm file.

Quy trình làm việc nhóm

Nhóm developer thường dùng workflow nhánh: tạo feature branch từ main, phát triển, rồi gộp qua pull request. Nhánh remote được lưu trong .git/refs/remotes/. git fetch cập nhật remote tracking refs mà không trộn; git pull tương đương fetch + merge. Với nhóm lớn, git worktree cho phép làm việc đồng thời trên nhiều nhánh mà không cần switch nhánh.

Các lệnh nâng cao thường dùng

  • git bisect: tìm commit gây lỗi bằng tìm kiếm nhị phân
  • git cherry-pick: áp dụng một commit cụ thể từ nhánh khác
  • git rebase -i: viết lại lịch sử: squash, reorder, edit commit
  • git filter-repo: xóa file lớn, nhạy cảm khỏi lịch sử toàn bộ repo

Khi nào cần hiểu sâu .git internals

  • Khôi phục sau lỗi: rebase xung đột, commit nhầm, xóa nhánh nhầm
  • Tối ưu repository: xóa file lớn trong lịch sử bằng git filter-repo
  • Debug CI/CD: hiểu tại sao file không được track hoặc bị bỏ qua
  • Quản lý code: audit changes qua reflog, kiểm soát access

Những developer senior thường dùng lệnh plumbing để xây dựng công cụ riêng, tích hợp CI/CD, và viết script migration. Nắm vững Git internals giúp bạn tự tin dùng git reset --hard, git rebase -i, git bisect khi cần thiết. Tham khảo sách Pro Git để đào sâu hơn.

Mẹo nhanh: Khi làm việc với repo lớn, sử dụng git gc --aggressive để nén objects và giảm dung lượng disk, nhưng chỉ chạy khi không có ai khác làm việc trên repo để tránh xung đột.

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

Ghostty: Terminal GPU-rendered thay thế iTerm2 và Alacritty

Ghostty: Terminal GPU-rendered thay thế iTerm2 và Alacritty Ghostty là terminal emulator mới phát hành phiên bản 1.0 vào cuối 2024, được viết bằng Zig và sử dụng GPU rendering…

Xem thêm

Feather Robotics: Nền tảng robot mô-đun giá 30k USD cho developer

Feather Robotics, khởi nghiệp humanoid do cựu kỹ sư Tesla và founder trước của 1X thành lập, đang định vị mình là “Android of robotics” — cung cấp nền tảng…

Xem thêm

Tauri 2.0: Ứng Dụng Desktop Rust Chạy Trên WebView Hệ Thống

Tauri 2.0: Ứng dụng Desktop Rust chạy trên WebView hệ thống Tauri 2.0 là bản phát hành ổn định tháng 10/2024 của framework ứng dụng desktop đa nền tảng mã…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất