Bài 01

Git hằng ngày: clone, commit, branch, gitignore

06 tháng 5, 2026 · 45 phút đọc

Bài 01 — Git hằng ngày: clone, commit, branch, gitignore

Bạn vừa được nhận vào team. Sếp bảo "clone repo, làm task, push lên". Bạn đã từng git commit -m "fix" đại khái — nhưng chưa chắc làm đúng. Bài này gói 90% Git mà DevOps gõ hằng ngày.


Mental model — đủ để hiểu, không thừa

Git lưu snapshot của code, mỗi snapshot có 1 SHA hash 40 ký tự.

3 khu vực phải biết:

Working dir   →   Staging   →   Repo (.git)   →   Remote
   (edit)       (git add)    (git commit)      (git push)

Branch = con trỏ trỏ vào 1 commit. Không phải "thư mục code". Tạo/xoá branch = tạo/xoá file 41 byte. Đây là toàn bộ lý thuyết bạn cần.

Hệ quả: xoá branch không xoá commit. Commit vẫn còn trong .git, chỉ mất con trỏ. Reflog (Bài 03) sẽ tìm lại.


Setup 1 lần

git config --global user.name "Tên Bạn"
git config --global user.email "ban@example.com"

# Pull mặc định rebase — history sạch hơn
git config --global pull.rebase true

# Branch mặc định khi init repo mới
git config --global init.defaultBranch main

SSH key cho GitHub/GitLab:

ssh-keygen -t ed25519 -C "ban@example.com"
cat ~/.ssh/id_ed25519.pub
# Paste vào GitHub: Settings → SSH and GPG keys → New SSH key

Test:

ssh -T git@github.com
# Hi <username>! You've successfully authenticated...

Workflow hằng ngày — 6 bước

# 1. Clone (lần đầu) hoặc pull (sau)
git clone git@github.com:org/repo.git
cd repo
# (lần sau) git pull

# 2. Tạo branch cho task
git switch -c feat/add-login

# 3. Edit code, xem trạng thái
git status

# 4. Stage + commit
git add file1.js file2.js     # add file cụ thể
# hoặc git add .              # add hết (cẩn thận file lạ)
git commit -m "feat(auth): add login form"

# 5. Push (lần đầu cần -u, sau đó push thuần)
git push -u origin feat/add-login

# 6. Tiếp tục commit, push
git commit -am "feat(auth): handle errors"   # -a: auto add file đã track
git push

-u (set-upstream) chỉ cần lần đầu. Sau đó git push không argument.


Commit message: Conventional Commits

Format:

type(scope): subject

Types hay dùng:

  • feat: tính năng mới
  • fix: sửa bug
  • chore: việc lặt vặt (deps, config)
  • docs: chỉ doc
  • refactor: refactor không đổi behavior
  • ci: CI/CD

Ví dụ:

feat(auth): add JWT refresh token
fix(payment): handle null response from gateway
chore(deps): bump terraform to 1.6.0

Đừng viết: fix, update, wip, asdf. 6 tháng sau chính bạn không hiểu commit của mình làm gì.

Atomic commit: 1 commit = 1 ý đồ. Đừng gộp "fix bug + format code + thêm feature" vào 1 commit. Khi cần revert hoặc bisect (Bài 03), bạn sẽ cảm ơn bản thân.


Xem history & diff

git log --oneline -20                # 20 commit gần nhất
git log --oneline --graph --all      # cây nhánh
git log --author="Hung"              # commit của ai
git log -p file.js                   # lịch sử 1 file kèm diff

git diff                             # working vs staging
git diff --staged                    # staging vs commit cuối
git diff main..feat/login            # khác biệt 2 branch
git diff HEAD~3                      # so với 3 commit trước

Học git log --oneline --graph --all cho thuộc — lệnh xem thiên hạ đang làm gì.


Branch — gọn, ngắn ngày

git branch                    # local
git branch -a                 # cả remote
git switch main               # chuyển nhánh
git switch -c feat/x          # tạo + chuyển
git branch -d feat/x          # xoá nếu đã merge (an toàn)
git branch -D feat/x          # xoá force (cẩn thận, mất commit)
git push origin --delete feat/x   # xoá branch trên remote

Quy ước đặt tên (chọn 1, dùng nhất quán):

  • feat/short-desc — tính năng
  • fix/issue-x — bug
  • hotfix/critical — khẩn cấp
  • chore/update-deps — vặt

Tránh: temp, test, my-branch, hung-branch. Không scale.

Branch sống ≤ 5 ngày. Feature lớn → split nhỏ. Branch sống 2 tuần = mega conflict khi merge (Bài 02).

Cleanup định kỳ:

# Fetch + xoá local ref của branch đã xoá ở remote
git fetch --prune

# Xoá branch local đã merge
git branch --merged main | grep -v main | xargs -r git branch -d

.gitignore — cài ngay từ commit đầu tiên

Quan trọng nhất: không bao giờ commit secret. .gitignore template gọn cho DevOps:

# Secrets
.env
.env.*
*.key
*.pem
credentials*

# Dependencies
node_modules/
.venv/
__pycache__/
*.pyc

# Build / artifact
dist/
build/

# IDE
.vscode/
.idea/
.DS_Store

# Terraform / IaC
*.tfstate
*.tfstate.backup
.terraform/

Test xem file có bị ignore không:

git check-ignore -v .env
# .gitignore:2:.env       .env

Lỡ commit secret rồi

git rm --cached .env             # gỡ tracking, giữ file local
echo ".env" >> .gitignore
git commit -m "chore: stop tracking .env"

⚠️ History vẫn còn secret. Bot scan GitHub liên tục tìm AWS key, GitHub token. Quy trình đúng:

  1. Rotate secret NGAY. Coi như đã leak. Disable AWS key, tạo cái mới, update vào secret manager.
  2. (Tuỳ chọn) Rewrite history:
    pip install git-filter-repo
    git filter-repo --path .env --invert-paths --force
    git push --force --all
  3. Notify team pull lại.

Câu chuyện thực tế

Tháng 3/2024, intern mới lỡ commit .env chứa AWS_ACCESS_KEY_ID lên repo private. 6 tiếng sau, AWS bill nhảy từ $50 → $2000/ngày — bot scan tìm thấy key, launch 50 EC2 GPU đào crypto.

Action: disable key, terminate instance, rotate, rewrite history. AWS sau refund vì là fraud, nhưng 4 tiếng sự cố lúc 11h đêm.

Bài học: .gitignore từ commit ĐẦU TIÊN. Pre-commit hook (gitleaks, detect-secrets) chặn tự động — đừng tin discipline cá nhân (Bài 03 setup hook).


Lab — chạy thử

mkdir /tmp/git-daily && cd /tmp/git-daily
git init

# .gitignore từ đầu
cat > .gitignore <<EOF
.env
*.key
node_modules/
EOF

echo "# Project" > README.md
git add . && git commit -m "chore: initial commit"

# Workflow
git switch -c feat/greeting
echo 'echo "Hello"' > hello.sh
git add hello.sh
git commit -m "feat(greeting): add hello script"

# Edit thêm
echo 'echo "World"' >> hello.sh
git diff
git commit -am "feat(greeting): add world line"

# Atomic: 2 thay đổi không liên quan → 2 commit
echo "Hello world" >> README.md
echo 'echo "Bye"' >> hello.sh

git add README.md
git commit -m "docs: update readme"

git add hello.sh
git commit -m "feat(greeting): add bye line"

# Xem history
git log --oneline --graph --all

# Test gitignore
echo "secret123" > .env
git status
# .env không xuất hiện trong "Untracked files" — đã ignore

Pitfalls — chốt lại

  1. git add . lúc đang edit nhiều thứ → add nhầm secret/build. Add file cụ thể hoặc dùng git add -p (interactive, chọn từng đoạn).
  2. Commit message "fix", "wip" → vô dụng cho future you và teammate. Dùng Conventional Commits.
  3. Branch sống quá lâu → conflict tệ. ≤ 5 ngày, sync main mỗi ngày (Bài 02).
  4. Commit .env dù 1 lần → rotate ngay, không "private repo nên an toàn".
  5. -D thay vì -d khi xoá branch chưa merge → mất commit. Dùng -d mặc định, -D chỉ khi chắc chắn.

Tóm tắt

  • Setup 1 lần: name, email, pull.rebase=true, SSH key.
  • Workflow: clone → branch → edit → add → commit → push (-u lần đầu).
  • Commit: Conventional Commits format, atomic (1 ý đồ).
  • Branch ngắn ngày, naming rõ ràng, -d mặc định.
  • .gitignore từ commit đầu. Lỡ commit secret → rotate ngay.

Bài tiếp: 02 — Làm việc team: merge, rebase, conflict, PR, GitFlow vs Trunk-based.

Bài tiếp theo →
Bài 02
Zalo tư vấn