Thiết lập .gitignore toàn cục và template theo dự án: Loại trừ file OS, IDE và ngôn ngữ lập trình đúng cách

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

Câu chuyện quen thuộc: Repository toàn rác

Chắc ai trong team cũng từng gặp cảnh này: mở pull request lên thì thấy diff toàn .DS_Store, Thumbs.db, thư mục .idea/ của IntelliJ, hay tệ hơn là cả file .env chứa API key bị commit lên. Người review mất thời gian lọc qua đống rác đó để tìm code thật sự thay đổi.

Mình từng làm việc ở một dự án không ai setup .gitignore đúng cách từ đầu. Sau 3 tháng, lịch sử commit đầy node_modules/ bị push lên. Dev Windows thì commit Thumbs.db, dev Mac thì commit .DS_Store. Cleanup mớ đó tốn cả buổi chiều — chưa kể phải thuyết phục cả team chạy lại git pull --rebase.

Nhưng vấn đề không chỉ là xấu về mặt thẩm mỹ — nó còn nguy hiểm thật sự. File .env lọt vào Git history là lỗi bảo mật nghiêm trọng. Dù sau đó có xóa đi thì lịch sử vẫn còn đó, và bất kỳ ai có quyền đọc repo đều có thể lấy được secret. GitHub thậm chí có cơ chế tự động scan và vô hiệu hóa API key lộ ra — bằng chứng cho thấy đây không phải chuyện hiếm gặp.

Giải pháp gọn nhất là thiết lập .gitignore ở hai cấp: toàn cục (máy của bạn) và theo dự án (repository). Hai cái này không thay thế nhau mà bổ sung cho nhau.

Khái niệm cốt lõi: Hai lớp .gitignore

1. Global .gitignore — bảo vệ bạn khỏi chính mình

File này nằm ở máy cá nhân, áp dụng cho tất cả repository trên máy đó. Đây là nơi để khai báo những thứ thuộc về môi trường làm việc của bạn — không phải của dự án:

  • File OS: .DS_Store (macOS), Thumbs.db, desktop.ini (Windows)
  • File IDE: .idea/ (JetBrains), .vscode/ (VS Code), *.sublime-workspace
  • File editor tạm: *.swp, *~ (Vim/Emacs)

Nguyên tắc: nếu chỉ bạn dùng công cụ đó, không ai khác trong team quan tâm, thì đưa vào global — đừng bắt cả team phải ignore giúp bạn.

2. Project .gitignore — quy tắc chung của cả team

File .gitignore nằm trong root của repository, commit vào Git, áp dụng cho tất cả mọi người. Đây là nơi khai báo những thứ thuộc về ngôn ngữ, framework, build tool của dự án:

  • Thư mục build: dist/, build/, target/, __pycache__/
  • Dependency: node_modules/, vendor/, .venv/
  • File config môi trường: .env, .env.local, secrets.yaml
  • Log, coverage: *.log, coverage/, .pytest_cache/

Ranh giới này quan trọng hơn bạn nghĩ. Người dùng VS Code không nên bắt người dùng Vim phải ignore .vscode/ trong project repo — đó là việc của global gitignore, không phải của project.

Thực hành chi tiết

Bước 1: Thiết lập Global .gitignore

Tạo file và khai báo với Git:

# Tạo file global gitignore
touch ~/.gitignore_global

# Khai báo với Git
git config --global core.excludesFile ~/.gitignore_global

# Kiểm tra đã nhận chưa
git config --global core.excludesFile
# Output: /home/youruser/.gitignore_global

Nội dung gợi ý cho ~/.gitignore_global:

# === macOS ===
.DS_Store
.AppleDouble
.LSOverride
Icon?
._*

# === Windows ===
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/

# === Linux ===
*~
.fuse_hidden*
.Trash-*

# === JetBrains IDEs (IntelliJ, PyCharm, GoLand...) ===
.idea/
*.iml
*.iws

# === VS Code ===
.vscode/
!.vscode/extensions.json

# === Vim / Neovim ===
*.swp
*.swo
[._]*.s[a-v][a-z]
[._]*.sw[a-p]

# === Emacs ===
\#*\#
.\#*

# === Sublime Text ===
*.sublime-workspace

Chú ý dòng !.vscode/extensions.json — dùng ! để un-ignore một file cụ thể trong thư mục đã bị ignore. File extensions.json liệt kê extension khuyến nghị cho dự án; nhiều team muốn commit cái này để mọi người có môi trường VS Code đồng nhất. Đừng ignore mù quáng cả thư mục rồi sau đó mới phát hiện ra mình cần giữ lại vài file trong đó.

Bước 2: Template .gitignore theo dự án

Thay vì viết từ đầu, dùng gitignore.io hoặc GitHub’s gitignore templates:

# Dùng curl để tạo .gitignore cho Python project
curl -sL https://www.toptal.com/developers/gitignore/api/python,linux,macos > .gitignore

# Hoặc dùng GitHub CLI (nếu đã cài)
gh repo create --gitignore Python

Template cho Python project (những phần quan trọng nhất):

# === Python ===
__pycache__/
*.py[cod]
*.pyo
*.pyd
.Python

# Virtual environments
.venv/
venv/
env/
.env/

# Distribution / packaging
build/
dist/
*.egg-info/
*.egg

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/

# Type checking
.mypy_cache/
.pytype/

# Jupyter
.ipynb_checkpoints/

# Environment variables — NEVER commit this
.env
.env.local
.env.*.local

Template cho Node.js project:

# === Node.js ===
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# Build output
dist/
build/
.next/
.nuxt/

# Cache
.npm
.eslintcache
.parcel-cache/

# Testing
coverage/

# Environment
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

Bước 3: Xử lý file đã lỡ commit

Thêm vào .gitignore thôi chưa đủ nếu file đã được Git track. Git sẽ vẫn theo dõi nó. Phải xóa khỏi tracking:

# Xóa một file khỏi tracking (giữ file trên disk)
git rm --cached path/to/file

# Xóa cả thư mục khỏi tracking
git rm --cached -r node_modules/

# Xóa tất cả file đang bị track nhưng khớp với .gitignore hiện tại
git ls-files -i --exclude-standard | xargs git rm --cached

# Sau đó commit lại
git commit -m "chore: remove tracked files that should be gitignored"

Với file nhạy cảm đã lỡ push lên remote — như .env chứa API key — chỉ xóa rồi commit lại là không đủ. Phải dùng git-filter-repo (hoặc git filter-branch nếu dùng git cũ) để xóa khỏi toàn bộ lịch sử. Đây là thao tác rewrite history, cần thông báo cả team trước khi chạy. Và bất kể làm gì, hãy rotate ngay tất cả secret đã bị lộ — coi như chúng đã bị compromise từ lúc commit.

Bước 4: Tổ chức .gitignore cho monorepo hoặc project phức tạp

Git cho phép đặt .gitignore ở bất kỳ thư mục con nào — rule sẽ áp dụng cho thư mục đó trở xuống. Hữu ích khi làm monorepo:

my-monorepo/
├── .gitignore          ← Rule chung cho toàn project
├── frontend/
│   └── .gitignore      ← Rule riêng cho frontend (Node.js)
└── backend/
    └── .gitignore      ← Rule riêng cho backend (Python)

Rule ở file con có thể override rule ở file cha. Thực tế: nếu root .gitignore ignore *.log mà bạn muốn giữ lại backend/important.log, chỉ cần thêm vào backend/.gitignore:

# backend/.gitignore
!important.log

Bước 5: Kiểm tra rule đang hoạt động

Lệnh hữu ích để debug khi không chắc file có bị ignore hay không:

# Kiểm tra file cụ thể có bị ignore không và tại sao
git check-ignore -v path/to/file
# Output: .gitignore:5:*.log    path/to/file
# (cho biết rule nào ở dòng nào đang match)

# Xem tất cả file đang bị ignore
git ls-files --others --ignored --exclude-standard

# Xem file đang được track (không bị ignore)
git ls-files

Kết luận

Setup .gitignore đúng cách ngay từ đầu dự án tiết kiệm rất nhiều đau đầu về sau. Nhớ lại nguyên tắc đơn giản: global gitignore giữ chuyện riêng của bạn (OS, IDE, editor), project gitignore giữ chuyện của cả team (ngôn ngữ, framework, secret).

Mình có 3 thói quen khi khởi tạo project mới. Một: tạo .gitignore từ template của gitignore.io. Hai: thêm .env* vào ngay — dù chưa có file đó. Ba: commit .gitignore làm commit đầu tiên, trước khi thêm bất cứ thứ gì khác. Mất 2 phút, nhưng tránh được cả tuần dọn dẹp sau này.

Với những team mới, đáng bỏ 15 phút review lại .gitignore của dự án hiện tại — thường sẽ tìm thấy vài thứ đáng thêm vào hoặc chuyển sang global.

Share: