- Git Flow là gì? Có những branching strategy nào phổ biến?
Git Flow có 5 loại branch: main (production), develop (tích hợp code), feature/ (tính năng mới), release/ (chuẩn bị release), hotfix/ (sửa lỗi khẩn cấp). Trunk-based Development là hướng ngược lại: commit thẳng vào main với feature flags, phù hợp team CI/CD mature. Thực tế…
- Git rebase vs merge khác nhau? Khi nào dùng gì?
Merge: tạo merge commit, giữ history đầy đủ, safe cho shared branches. Rebase: rewrite history thành linear, clean hơn, KHÔNG dùng cho shared branches. Best practice: rebase feature branch lên develop trước khi merge (hoặc squash merge). git rebase -i để clean commits.
- Git Flow và Trunk-based development khác nhau thế nào? Khi nào dùng cái nào?
Git Flow: nhiều nhánh dài hạn — main, develop, feature/, release/, hotfix/. Hợp khi: release theo chu kỳ dài, cần maintain nhiều version song song, team lớn cần tách biệt. Nhược điểm: feature branch sống lâu → merge conflict lớn; hotfix phải merge vào cả…
- GitHub Flow vs Git Flow: dự án startup 5 người nên chọn cái nào và tại sao?
GitHub Flow (đơn giản): main là production-ready, mọi tính năng làm trên branch từ main, PR → review → merge → deploy ngay. Chỉ có 1 loại branch ngoài main. Git Flow (phức tạp): main + develop + feature/ + release/ + hotfix/. Overhead cao…
- Feature branch của bạn đã sống được 2 tuần và bây giờ cách main 50 commits. Chiến lược nào để merge mà không gây sự cố nghiêm trọng?
- Monorepo với nhiều teams: branching strategy nào phù hợp và làm sao tránh teams block lẫn nhau?
Monorepo không thay đổi branching strategy cơ bản nhưng tăng complexity của conflict và CI. Recommended: trunk-based + CODEOWNERS + scoped CI CODEOWNERS (/.github/CODEOWNERS): định nghĩa team nào review phần nào: PR chỉ require approval từ owner của file được thay đổi → teams không…
- Production có bug nghiêm trọng lúc 2 giờ sáng, team đang giữa sprint. Quy trình hotfix đúng chuẩn là gì?
Git Flow hotfix: GitHub Flow hotfix (đơn giản hơn): Lưu ý: luôn merge hotfix vào cả production branch VÀ development branch — đừng để fix bị mất ở lần deploy tới. Tag version sau hotfix để dễ rollback. Viết post-mortem sau khi hệ thống ổn…
- Release branch có tác dụng gì? Khi nào cần và khi nào là overhead không cần thiết?
Release branch (release/1.5.0) tách quá trình stabilize một version khỏi ongoing development. Flow: feature freeze → tạo release branch → chỉ bug fixes được merge vào → QA → deploy → merge về main + tag. Cần release branch khi: - QA cycle dài (days/weeks)…
- Branch protection rules trên GitHub: cần cấu hình gì để prevent team push thẳng lên main?
Vào GitHub repo → Settings → Branches → Add branch protection rule cho main: Tối thiểu cần bật: - Require a pull request before merging — không ai push thẳng - Require approvals (1-2 reviewers) - Dismiss stale pull request approvals when new commits are…
- Polyrepo vs Monorepo: git workflow khác nhau như thế nào và khi nào nên migrate?
- Conventional Commits là gì? Tại sao nên enforce bằng commitlint thay vì chỉ "agree" trong team?
Conventional Commits là convention format: type(scope): description. Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert. Tại sao không chỉ "agree": agreement không có enforcement = mọi người quên hoặc bỏ qua khi deadline gần. Sau 3 tháng, git log trở thành…
- Interactive rebase: làm sao dùng squash, fixup, reword, drop để clean up history trước khi merge PR?
Interactive rebase (git rebase -i) cho phép edit lịch sử commit local trước khi share. Workflow chuẩn trước merge PR: Trong editor hiện ra: Thay đổi: - squash (s): merge commit này vào trước, giữ message - fixup (f): merge vào trước, BỎ message (dùng…
- Khi nào nên squash merge PR thay vì merge commit? Trade-offs là gì?
3 merge strategies trên GitHub: Merge commit (--no-ff): tạo merge commit, giữ toàn bộ history của branch. git log --graph thấy branch structure. Tốt cho: feature branches quan trọng muốn preserve full context. Squash merge: tất cả commits của PR → 1 commit trên main.…
- Vừa commit nhầm (message sai hoặc quên file), làm sao sửa mà không tạo commit mới?
Amend last commit — chỉ dùng khi commit CHƯA push: Nếu đã push (chỉ branch của riêng bạn): Lưu ý: - --amend tạo commit MỚI với hash khác — không phải edit in-place - KHÔNG amend commits trên main/develop hoặc bất kỳ shared branch -…
- Vô tình `git reset --hard` xoá mất 3 commit chưa push, làm sao recover?
- Signed commits với GPG/SSH là gì? Khi nào enterprise team cần enforce?
Signed commits đảm bảo commit thực sự từ người có private key tương ứng — chống giả mạo identity (bất kỳ ai cũng có thể set git config user.email thành email của bạn). Setup GPG signing: SSH signing (mới hơn, dễ hơn GPG): GitHub hiển…
- Atomic commits là gì? Tại sao 1 commit "feat: add user auth + fix navbar + update deps" lại là anti-pattern?
Atomic commit: mỗi commit chứa MỘT logical change hoàn chỉnh — pass tests độc lập, có thể revert độc lập, message mô tả đủ ý. Tại sao commit "fat" là anti-pattern: 1. Revert bị ràng buộc: cần revert chỉ navbar fix nhưng buộc phải revert…
- CODEOWNERS file hoạt động như thế nào? Cách dùng để enforce review chính xác trong team lớn?
- Merge vs Rebase: khi nào dùng cái nào? Giải thích golden rule of rebasing.
Merge: tạo merge commit, preserve history đầy đủ. git log --graph thấy nhánh. Non-destructive — không thay đổi existing commits. Rebase: replay commits lên trên branch khác, tạo linear history. Rewrite commit hashes. Golden Rule of Rebasing: KHÔNG BAO GIỜ rebase branch đã được share/push…
- Đang rebase gặp conflict phức tạp ở nhiều commits. Chiến lược xử lý mà không bị "rebase hell"?
- Fast-forward merge vs no-ff merge: khác nhau gì? GitHub mặc định dùng cái nào và tại sao team nên chủ động chọn?
Fast-forward merge (mặc định khi có thể): nếu branch hiện tại là ancestor trực tiếp của branch cần merge, git chỉ di chuyển HEAD pointer lên — không tạo merge commit. History linear. No-ff merge (--no-ff): luôn tạo merge commit dù có thể fast-forward. Trade-offs:…
- 3-way merge là gì? Git tự động resolve như thế nào và khi nào phải manual resolve?
- `git rerere` là gì? Khi nào nó giúp bạn khỏi phải resolve một conflict nhiều lần?
- Đang merge feature branch vào main, gặp conflict trong file do cả 2 sides đều refactor. Quy trình resolve an toàn?
Worst case conflict: không phải thêm/xoá dòng đơn giản mà là structural refactor — function bị rename, logic được reorganize. Quy trình an toàn: 1. Hiểu context trước khi resolve: 2. Dùng 3-panel merge tool — git mergetool (trái: ours, phải: theirs, giữa: base —…
- Undo một public commit đã merge vào main: revert vs reset — khi nào dùng cái nào?
Reset (git reset --hard HEAD~1): di chuyển HEAD pointer về commit cũ, xoá commits khỏi history. KHÔNG dùng trên main/shared branch — sẽ cần force push, làm hỏng history của mọi người đã pull. Revert (git revert <commit): tạo commit MỚI undo changes của commit…
- Rebase interactive: edit mode cho phép làm gì mà squash không làm được?
- Teammate vừa force push lên shared branch làm mất commits của bạn. Recover như thế nào?
- `git bisect` hoạt động như thế nào? Scenario thực tế dùng nó tìm commit gây regression?
- `git log -S` và `git log -G` dùng để làm gì? Khi nào chúng giúp ích lúc debug?
Pickaxe search — tìm commits đã thêm/xoá một chuỗi cụ thể trong code. - git log -S "string" (pickaxe): tìm commits mà số lần xuất hiện của string thay đổi (thêm hoặc xoá) — chính xác hơn khi code bị rename/move. - git log -G…
- Branch bị xoá nhầm, chưa merge vào đâu cả. Recover như thế nào?
Branch chỉ là pointer đến commit. Xoá branch không xoá commits — chỉ xoá pointer. Commits vẫn tồn tại trong git object store cho đến khi git gc chạy. Recovery qua reflog: - Không nhớ tên branch: git reflog grep "checkout: moving from" — tìm…
- `git blame` trong thực tế: nó không chỉ để "đổ lỗi" — những use case thực sự hữu ích là gì?
git blame <file hiển thị mỗi dòng: commit hash, author, date, line content — ai viết dòng đó khi nào. Use cases thực sự hữu ích: 1. Hiểu context của code lạ: git blame src/utils/pricing.ts -L 23,35 → thấy dòng 28 do ai viết 6…
- Production deploy xong thì phát hiện bug. Cần rollback ngay. `git revert` hay deploy từ previous tag?
- `--force` vs `--force-with-lease`: tại sao force-with-lease an toàn hơn và team nên enforce như thế nào?
git push --force: overwrite remote không kiểm tra gì — nếu teammate đã push commits mới lên remote mà bạn chưa fetch, bạn sẽ overwrite và mất work của họ. git push --force-with-lease: kiểm tra remote ref trước khi overwrite — chỉ force push nếu…
- Khi nào force push là acceptable và khi nào tuyệt đối không được phép?
Force push ACCEPTABLE: 1. Feature branch của riêng bạn, chưa ai review/pull: sau git rebase -i để clean up commits trước PR 2. Personal fork: không ảnh hưởng ai 3. Sau git commit --amend trên branch riêng: cần update remote 4. Reset --hard và force…
- Vừa force push nhầm lên main, history bị overwrite. Quy trình khôi phục khẩn cấp?
- Vô tình commit file `.env` chứa credentials lên remote. Xử lý như thế nào?
Credentials đã push = credentials bị compromise. Rotate ngay lập tức — đây là ưu tiên số 1. Bước 1: Rotate credentials (NGAY LẬP TỨC): - API keys, DB passwords, JWT secrets → revoke và generate mới - Không chờ xoá khỏi git — ai…
- Large file vô tình được commit vào git history, làm repo nặng. Xoá khỏi history mà không ảnh hưởng người khác trong team?
- `git worktree` là gì? Khi nào nó tốt hơn stash hoặc tạo clone thứ 2?
- `git stash` nâng cao: push, pop, apply, list, show, drop — những pattern thực tế cần biết?
Cơ bản hay bị hiểu nhầm: - git stash = git stash push — stash working dir + index - pop = apply + drop (xoá stash sau khi apply) - apply = apply nhưng GIỮ stash (dùng khi muốn apply vào nhiều branches) Patterns…
- `git cherry-pick` trong thực tế: khi nào là công cụ đúng và khi nào là dấu hiệu branching strategy có vấn đề?
git cherry-pick <commit copy 1 commit từ branch khác vào branch hiện tại — tạo commit mới với cùng changes nhưng hash khác. Khi cherry-pick là đúng: 1. Hotfix cần apply vào nhiều release branches: 2. Lấy 1 commit cụ thể từ branch của đồng…
- Partial clone và shallow clone: khi nào dùng trong CI/CD để tăng tốc pipeline?
- Git submodules vs git subtrees: tại sao hầu hết teams tránh cả hai?
- Git LFS là gì? Setup thực tế cho dự án có design files và build artifacts lớn?
- Tại sao `git pull` thường tạo merge commit không cần thiết và cách fix với `--rebase`?
Vấn đề: bạn có local commits chưa push. Teammate đã push lên remote. git pull = git fetch + git merge → tạo merge commit "Merge branch 'main' of github.com/..." không mang thông tin gì, git log --graph đầy những vòng merge vô nghĩa. Fix:…
- Setup pre-commit hook với Husky + lint-staged: tại sao chỉ lint files đang staged thay vì cả project?
Vấn đề nếu lint cả project trên mỗi commit: - Project lớn → eslint . mất 30-60 giây → developers tắt hooks - Không liên quan: bạn sửa 1 file nhưng phải đợi 500 files khác lint Giải pháp là lint-staged: chỉ chạy linter trên…
- commit-msg hook với commitlint: cách setup và làm thế nào để không block developer khi làm WIP commits?
commit-msg hook chạy sau khi developer viết commit message — có thể reject nếu message không hợp lệ. Setup: npm i -D @commitlint/cli @commitlint/config-conventional, file .husky/commit-msg (Husky v9) chỉ chứa 1 dòng npx --no -- commitlint --edit $1. commitlint.config.js: Cho phép WIP commits (không block…
- pre-push hook chạy tests: trade-offs và cách configure để không làm chậm developer workflow?
pre-push hook chạy trước khi git push — có thể block push nếu tests fail. Trade-off chính: - Bảo vệ remote branch khỏi broken code - Nhưng full test suite có thể mất 5-10 phút → developers tìm cách lách (push thẳng không qua hook)…
- semantic-release: làm sao tự động hoá versioning và CHANGELOG từ conventional commits?
- Server-side hooks (GitHub Actions) vs client-side hooks (Husky): nên dùng cái nào để enforce gì?
- `git fetch` và `git pull` khác nhau như thế nào? Khi nào chỉ nên fetch?
git fetch tải commits/refs mới từ remote về remote-tracking branches (origin/main) — KHÔNG đụng vào working directory hay local branch. git pull = git fetch + git merge (hoặc + git rebase nếu config pull.rebase) — tích hợp thẳng vào branch hiện tại. Chỉ nên…
- Merge conflict xảy ra khi nào? Quy trình resolve một conflict cơ bản?
Conflict xảy ra khi git không thể tự hợp nhất: 2 branch cùng sửa 1 vùng dòng của cùng file, hoặc 1 bên xoá file mà bên kia sửa. Git dừng merge và chèn conflict markers vào file: Quy trình resolve: 1. git status —…
- Detached HEAD là gì? Checkout một commit cũ để xem code rồi quay lại như thế nào?
Bình thường HEAD trỏ vào một branch; commit mới sẽ kéo branch đi theo. Khi bạn git checkout <commit-hash (hoặc checkout tag), HEAD trỏ thẳng vào commit — trạng thái "detached HEAD". Code vẫn xem/build/test được bình thường, nhưng commit mới tạo ở đây không…
- File đã lỡ commit (vd `node_modules/`, file log) — thêm vào `.gitignore` rồi mà git vẫn track. Xử lý thế nào?
.gitignore chỉ có tác dụng với file chưa được track. File đã commit thì git tiếp tục track bất kể .gitignore — phải gỡ khỏi index: Lưu ý: - Thiếu --cached → git rm xoá luôn file thật trên disk - File vẫn nằm trong…