Phân biệt assume-unchanged và skip-worktree trong Git: Bỏ qua file config cục bộ chuẩn xác

Git tutorial - IT technology blog
Git tutorial - IT technology blog

Quick start: Xử lý nhanh trong 3 phút

2 giờ sáng, server staging sập kết nối database ngay sau khi kéo bản build mới. Bạn cần sửa gấp chuỗi connection string trong file config/database.json để cứu hệ thống. Tuy nhiên, bạn không muốn commit nhầm thông số này lên repo, cũng chẳng thể thêm vào .gitignore vì file vốn đã được Git theo dõi (tracked) từ trước.

Giải pháp an toàn và chuẩn nhất là dùng cờ skip-worktree:

# 1. Báo Git bỏ qua mọi thay đổi cục bộ ở file database.json
git update-index --skip-worktree config/database.json

# 2. Kiểm tra lại - file biến mất khỏi danh sách modified
git status

# 3. Khi cần theo dõi lại (để pull code mới hoặc commit thay đổi)
git update-index --no-skip-worktree config/database.json

Nếu bạn chỉ muốn tăng tốc độ gõ lệnh trên máy local và chắc chắn remote không bao giờ sửa file đó, assume-unchanged là lựa chọn thay thế:

# Bỏ qua kiểm tra thay đổi file
git update-index --assume-unchanged config/database.json

# Bật lại theo dõi bình thường
git update-index --no-assume-unchanged config/database.json

Bản chất kỹ thuật: Đừng để vẻ ngoài đánh lừa

Sau khi chạy lệnh, cả hai cờ đều khiến file đã sửa biến mất khỏi git status. Điểm khác biệt cốt lõi nằm ở cách Git xử lý khi có xung đột từ remote.

1. assume-unchanged: Tối ưu I/O cho repo khủng

Tính năng này ra đời để phục vụ các dự án monolithic chứa hàng trăm nghìn file (như Chromium hay Linux kernel). Việc gọi hàm stat() liên tục trên từng file gây nghẽn I/O ổ đĩa nghiêm trọng. Bật cờ này đồng nghĩa với lời hứa: “File này tôi không bao giờ sửa, Git đừng tốn công quét đĩa nữa.”

Rủi ro xuất hiện khi bạn lỡ tay sửa file:

  • Git bỏ qua kiểm tra nên không hề cảnh báo bạn lúc commit.
  • Khi bạn chạy git pull và remote có commit sửa đúng file đó, Git sẽ tự động hủy cờ hoặc ghi đè, làm mất sạch cấu hình bạn vừa tinh chỉnh.

2. skip-worktree: Lá chắn cho cấu hình local

Cờ --skip-worktree giải quyết đúng bài toán giữ config cá nhân trên máy. Lệnh này gửi thông điệp rõ ràng: “Tôi có sửa file này ở local, nhưng hãy giữ nguyên bản trên repo và đừng bao giờ đẩy thay đổi lên.”

  • Khi git pull gặp xung đột trên remote, Git chủ động dừng tiến trình và báo lỗi rõ ràng thay vì âm thầm ghi đè nội dung.
  • Các thao tác git merge hay git rebase thông thường không tự ý tắt cờ này.

So sánh nhanh

Tiêu chí assume-unchanged skip-worktree
Mục đích chính Giảm tải I/O ổ đĩa trên repo lớn Bảo vệ nội dung sửa đổi cục bộ
Hành vi khi git pull có xung đột Dễ bị reset cờ và ghi đè nội dung Chặn pull, báo lỗi để bảo vệ file
File phù hợp SDK tĩnh, thư viện vendor nặng File config, credentials, environment

Quản lý danh sách file đang bị ẩn

Sau vài tuần gắn cờ, bạn rất dễ quên mất mình đã ẩn những file nào. Dùng lệnh git ls-files -v để xem trạng thái index thực tế của dự án.

Lọc file theo cờ

# Liệt kê các file đang gắn skip-worktree (chữ S viết hoa)
git ls-files -v | grep '^S'

# Liệt kê các file đang gắn assume-unchanged (chữ h viết thường)
git ls-files -v | grep '^h'

Ý nghĩa các ký tự đầu dòng:

  • S: File đang bật skip-worktree.
  • h: File đang bật assume-unchanged.
  • H: File bình thường được theo dõi đầy đủ.

Bộ alias tiết kiệm thời gian gõ lệnh

Gõ cả cụm lệnh dài ngoằng mỗi ngày rất mất thời gian. Bạn nên thêm ngay 3 dòng alias này vào file ~/.gitconfig:

git config --global alias.ignore-local "update-index --skip-worktree"
git config --global alias.unignore-local "update-index --no-skip-worktree"
git config --global alias.ignored-locals "!git ls-files -v | grep '^S'"

Khi cần dùng, bạn chỉ việc gõ ngắn gọn:

git ignore-local config/database.json
git ignored-locals

3 lưu ý đắt giá khi vận hành thực tế

  1. Ưu tiên tuyệt đối skip-worktree cho file config: Không bao giờ dùng assume-unchanged cho credential hay connection string. Một lệnh git checkout bất cẩn có thể xóa trắng mọi cấu hình bạn mất cả buổi thiết lập.
  2. Gỡ cờ trước khi cập nhật code: Khi Git chặn pull vì xung đột file gắn skip-worktree, hãy chạy git unignore-local <file>, stash lại thay đổi, pull xong xuôi rồi mới apply lại và bật cờ.
  3. Tách biến môi trường vẫn là chuẩn lâu dài: Cờ Git chỉ là giải pháp tạm thời khi debug hoặc fix nóng. Về lâu dài, dự án vẫn cần kiến trúc tách biệt giữa .env.example (được track) và file .env cục bộ (nằm trong .gitignore).
Share: