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 addcommit. 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

HTMX framework — Thư viện HTML-driven cho ứng dụng web hiện đại

HTMX framework HTMX là thư viện JavaScript nhẹ, không phụ thuộc build tool, cho phép truy cập AJAX, CSS Transitions, WebSockets và Server Sent Events trực tiếp qua thuộc tính…

Xem thêm

Event-Driven Architecture: Kafka, RabbitMQ, Apache Pulsar

Event-Driven Architecture là gì? Event-Driven Architecture (EDA) là kiến trúc phần mềm xây dựng xung quanh sự kiện — các thay đổi trạng thái trong hệ thống được phát hiện,…

Xem thêm

WebSocket thời gian thực trong web

WebSocket là gì? WebSocket là giao thức truyền thông hai chiều (full-duplex) qua một kết nối TCP duy nhất, cho phép server và client trao đổi dữ liệu thời gian…

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