git-tips/tips: Kho cheat sheet Git mà dev nào cũng nên bookmark
Tổng hợp và phân tích chi tiết những git tips thực chiến nhất từ repo 21k+ stars, kèm ví dụ copy-paste được ngay vào terminal.
Nguyễn Nhật Long
@nguyennhatlong1303
Mình cá là hầu hết anh em dev đều dùng Git hàng ngày, nhưng thực tế thì đa số chúng ta chỉ xoay quanh mấy lệnh quen thuộc: git add, git commit, git push, git pull, rồi thỉnh thoảng git merge hay git checkout. Gặp tình huống phức tạp hơn một chút kiểu như cần sửa commit message cũ, cherry-pick một commit từ branch khác, hay recover lại file đã xóa là bắt đầu Google tá lả. Mình cũng từng như vậy suốt mấy năm đầu đi làm.
Rồi mình tình cờ gặp repo git-tips/tips trên GitHub. Repo này hiện đã có hơn 21.7k stars, và nó đơn giản là một bộ sưu tập cực kỳ gọn gàng những git commands hay dùng nhất, được phân loại rõ ràng, kèm giải thích ngắn gọn. Nghe thì đơn giản, nhưng cái hay là nó tập trung vào những tình huống thực tế mà dev gặp hàng ngày, không phải mấy thứ lý thuyết xa vời.
Hôm nay mình sẽ đi sâu vào những tips mà mình thấy thực sự hữu ích, kèm context giải thích khi nào nên dùng và tại sao. Không chỉ copy-paste command, mà mình muốn anh em hiểu được flow đằng sau.
Những tình huống "cứu mạng" mà ai cũng gặp
Sửa commit vừa push nhầm
Đây là tình huống kinh điển. Bạn vừa commit xong, nhìn lại thấy typo trong message, hoặc quên add một file. Thay vì tạo thêm một commit mới kiểu "fix typo" hay "forgot to add file" (nhìn history xấu kinh khủng), bạn dùng:
1# Sửa commit message gần nhất2git commit --amend -m "Message mới đúng chính tả"34# Thêm file quên vào commit gần nhất mà KHÔNG đổi message5git add forgotten-file.js6git commit --amend --no-edit
Lưu ý quan trọng: nếu bạn đã push commit đó lên remote rồi, thì sau khi amend bạn phải git push --force-with-lease. Mình nhấn mạnh là --force-with-lease chứ không phải --force, vì --force-with-lease sẽ check xem có ai khác đã push lên branch đó chưa nếu có thì nó sẽ từ chối, tránh việc bạn overwrite code của đồng nghiệp.
1git push --force-with-lease
Theo kinh nghiệm của mình, cái --force-with-lease này nên được set làm default thay cho --force luôn. Bạn có thể alias nó:
1git config --global alias.pushf 'push --force-with-lease'
Recover file đã xóa
Bạn lỡ xóa một file và đã commit mất rồi? Đừng hoảng. Git lưu lại mọi thứ:
1# Tìm commit cuối cùng mà file đó còn tồn tại2git rev-list -n 1 HEAD -- path/to/deleted-file.js34# Restore file từ commit đó5git checkout <commit-hash>^ -- path/to/deleted-file.js
Dấu ^ sau commit hash nghĩa là "commit ngay trước đó" tức là commit mà file vẫn còn tồn tại, chứ không phải commit đã xóa nó.
Quay lại branch trước đó
Cái này nhỏ nhưng tiết kiệm thời gian cực kỳ:
1git checkout -
Giống như cd - trong terminal vậy nó switch về branch bạn vừa rời đi. Khi bạn đang nhảy qua nhảy lại giữa main và feature-branch thì cái này nhanh hơn gõ tên branch nhiều.
Làm việc với branches như một pro
Repo git-tips có cả một section về branching mà mình thấy rất đáng để nắm vững.
Xem tất cả branches đã merge vào master
1git branch --merged master
Cái này cực hữu ích khi bạn muốn cleanup branches cũ. Sau khi list ra, bạn có thể xóa hàng loạt:
1# Xóa tất cả local branches đã merge vào master (trừ master)2git branch --merged master | grep -v '^\* master$' | xargs -n 1 git branch -d
Mình hay chạy cái này mỗi tuần vì sau một thời gian, local repo toàn branches cũ không còn dùng nữa, nhìn git branch ra cả trang.
Xem branches được sắp xếp theo commit gần nhất
1git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:relative)' refs/heads/
Output sẽ kiểu:
1feature/payment 2 hours ago2fix/login-bug 3 days ago3main 5 days ago4old-experiment 3 months ago
Nhìn là biết ngay branch nào đang active, branch nào nên xóa đi. Mình alias cái này thành git recent:
1git config --global alias.recent 'for-each-ref --sort=-committerdate --format="%(refname:short) %(committerdate:relative)" refs/heads/'
Cherry-pick và những pha cứu nguy ngoạn mục
Cherry-pick là khi bạn muốn lấy đúng một commit cụ thể từ branch khác sang branch hiện tại, thay vì merge cả branch. Tình huống thực tế: đồng nghiệp fix một bug trên branch feature-x, mà bạn cũng cần cái fix đó trên branch feature-y của mình, nhưng chưa muốn merge cả feature-x vào.
1# Lấy commit abc123 từ branch khác2git cherry-pick abc12334# Cherry-pick nhiều commits5git cherry-pick abc123 def45667# Cherry-pick nhưng không tự động commit (để bạn review trước)8git cherry-pick abc123 --no-commit
Anh em lưu ý: cherry-pick tạo ra một commit mới với hash khác, nên nếu sau này merge branch lại thì có thể gặp duplicate changes. Không phải lúc nào cherry-pick cũng là giải pháp tốt nhất đôi khi rebase sạch hơn.
Stash nâng cao không chỉ là git stash rồi git stash pop
Đa số anh em chỉ dùng stash ở mức cơ bản. Nhưng git-tips chỉ ra mấy trick hay:
1# Stash kèm message để nhớ đang stash cái gì2git stash save "WIP: đang làm dở payment flow"34# Xem list tất cả stash5git stash list67# Apply một stash cụ thể (không phải cái mới nhất)8git stash apply stash@{2}910# Lấy MỘT FILE cụ thể từ stash11git checkout stash@{0} -- path/to/file.js
Cái cuối cùng là gem thực sự. Nhiều khi bạn stash cả đống thay đổi nhưng chỉ cần lấy lại một file thay vì pop cả stash ra rồi lại phải xử lý conflict, bạn checkout đúng file đó thôi.
Những commands mà mình ước biết sớm hơn
Đây là bảng so sánh một số tình huống phổ biến và cách xử lý "thông thường" vs cách tối ưu hơn từ git-tips:
Cái git bisect đặc biệt đáng nói. Nó dùng binary search để tìm commit gây bug. Bạn chỉ cần nói cho Git biết commit nào "good" (chưa có bug) và commit nào "bad" (đã có bug), rồi Git sẽ tự checkout các commit ở giữa để bạn test. Thay vì phải check 100 commits, bạn chỉ cần check khoảng 7 commits (log₂ 100). Mình đã dùng cái này để tìm một regression bug trong project có hàng nghìn commits tiết kiệm cả buổi chiều.
| Tình huống | Cách hay làm | Cách tối ưu hơn |
|---|---|---|
| Xem diff ngắn gọn | `git diff` (output dài) | `git diff --stat` (chỉ hiện tên file + số dòng thay đổi) |
| Xem log đẹp | `git log` | `git log --oneline --graph --decorate --all` |
| Tìm commit gây bug | Checkout từng commit thủ công | `git bisect start` → `git bisect bad` → `git bisect good <hash>` |
| Xóa branch remote | Lên GitHub xóa tay | `git push origin --delete branch-name` |
| Xem ai sửa dòng nào | Mở GitHub blame | `git blame path/to/file.js` |
| Commit rỗng (trigger CI) | Sửa linh tinh rồi commit | `git commit --allow-empty -m "trigger CI"` |
| Xem status nhanh | `git status` (verbose) | `git status -sb` (short + branch info) |
1git bisect start2git bisect bad # commit hiện tại có bug3git bisect good v1.0.0 # tag/commit mà bạn biết chắc chưa có bug4# Git sẽ checkout commit ở giữa, bạn test rồi đánh dấu:5git bisect good # nếu commit này OK6git bisect bad # nếu commit này có bug7# Lặp lại cho đến khi Git tìm ra commit gây bug8git bisect reset # quay về branch ban đầu
Stage từng phần của file interactive staging
Đây là feature mà mình thấy ít người biết nhưng cực kỳ powerful:
1git add -p
Lệnh này cho phép bạn chọn từng hunk (từng đoạn thay đổi) trong một file để stage, thay vì stage cả file. Tại sao lại cần? Vì đôi khi bạn sửa một file nhưng có 2 thay đổi logic khác nhau ví dụ vừa fix bug vừa refactor tên biến. Bạn muốn tách thành 2 commits riêng biệt cho clean history.
Khi chạy git add -p, Git sẽ hiện từng đoạn thay đổi và hỏi bạn:
ystage đoạn nàynbỏ quassplit thành đoạn nhỏ hơneedit thủ công
Mình dùng cái này gần như mỗi ngày. Nó giúp commit history sạch đẹp hơn rất nhiều so với kiểu "commit cả đống thay đổi vào một commit".
CLI tool đi kèm: git-tip
Repo này còn có một CLI tool tên là git-tip cài qua npm:
1npm install -g git-tip
Sau đó mỗi lần mở terminal, bạn gõ git-tip là nó random hiện một tip cho bạn. Mình hay bỏ cái này vào .bashrc hoặc .zshrc để mỗi lần mở terminal lên là học được một tip mới:
1# Thêm vào cuối ~/.zshrc2echo "💡 Git tip of the day:"3git-tip
Cách học kiểu này hiệu quả hơn ngồi đọc cả list một lúc rất nhiều, vì mỗi ngày bạn chỉ tiếp thu một thứ nhỏ, dần dần nó ngấm vào workflow tự nhiên.
Mấy alias mà mình recommend setup ngay
Dựa trên những tips từ repo, đây là bộ alias mình đang dùng hàng ngày:
1git config --global alias.co 'checkout'2git config --global alias.br 'branch'3git config --global alias.ci 'commit'4git config --global alias.st 'status -sb'5git config --global alias.lg 'log --oneline --graph --decorate --all'6git config --global alias.unstage 'reset HEAD --'7git config --global alias.last 'log -1 HEAD --stat'8git config --global alias.pushf 'push --force-with-lease'9git config --global alias.recent 'for-each-ref --sort=-committerdate --format="%(refname:short) %(committerdate:relative)" refs/heads/'10git config --global alias.aliases 'config --get-regexp alias'
Cái cuối cùng git aliases để xem lại tất cả alias bạn đã setup vì setup nhiều quá đôi khi quên mất mình có alias gì.
Repo này phù hợp với ai?
Thẳng thắn mà nói, nếu bạn chỉ dùng Git qua GUI (GitKraken, SourceTree, hay VS Code built-in), thì nhiều tips trong này bạn có thể không cần. Nhưng theo kinh nghiệm của mình, hiểu được CLI commands đằng sau giúp bạn debug nhanh hơn khi GUI tool gặp vấn đề, và quan trọng hơn là hiểu được Git thực sự hoạt động như thế nào.
Repo có hơn 21k stars không phải tự nhiên. Nó được maintain tốt, có đóng góp từ cộng đồng, và đặc biệt là có bản dịch tiếng Việt (cùng nhiều ngôn ngữ khác). Mình suggest anh em bookmark lại, không cần đọc hết một lúc cứ mỗi khi gặp tình huống lạ với Git thì vào tìm, khả năng cao là có sẵn solution trong đó rồi.
Còn nếu bạn muốn đọc dạng sách thì repo cũng có bản GitBook interactive đọc trên web khá tiện, có mục lục và tìm kiếm được.
Nguyễn Nhật Long
@nguyennhatlong1303Nguyễn Nhật Long is a Senior Frontend Engineer and Frontend Team Leader with 7 years of experience building real-time fintech platforms. Specializing in React, Next.js, TypeScript, and React Native, shipping 10+ products across Web, Mobile, Telegram Mini-Apps, and Web3.
Thấy hay? Chia sẻ cho bạn bè!