Trong thế giới lập trình với Git, bạn sẽ thường xuyên phải đối mặt với tình huống: "Tôi chỉ cần một thay đổi nhỏ từ nhánh feature-X
nhưng không muốn gộp (merge) cả nhánh đó vào nhánh main
ngay bây giờ." Hoặc: "Có một bản vá lỗi (hotfix) quan trọng ở nhánh develop
mà tôi cần áp dụng ngay cho nhánh release
."
Nếu bạn từng bối rối trong những trường hợp này, thì git cherry-pick
chính là "vị cứu tinh" bạn đang tìm kiếm. Đây là một trong những công cụ mạnh mẽ và chính xác nhất trong kho vũ khí của Git, cho phép bạn "hái" từng commit riêng lẻ như những quả cherry chín mọng từ một nhánh và đắp nó vào một nhánh khác.
Hãy cùng khám phá sâu hơn về công cụ tuyệt vời này nhé!
Git cherry-pick là gì? Nhặt "cherry ngọt" từ branch khác về 🍒
Nói một cách đơn giản, git cherry-pick
là lệnh dùng để áp dụng một commit cụ thể từ một nhánh bất kỳ lên đầu của nhánh hiện tại (HEAD).
Hãy tưởng tượng mỗi nhánh (branch) là một cây cherry với nhiều quả (commit). Thay vì phải chặt cả cây (git merge
) hoặc bứng cả cây sang trồng ở một gốc mới (git rebase
), cherry-pick
cho phép bạn đi đến một cây khác, chọn lấy đúng một hoặc vài quả cherry ngon nhất mà bạn muốn, rồi mang về gắn lên cây của mình.
Kết quả là bạn sẽ có một commit mới trên nhánh của mình. Commit mới này có cùng nội dung thay đổi (diff) và cùng thông điệp (commit message) với commit gốc, nhưng nó sẽ có một mã hash hoàn toàn mới vì nó có một commit cha khác và được tạo ở một thời điểm khác.
Khi nào nên và không nên "hái cherry"?
git cherry-pick
cực kỳ hữu dụng, nhưng dùng sai cách có thể gây ra những rắc rối không đáng có. Hiểu rõ khi nào nên và không nên dùng là chìa khóa để trở thành một cao thủ Git.
🎯 Nên dùng khi:
- Vá lỗi khẩn cấp (Hotfix): Đây là trường hợp phổ biến nhất. Một bug nghiêm trọng được sửa ở nhánh
develop
hoặc một nhánh feature. Bạn cần áp dụng bản vá này ngay lập tức cho nhánhmain
hoặcrelease
mà không cần chờ toàn bộ tính năng được gộp vào. - Lấy một tính năng nhỏ lẻ: Nhánh
feature-A
có một commit refactor code rất hữu ích, nhưng toàn bộ tính năng A chưa sẵn sàng. Bạn có thểcherry-pick
commit refactor đó sang nhánhfeature-B
của mình để tiếp tục công việc. - Khôi phục thay đổi đã mất: Bạn vô tình
git reset
và làm mất một vài commit quan trọng trên nhánh của mình, nhưng may mắn là những commit đó vẫn tồn tại ở một nhánh khác trên remote. Bạn có thể dùngcherry-pick
để lấy lại chúng. - Hợp tác chia sẻ công việc: Một đồng nghiệp đã hoàn thành một commit giải quyết một phần nhỏ trong task của bạn. Thay vì merge cả nhánh của họ, bạn có thể
cherry-pick
commit đó để tích hợp vào luồng công việc của mình.
⚠️ Không nên dùng khi:
- Di chuyển một lượng lớn commit: Nếu bạn thấy mình phải
cherry-pick
cả một chuỗi dài các commit từ nhánh này sang nhánh khác, rất có thể bạn đang làm sai. Trong trường hợp này, hãy cân nhắc sử dụnggit rebase
hoặcgit merge
. - Làm việc trên các nhánh công khai (public branches):
cherry-pick
tạo ra các commit trùng lặp về nội dung nhưng khác hash. Nếu bạncherry-pick
một commit từ nhánhdevelop
sangmain
, sau này khi mergedevelop
vàomain
, Git có thể bị bối rối vì thấy một thay đổi đã tồn tại. Việc này có thể tránh được nhưng nó làm phức tạp hóa lịch sử commit.
Hướng dẫn "hái cherry" đúng cách
Cú pháp cơ bản rất đơn giản, nhưng sức mạnh của cherry-pick
nằm ở các tùy chọn đi kèm.
1. Cách hái một quả (Single commit)
Trước hết, bạn cần xác định "quả cherry" mình muốn hái. Hãy dùng git log
trên nhánh nguồn để lấy mã hash của commit đó.
# Đứng ở nhánh nguồn (ví dụ: develop) để xem lịch sử
git log --oneline
# Kết quả sẽ giống như này:
# fdb321e Fix: Correct user authentication flow
# a412cbe Feat: Add new user profile page
# c876dab Style: Update button styles
Giả sử bạn muốn lấy commit fdb321e
để áp dụng vào nhánh main
.
# 1. Chuyển sang nhánh bạn muốn áp dụng commit vào
git switch main
# 2. Thực hiện cherry-pick với mã hash
git cherry-pick fdb321e
Xong! Commit fdb321e
giờ đã có mặt trên nhánh main
với một mã hash mới.
2. Cách hái cả chùm (Multiple commits)
Bạn có thể hái nhiều quả cherry cùng lúc bằng cách liệt kê các mã hash.
# Hái 2 commit cụ thể
git cherry-pick fdb321e a412cbe
Hoặc hái cả một khoảng commit (lưu ý: commitA
sẽ không được bao gồm).
# Hái tất cả commit từ sau commitA đến và bao gồm commitB
git cherry-pick commitA..commitB
3. Các tùy chọn bổ sung
--no-commit
hoặc-n
: Lệnh này sẽ áp dụng các thay đổi của commit vào working directory của bạn nhưng không tự động tạo commit mới. Điều này cực kỳ hữu ích khi bạn muốn gộp các thay đổi từ nhiều commit thành một commit duy nhất, hoặc muốn kiểm tra lại code trước khi commit.git cherry-pick -n <commit-hash> # ...kiểm tra, sửa đổi code... git add . git commit -m "Thông điệp commit mới của tôi"
--edit
hoặc-e
: Trước khicherry-pick
hoàn tất, Git sẽ mở trình soạn thảo văn bản cho phép bạn chỉnh sửa lại thông điệp commit. Rất hữu ích để thêm ngữ cảnh về lý do tại sao commit này lại được "hái" sang nhánh hiện tại.
Xử lý "cherry dập": Giải quyết Conflict 💥
Không phải lúc nào việc "hái cherry" cũng suôn sẻ. Nếu commit bạn đang cố gắng áp dụng thay đổi cùng một đoạn code đã được thay đổi trên nhánh hiện tại của bạn, một cuộc xung đột (conflict) sẽ xảy ra.
Đừng hoảng sợ! Git sẽ tạm dừng quá trình cherry-pick
và cho bạn biết file nào đang bị conflict. Quy trình giải quyết rất giống với khi merge hoặc rebase:
- Mở các file bị xung đột. Bạn sẽ thấy các dấu
<<<<<<<
,=======
,>>>>>>>
của Git. - Chỉnh sửa file, xóa các dấu của Git và giữ lại phần code cuối cùng mà bạn muốn.
- Sau khi đã giải quyết tất cả các xung đột, hãy báo cho Git biết:
git add <tên-file-đã-sửa>
- Tiếp tục quá trình
cherry-pick
:git cherry-pick --continue
Nếu bạn cảm thấy bối rối và muốn hủy bỏ mọi thứ, chỉ cần chạy lệnh:
git cherry-pick --abort
Mọi thứ sẽ trở về trạng thái như trước khi bạn bắt đầu cherry-pick
.
So sánh cherry-pick với Merge và Rebase
Để hiểu rõ hơn giá trị của cherry-pick
, hãy đặt nó cạnh hai người anh em merge
và rebase
.
Tiêu chí | git cherry-pick | git merge | git rebase |
---|---|---|---|
Mục đích | Áp dụng một vài commit riêng lẻ. | Gộp toàn bộ lịch sử của một nhánh vào nhánh khác. | Viết lại lịch sử bằng cách di chuyển một chuỗi commit sang một điểm gốc mới. |
Lịch sử commit | Tạo ra commit mới, có thể gây trùng lặp nội dung. | Tạo một "merge commit" để kết nối hai lịch sử. Lịch sử phân nhánh rõ ràng. | Tạo ra lịch sử commit thẳng, sạch sẽ, nhưng làm thay đổi hash của các commit. |
Trường hợp dùng | Hotfix, lấy tính năng nhỏ. | Tích hợp một nhánh tính năng đã hoàn thành vào nhánh chính. | Dọn dẹp lịch sử của nhánh cá nhân trước khi merge. |
Lời kết: Nắm rõ cherry-pick để làm việc linh hoạt hơn
git cherry-pick
là một công cụ cực kỳ sắc bén và chính xác. Nó cho phép bạn quản lý mã nguồn một cách linh hoạt, giải quyết các vấn đề cấp bách mà không làm xáo trộn luồng phát triển chính. Giống như bất kỳ công cụ mạnh nào, hãy sử dụng nó một cách có ý thức, giao tiếp rõ ràng với đội nhóm của bạn và bạn sẽ thấy công việc của mình trở nên dễ dàng hơn rất nhiều.
Chúc bạn "hái" được thật nhiều "cherry ngọt" và code vui vẻ! 🚀