.gitignore
Xem thửVấn đề cần giải quyết
Bạn chạy git status và thấy hàng nghìn dòng node_modules/..., vài tệp .log, và một tệp .env chứa mật khẩu cơ sở dữ liệu. Chỉ cần một lần git add . bất cẩn là mật khẩu vào lịch sử, và lúc đó đã quá muộn. Tệp .gitignore liệt kê các mẫu mà Git sẽ bỏ qua.
Sau bài này, bạn có thể
- Viết
.gitignorecho dự án thật và hiểu các mẫu cơ bản. - Giải thích vì sao
.gitignorekhông tác dụng với tệp đã được theo dõi. - Gỡ một tệp đã lỡ commit khỏi theo dõi mà vẫn giữ trên đĩa, và biết giới hạn của việc đó.
Tiên quyết: bài Tổng quan lưu thay đổi.
Ví dụ .gitignore
# Phụ thuộc
node_modules/
vendor/
# Kết quả build
dist/
build/
*.log
# Biến môi trường và bí mật
.env
.env.local
# Tệp hệ điều hành và IDE
.DS_Store
.idea/
.vscode/
Git quyết định một tệp có bị bỏ qua thế nào
Với mỗi tệp trong Working Directory, Git hỏi hai câu theo thứ tự. Hãy chú ý nhánh đầu tiên.
Đang tải sơ đồ…
Cách đọc hình. Câu hỏi đầu tiên là tệp đã được theo dõi chưa. Nếu rồi, .gitignore không có tác dụng và tệp vẫn được theo dõi. Chỉ với tệp chưa theo dõi, Git mới kiểm tra mẫu: khớp thì bị bỏ qua, không khớp thì hiện là untracked trong git status.
Thử và quan sát
Hãy dự đoán: bạn thêm .env vào .gitignore, nhưng .env đã được commit từ trước. Sửa .env rồi chạy git status thì còn báo thay đổi không? Chạy mô phỏng cả hai kịch bản.
Đang tải Animation…
Bảng bước (bản đọc tĩnh của mô phỏng)
| Bước | Lệnh | Điều xảy ra |
|---|---|---|
| 1 | git status --short | Ba thứ không nên theo dõi đang làm rối danh sách: log, bí mật và thư viện tải về. |
| 2 | echo "*.log" >> .gitignore | Mẫu *.log khớp mọi tệp kết thúc bằng .log nên debug.log bị bỏ qua. |
| 3 | printf ".env\nnode_modules/\n" >> .gitignore | Thêm hai mẫu nữa. Mẫu có dấu / ở cuối chỉ khớp thư mục. |
| 4 | git status --short | Ba tệp đã biến mất khỏi danh sách. Chỉ còn bản thân .gitignore là tệp mới cần commit. |
| 5 | git add .gitignore && git commit -m "Thêm .gitignore" | Commit .gitignore để cả đội dùng chung quy tắc. |
Biến thể: .env đã lỡ commit từ trước
| Bước | Lệnh | Điều xảy ra |
|---|---|---|
| 1 | echo "SECRET=abc" >> .env | .env nằm trong .gitignore nhưng đã được theo dõi, nên Git vẫn thấy nó đã sửa. |
| 2 | git status --short | .gitignore không có tác dụng với tệp đã được theo dõi. |
| 3 | git rm --cached .env | Gỡ .env khỏi index nhưng giữ tệp trên đĩa. Từ giờ .gitignore bỏ qua nó. |
| 4 | git commit -m "Ngừng theo dõi .env" | Commit mới không còn chứa .env. |
| 5 | git log --oneline -- .env | Commit cũ vẫn chứa nội dung .env trong lịch sử. Nếu đó là bí mật, phải đổi bí mật. |
Giải đáp. Còn báo, vì tệp đã được theo dõi. Phải ngừng theo dõi bằng git rm --cached, rồi .gitignore mới bỏ qua nó. Nhưng các commit cũ đã chứa .env vẫn giữ nguyên trong lịch sử; nếu đó là bí mật thật, hãy đổi bí mật.
Quy tắc mẫu
| Mẫu | Ý nghĩa |
|---|---|
*.log | Mọi tệp kết thúc bằng .log |
build/ | Thư mục tên build ở mọi cấp |
/secret.txt | Chỉ secret.txt ở thư mục gốc |
!important.log | Không bỏ qua (phủ định) |
doc/**/*.pdf | Mọi PDF ở mọi cấp trong doc |
Đã lỡ commit thì sao
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "Ngừng theo dõi .env"
git rm --cached gỡ tệp khỏi index nhưng giữ trên đĩa. Để biết một tệp bị bỏ qua bởi mẫu nào:
git check-ignore -v debug.log
Kết quả cho thấy tệp .gitignore, số dòng và mẫu khớp, ví dụ .gitignore:1:*.log debug.log.
Hiểu lầm thường gặp
- "Thêm vào .gitignore là Git ngừng theo dõi." Không với tệp đã theo dõi.
- "git rm --cached xóa tệp khỏi lịch sử." Nó chỉ ngừng theo dõi từ commit mới; commit cũ vẫn chứa tệp.
- "Mỗi người nên tự có .gitignore riêng." Hãy commit
.gitignorechung cho cả đội; quy tắc riêng của cá nhân đặt trong tệp ignore toàn cục.
Tự kiểm tra
- Một tệp đã commit rồi mới thêm vào
.gitignore. Git có bỏ qua nó không? - Mẫu
/config.jsonkhácconfig.jsonthế nào? - Bạn lỡ commit một khóa API. Chỉ
git rm --cachedcó đủ không?
Đáp án gợi ý. (1) Không, vì tệp đã theo dõi. (2) /config.json chỉ khớp ở thư mục gốc; config.json khớp ở mọi cấp. (3) Không; khóa vẫn nằm trong lịch sử, cần thu hồi và cấp khóa mới.
Điều cần nhớ
.gitignorechỉ tác động tới tệp chưa được theo dõi.- Tệp đã theo dõi: dùng
git rm --cached, và lịch sử cũ vẫn giữ bản đã commit. - Commit
.gitignoređể cả đội dùng chung quy tắc. - Chương sau: Kiểm tra kho, đọc trạng thái và lịch sử.
Nguồn tham khảo
Pro Git, chương 2.2 "Ignoring Files" (git-scm.com/book); tài liệu gitignore (git-scm.com/docs/gitignore).