Tạm lưu công việc với git stash: Mẹo dùng stash chuyên nghiệp khi cần chuyển nhánh gấp
Hướng dẫn git stash từ cơ bản đến chuyên nghiệp: stash file tracked/untracked, đặt tên, xem diff, apply, pop, drop, stash từng phần, xử lý conflict và khôi phục an toàn.
ShanverseUpdated 12 min read— viewsLoading views
Git
Developer Tools
Một tình huống quen thuộc: bạn đang sửa nhiều file trên feature/profile, chưa đủ hoàn chỉnh để tạo commit, nhưng team yêu cầu kiểm tra ngay một lỗi production. Git có thể từ chối chuyển branch nếu thay đổi hiện tại sẽ bị ghi đè. git stash giúp cất chúng đi, làm sạch working tree, rồi khôi phục khi bạn quay lại.
Tuy nhiên, stash không phải nơi lưu trữ dài hạn. Muốn dùng chuyên nghiệp, bạn cần hiểu nó lưu gì, không lưu gì và sự khác nhau giữa apply, pop, drop, branch, -u,
Comments
-a
,
--keep-index
và
-p
.
git stash hoạt động như thế nào?
Stash lưu snapshot của thay đổi trong working tree và staging area vào các object nội bộ của repository, sau đó đưa working tree về trạng thái sạch phù hợp.
Mermaid
Loading diagram…
Mỗi stash được tham chiếu dạng:
stash@{0} thường là stash mới nhất.
Khi nào nên dùng stash?
Stash phù hợp khi:
Cần chuyển branch gấp nhưng thay đổi chưa sẵn sàng commit.
Muốn pull/rebase trên working tree sạch.
Cần thử một hướng sửa khác trong thời gian ngắn.
Muốn tạm loại bỏ một phần thay đổi để test.
Muốn giữ staged snapshot và cất phần còn lại.
Không nên dùng stash như:
Kho lưu công việc nhiều tuần.
Cách thay thế commit có ý nghĩa.
Backup duy nhất cho thay đổi quan trọng.
Nơi cất hàng chục thay đổi không có tên.
Nếu công việc cần chia sẻ, review hoặc tồn tại lâu, hãy tạo branch và commit WIP có chủ đích.
Quy trình nhanh khi phải chuyển branch gấp
Quy trình dùng apply trước rồi drop sau an toàn hơn pop khi thay đổi quan trọng.
1. Tạo stash cơ bản
Cách rõ ràng, nên ưu tiên:
Cú pháp ngắn vẫn hoạt động:
Đặt message để dễ tìm:
Xem danh sách:
Kết quả có thể như:
2. Stash có lưu file Untracked không?
Mặc định, git stash push lưu thay đổi của file tracked, gồm staged và unstaged. Nó thường không lưu file Untracked.
Bao gồm file Untracked:
-u là viết tắt của --include-untracked.
Bao gồm cả file ignored:
-a là viết tắt của --all.
3. Stash từng file hoặc đường dẫn
Chỉ cất một số file:
Dấu -- ngăn Git hiểu tên file như option.
Stash một thư mục:
Các thay đổi không khớp pathspec vẫn ở working tree.
4. Stash từng phần với --patch
Khi một file chứa nhiều thay đổi nhưng chỉ muốn cất một số hunk:
Hoặc:
Git hỏi từng hunk:
Đây là công cụ mạnh để tách thay đổi logic khỏi debug code hoặc công việc chưa liên quan.
5. Giữ staged changes bằng --keep-index
Giả sử bạn đã stage phần sẵn sàng commit, nhưng working tree còn thay đổi dở dang.
Kết quả:
Phần đã staged vẫn ở index.
Thay đổi chưa staged được cất.
Bạn có thể test hoặc commit phần đã chọn.
Quy trình hữu ích:
6. Chỉ stash phần đã staged
Với phiên bản Git hỗ trợ:
Lệnh này cất nội dung trong staging area và giữ phần unstaged ở working tree. Hãy chạy git status và git diff sau đó để xác nhận đúng lớp thay đổi mong muốn.
7. Xem stash trước khi khôi phục
Danh sách stash:
Tóm tắt file thay đổi trong stash mới nhất:
Xem patch đầy đủ:
Xem tên file:
Xem thống kê:
Không nên pop một stash cũ chỉ dựa trên số thứ tự. Hãy đọc message và diff trước.
8. apply và pop khác nhau thế nào?
git stash apply
Khôi phục thay đổi.
Giữ stash trong danh sách.
An toàn hơn khi muốn kiểm tra trước.
git stash pop
Khôi phục thay đổi.
Xóa stash nếu áp dụng thành công.
Nếu conflict xảy ra, stash thường được giữ để bạn không mất dữ liệu.
Khuyến nghị với thay đổi quan trọng:
Khôi phục cả staged state
Mặc định, apply có thể không khôi phục staging đúng như trước. Dùng --index:
Hoặc:
Việc khôi phục index có thể conflict nếu staging area hiện tại không tương thích.
9. Áp dụng stash sang branch khác
Bạn có thể tạo stash trên branch A rồi áp dụng trên branch B:
Điều này hữu ích khi nhận ra công việc đang được làm trên nhầm branch.
Quy trình:
Nếu code nền khác nhiều, conflict có thể xảy ra.
10. Tạo branch trực tiếp từ stash
Khi branch hiện tại đã thay đổi nhiều khiến apply conflict, tạo branch từ commit gốc nơi stash được tạo:
Git sẽ:
Tạo branch mới từ commit gốc của stash.
Checkout branch đó.
Áp dụng stash.
Xóa stash nếu áp dụng thành công.
Đây là một trong những cách an toàn nhất để phục hồi stash cũ.
11. Xóa stash
Xóa một stash:
Xóa tất cả:
Sau khi drop, số thứ tự các stash còn lại có thể thay đổi. Đừng ghi nhớ một số stash@{n} trong thời gian dài mà không kiểm tra lại danh sách.
12. Xử lý conflict khi apply hoặc pop
Nếu code hiện tại đã thay đổi ở cùng vùng, stash có thể conflict.
Bắt đầu bằng:
Mở file và xử lý marker:
Sau khi tạo nội dung cuối:
Kiểm tra:
Nếu dùng pop và conflict xảy ra, không vội drop stash. Xác nhận stash vẫn còn:
Sau khi code đúng, test và commit:
13. Hủy thay đổi sau khi apply stash
Nếu vừa apply và muốn bỏ kết quả, đừng chạy lệnh phá hủy khi working tree có thay đổi khác từ trước.
Trước khi apply, cách an toàn là:
Nếu working tree sạch trước apply và bạn chắc chắn muốn bỏ toàn bộ thay đổi tracked vừa khôi phục:
File Untracked được khôi phục từ stash cần xử lý riêng. Luôn kiểm tra git status và tạo backup branch/stash nếu có bất kỳ nghi ngờ nào.
14. Stash có chứa commit không?
Không. Stash không “cất commit”; nó lưu trạng thái chưa commit. Các commit đã thuộc lịch sử branch và không biến mất khi chuyển branch theo cách thông thường.
Về mặt nội bộ, stash được biểu diễn bằng các commit-like object, nhưng workflow của người dùng vẫn nên xem nó là snapshot tạm thời, không phải lịch sử chia sẻ.
15. Tìm lại stash đã drop
Stash bị drop đôi khi vẫn còn trong object database cho tới khi garbage collection dọn dẹp, nhưng khôi phục không được đảm bảo.
Bắt đầu bằng reflog nếu còn tham chiếu:
Có thể tìm dangling commit:
Sau khi xác định đúng object bằng git show, tạo branch hoặc áp dụng commit phù hợp. Đây là thao tác phục hồi nâng cao; đừng dựa vào nó thay cho commit hoặc backup.
Mẹo chuyên nghiệp
Luôn đặt tên stash
Dùng apply trước, drop sau
Giữ đường lui cho đến khi test thành công.
Kiểm tra stash bằng patch
Không để stash tồn tại quá lâu
Cuối ngày hoặc cuối sprint, chuyển stash quan trọng thành branch và commit rõ nghĩa.
Dùng branch cho công việc có giá trị
Kiểm tra file Untracked
Trước khi stash:
Nếu có ??, quyết định có cần -u hay không.
Không stash secret theo thói quen
Nếu .env bị ignored, -a có thể đưa nó vào stash. Secret nên nằm trong hệ thống quản lý môi trường phù hợp.
Lỗi thường gặp
No local changes to save
Git không thấy thay đổi tracked phù hợp. Kiểm tra:
Nếu chỉ có file Untracked:
Stash không chứa file mới
Bạn quên -u. Nếu file vẫn ở working tree, tạo stash mới với --include-untracked.
pop nhầm stash
Nếu thay đổi chưa commit, dừng lại và kiểm tra git status, git diff và danh sách stash. Tránh reset mạnh. Khi cần, tạo một stash/branch bảo toàn trạng thái hiện tại trước khi tách các thay đổi.
Không chuyển branch được sau khi stash
Có thể còn file Untracked/ignored gây ghi đè hoặc một số thay đổi không được stash. Kiểm tra:
Dùng -u hoặc xử lý file cụ thể; không tự động dùng -a nếu có secret.
Apply đúng stash nhưng conflict nhiều
Dùng:
Branch mới từ base gốc thường giảm conflict so với áp dụng lên code đã thay đổi nhiều.
Checklist khi chuyển nhánh gấp
Chạy git status và đọc danh sách file.
Xem git diff và git diff --staged.
Quyết định có cần file Untracked với -u không.
Tránh -a nếu có file ignored nhạy cảm.
Đặt message mô tả công việc.
Xác nhận working tree sạch sau stash.
Khi quay lại, chạy git stash list và git stash show -p.
Ưu tiên apply trước pop cho thay đổi quan trọng.
Chạy test trước khi drop stash.
Chuyển stash lâu ngày thành branch và commit.
Tổng kết
Các lệnh cần nhớ:
Dùng -u khi cần cất file Untracked.
Dùng -p để chọn từng phần.
Dùng --keep-index để giữ phần đã staged.
Dùng apply để giữ đường lui, rồi drop sau khi xác nhận.
Dùng stash branch khi stash cũ conflict với code mới.
Table of contents(37)
Codeplain text
1stash@{0}2stash@{1}3stash@{2}
Codeplain text
1stash@{0}: On feature/checkout: checkout validation in progress2stash@{1}: On feature/profile: profile form before hotfix
1<<<<<<< Updated upstream2Nội dung hiện tại3=======4Nội dung từ stash5>>>>>>> Stashed changes
Codebash
1# 1. Kiểm tra trạng thái2gitstatus34# 2. Xem thay đổi trước khi cất5gitdiff6gitdiff--staged78# 3. Tạo stash có tên, gồm cả file untracked9gitstashpush-u-m"profile form before hotfix"1011# 4. Xác nhận working tree sạch12gitstatus1314# 5. Chuyển branch xử lý việc gấp15gitswitchmain16gitpull17gitswitch-chotfix/payment-timeout1819# 6. Sau khi xong, quay lại20gitswitchfeature/profile2122# 7. Xem và áp dụng stash23gitstashlist24gitstashshow-pstash@{0}25gitstashapplystash@{0}2627# 8. Kiểm tra rồi xóa stash khi chắc chắn28gitstatus29gitstashdropstash@{0}
Hướng dẫn Git Aliases và .gitconfig thực chiến: alias an toàn, log đẹp, cấu hình pull/push/rebase, includeIf cho tài khoản work/personal, bảo mật và chia sẻ dotfiles.
Phân tích Gitflow vs GitHub Flow vs Trunk-Based Development: cấu trúc branch, ưu nhược điểm, điều kiện áp dụng, ma trận quyết định và lộ trình chuyển đổi cho từng loại dự án.
Hướng dẫn git worktree từ cơ bản đến thực tế: tạo nhiều working tree, làm feature và hotfix song song, review PR, quản lý list/remove/prune/lock/repair và tránh lỗi phổ biến.