Cú pháp của Git Cherry-Pick
Hiểu cú pháp git cherry-pick là chìa khóa để dùng lệnh này hiệu quả. Không chỉ là chọn commit, mà còn là áp dụng chúng một cách chính xác để đạt kết quả mong muốn.
Cú pháp cơ bản để cherry-pick một commit đơn lẻ là:
git cherry-pick <commit-hash>
git cherry-pick: Lệnh khởi động thao tác.<commit-hash>: Định danh duy nhất (băm SHA-1) của commit bạn muốn cherry-pick. Bạn có thể tìm hash này bằng cách chạygit logđể liệt kê lịch sử commit.
Khi thực thi lệnh trên, Git áp dụng các thay đổi từ commit được chỉ định vào nhánh hiện tại, tạo một commit mới với cùng thay đổi nhưng có hash khác.
Lưu ý quan trọng: lệnh chỉ chuyển bản thân commit, không chuyển ngữ cảnh hoặc lịch sử cha từ nhánh gốc.
Mới làm quen với Git và GitHub? Bắt đầu với kiểm soát phiên bản trong bài hướng dẫn thân thiện với người mới GitHub và Git.
Cách dùng Git Cherry-Pick: Ví dụ từng bước
Giờ bạn đã hiểu cú pháp cơ bản của git cherry-pick, hãy xem lệnh này hoạt động thực tế ra sao.
Phần này cung cấp các ví dụ thực hành bao quát những kịch bản cơ bản và phức tạp hơn nơi cherry-pick hữu ích. Mỗi ví dụ minh họa cách áp dụng thay đổi từ một hoặc nhiều commit sang nhánh khác.
Ví dụ 1: Cherry-pick một commit đơn
Giả sử bạn đã sửa một lỗi trên nhánh tính năng và muốn áp dụng nó vào nhánh chính mà không merge toàn bộ nhánh tính năng.
- Trước tiên, tìm hash của commit bạn muốn cherry-pick bằng cách chạy:
git log
- Xác định hash của commit.
- Chuyển sang nhánh chính:
git checkout main
- Chạy lệnh cherry-pick (giả sử hash là
abc1234):
git cherry-pick abc1234
Khi bạn chạy lệnh này, Git sẽ áp dụng các thay đổi từ commit abc1234 vào nhánh hiện tại (trong trường hợp này là main). Git tạo một commit mới trên nhánh chính chứa cùng thay đổi như commit gốc nhưng có hash mới.
Ví dụ 2: Cherry-pick nhiều commit
Trong một số tình huống, bạn có thể cần áp dụng nhiều commit khác nhau từ một nhánh sang nhánh khác. Giả sử bạn có ba commit riêng biệt trong nhánh tính năng cần đưa vào nhánh chính.
- Tìm hash của mỗi commit bạn muốn cherry-pick bằng
git log:
git log
- Chuyển sang nhánh chính:
git checkout main
- Chạy lệnh cherry-pick, liệt kê các commit:
git cherry-pick abc1234 def5678 ghi7890
Ví dụ 3: Cherry-pick một dải commit
Giả sử bạn đã tạo một loạt commit trên nhánh tính năng và muốn áp dụng chúng lên nhánh chính trong một lần mà không cần chỉ ra từng commit. Làm thế nào?
- Dùng
git logđể xác định commit bắt đầu và kết thúc bạn muốn cherry-pick (ví dụ, từabc1234đếnghi7890). - Chuyển sang nhánh chính:
git checkout main
- Chạy lệnh cherry-pick với dải commit:
git cherry-pick abc1234...ghi7890
Ví dụ 4: Cherry-pick một commit từ nhánh remote
Đôi khi, một bản sửa quan trọng nằm ở nhánh remote và bạn muốn áp dụng nó vào nhánh local mà không merge toàn bộ nhánh. Cách làm như sau:
- Fetch các thay đổi mới nhất từ kho remote
git fetch origin
- Liệt kê các commit trong nhánh remote để tìm hash bạn cần:
git log origin/feature_branch --oneline
- Giả sử hash commit bạn cần là
abc1234. - Chuyển sang nhánh chính local của bạn:
git checkout main
- Cherry-pick commit từ nhánh remote:
git cherry-pick abc1234
Điều này cho phép bạn áp dụng một commit từ nhánh remote mà không merge toàn bộ nhánh.
Cần checkout một nhánh remote? Làm theo hướng dẫn từng bước về Git checkout cho các nhánh remote.
Ví dụ 5: Cherry-pick một commit và chỉnh sửa nó
Nếu bạn cherry-pick một commit nhưng cần chỉnh sửa nhẹ trước khi commit, bạn có thể dùng chế độ tương tác của Git. Cách làm:
- Chuyển sang nhánh đích:
git checkout main
- Cherry-pick commit nhưng dừng trước khi commit:
git cherry-pick -n abc1234
Cờ -n (hoặc --no-commit) áp dụng thay đổi nhưng không tạo commit.
- Chỉnh sửa các tệp khi cần.
- Stage và commit thủ công:
git add .
git commit -m "Modified cherry-picked commit from feature_branch"
Điều này hữu ích khi bạn cần tinh chỉnh một commit đã cherry-pick trước khi hoàn tất.
Xử lý xung đột khi Git Cherry-Pick
Xung đột là điều khó tránh khi cherry-pick commit giữa các nhánh, đặc biệt khi mã nguồn đã phân kỳ đáng kể.
Dù cherry-pick được thiết kế để áp dụng thay đổi một cách trơn tru, nó không phải lúc nào cũng tự động hòa giải được khác biệt. Trong những trường hợp này, xung đột phải được xử lý thủ công. Hiểu cách xung đột phát sinh và cách xử lý chúng là rất quan trọng để hoàn tất một thao tác cherry-pick.
Xung đột xảy ra như thế nào
Xung đột thường xảy ra khi các thay đổi từ commit được cherry-pick chồng lấn hoặc mâu thuẫn với các thay đổi đã có trong nhánh đích. Ví dụ:
- Cùng một dòng bị sửa ở cả hai nhánh: Nếu cùng một dòng mã được sửa ở cả nhánh nguồn và đích, Git sẽ không biết áp dụng phiên bản nào.
- Tệp bị xóa ở một nhánh nhưng sửa ở nhánh khác: Nếu một tệp bị xóa ở một nhánh nhưng được sửa trong commit được cherry-pick, Git sẽ không biết nên giữ lại hay áp dụng thay đổi.
- Thay đổi không liên quan nhưng cùng tệp: Ngay cả khi thay đổi có vẻ không liên quan, nếu chúng xảy ra trong cùng một tệp, Git có thể gắn cờ là xung đột tiềm ẩn.
Khi xảy ra xung đột, Git sẽ dừng thao tác cherry-pick, để lại thư mục làm việc của bạn ở trạng thái xung đột và cần được giải quyết trước khi tiếp tục.
Giải quyết xung đột
Khi phát sinh xung đột, Git sẽ hiển thị các tệp bị xung đột và bạn cần tự tay xử lý khác biệt. Cách làm như sau:
1. Kiểm tra các tệp xung đột: Chạy lệnh sau để xem tệp nào bị xung đột:
git status
Lệnh sẽ hiển thị danh sách các tệp có xung đột.
2. Giải quyết xung đột: Bạn có thể chỉnh sửa thủ công các tệp xung đột để giải quyết vấn đề. Xóa các dấu mốc xung đột (<<<<<<<, =======, >>>>>>>) và quyết định giữ thay đổi nào hoặc kết hợp chúng ra sao.
3. Dùng Git Mergetool (tùy chọn): Nếu xử lý thủ công quá khó, bạn có thể dùng công cụ hợp nhất để hỗ trợ trực quan hóa và giải quyết xung đột:
git mergetool
Tùy cấu hình, lệnh trên sẽ mở một công cụ hợp nhất trực quan, giúp việc xem xét và xử lý xung đột dễ dàng hơn.
4. Đánh dấu xung đột đã được giải quyết: Sau khi xử lý xung đột, đánh dấu các tệp là đã giải quyết bằng:
git add <conflicted-file>
5. Hoàn tất cherry-pick: Khi toàn bộ xung đột đã được giải quyết và các tệp đã được stage, hoàn tất cherry-pick bằng cách chạy:
git cherry-pick --continue
Nhiều IDE và công cụ hiện đại như Visual Studio Code và GitHub cung cấp sẵn tính năng xử lý xung đột. Giao diện web của GitHub cho phép bạn giải quyết xung đột trực tiếp trong pull request, giúp cộng tác trên kho dùng chung thuận tiện hơn mà không cần chuyển sang môi trường local.
Bỏ qua một commit sau khi xung đột
Đôi khi việc xử lý xung đột quá phức tạp, hoặc bạn nhận ra commit đó không cần thiết. Trong trường hợp này, bạn có thể bỏ qua hoàn toàn commit.
1. Bỏ qua commit đang gây xung đột: Nếu xung đột quá phức tạp và bạn không muốn áp dụng commit, có thể bỏ qua bằng cách chạy:
git cherry-pick --skip
Lệnh này sẽ bỏ commit đang xung đột và chuyển sang commit tiếp theo (nếu bạn cherry-pick nhiều commit).
2. Hủy toàn bộ cherry-pick: Nếu bạn muốn hủy thao tác cherry-pick hoàn toàn, hãy chạy:
git cherry-pick --abort
Lệnh này sẽ khôi phục thư mục làm việc về trạng thái trước khi bạn bắt đầu cherry-pick.
Muốn dọn dẹp lịch sử commit? Tìm hiểu cách gộp nhiều commit thành một qua hướng dẫn Git squash.
Thực tiễn tốt nhất khi dùng Git Cherry-Pick
Dùng sai cherry-pick có thể dẫn đến lịch sử phức tạp và gây nhầm lẫn trong kiểm soát phiên bản của dự án. Để tránh các cạm bẫy này, tuân thủ thực tiễn tốt nhất sẽ đảm bảo bạn dùng cherry-pick hiệu quả mà không tạo thêm phức tạp không cần thiết cho codebase.
Giữ phạm vi nhỏ và cụ thể
Cherry-pick hiệu quả nhất khi dùng cho các commit nhỏ, cụ thể nhằm giải quyết các tác vụ rõ ràng, như sửa lỗi hoặc cải tiến tính năng nhỏ.
Tránh cherry-pick các commit lớn, phức tạp gộp nhiều thay đổi, vì chúng có thể gây xung đột và làm khó quản lý codebase. Commit càng có mục tiêu rõ ràng thì càng dễ áp dụng mà không gây tác dụng phụ ngoài ý muốn.
Ghi chú lại các lần cherry-pick
Để duy trì lịch sử rõ ràng, luôn cung cấp bối cảnh phù hợp khi cherry-pick. Có thể thực hiện qua thông điệp commit chi tiết hoặc chú thích trong tài liệu.
Tóm lại, bạn cần giải thích vì sao cherry-pick là cần thiết. Điều này đặc biệt quan trọng khi cherry-pick giữa các nhánh tồn tại lâu hoặc trong môi trường cộng tác, vì nó giúp những người đóng góp sau này hiểu lý do thay đổi được áp dụng chọn lọc.
Rà soát lịch sử commit
Trước khi cherry-pick, hãy xem lịch sử commit của cả nhánh nguồn và nhánh đích. Bước này giúp xác định liệu commit bạn sắp cherry-pick có phụ thuộc vào thay đổi khác hay không. Thiếu phụ thuộc có thể dẫn đến chức năng không đầy đủ hoặc lỗi, vì vậy hãy đảm bảo cherry-pick không đưa vào những tính năng hay cập nhật “nửa vời”.
Tránh lạm dụng cherry-pick
Dù cherry-pick tiện lợi để áp dụng các thay đổi cụ thể, lạm dụng nó có thể dẫn đến lịch sử rời rạc với commit trùng lặp giữa các nhánh. Điều này khiến việc truy vết nguồn gốc thay đổi hoặc hiểu bối cảnh phát triển tổng thể trở nên khó khăn.
Luôn cân nhắc liệu merge hoặc rebase có phù hợp hơn trước khi cherry-pick. Hãy dùng cherry-pick một cách tiết chế và có chủ đích để tránh làm lộn xộn lịch sử commit.
Gặp rắc rối với các tệp không cần thiết trong Git? Tìm hiểu cách dùng .gitignore hiệu quả qua hướng dẫn Git ignore.
Khắc phục sự cố thường gặp với Git Cherry-Pick
Khắc phục sự cố khi dùng cherry-pick đòi hỏi hiểu rõ cơ chế nền tảng của Git. Trong phần này, tôi sẽ đề cập một số vấn đề phổ biến bạn có thể gặp khi cherry-pick và cách giải quyết.
Cherry-pick một commit không tồn tại
Đôi khi bạn cố cherry-pick một commit không thể truy cập từ nhánh hiện tại hoặc đã được merge rồi. Thường dẫn đến thông báo lỗi cho biết commit không thể tìm thấy hoặc không thể áp dụng.
1. Không tìm thấy commit: Điều này xảy ra khi hash commit bạn cố cherry-pick không tồn tại trong kho hoặc ngữ cảnh nhánh hiện tại của bạn. Hãy chắc chắn bạn tham chiếu đúng commit bằng cách kiểm tra lịch sử với git log trên nhánh có commit đó. Giải pháp:
- Kiểm tra lại hash commit để đảm bảo chính xác.
- Xác minh commit tồn tại trên một nhánh bạn có quyền truy cập.
- Nếu commit ở nhánh remote, hãy đảm bảo nhánh đã được fetch bằng
git fetch.
2. Commit đã được áp dụng: Nếu commit đã được merge hoặc cherry-pick vào nhánh đích, Git sẽ ngăn bạn tạo bản trùng lặp. Cơ chế này giữ lịch sử sạch và tránh thay đổi dư thừa. Giải pháp:
- Dùng
git logđể kiểm tra commit đã có trong nhánh đích hay chưa. - Nếu cần, hãy bỏ qua thao tác
cherry-pickvì thay đổi đã được áp dụng.
Cherry-pick sau khi rebase hoặc merge
Cherry-pick sau khi rebase hoặc merge có thể phức tạp do lịch sử nhánh bị thay đổi. Rebase viết lại lịch sử commit, còn merge kết hợp các nhánh, cả hai đều có thể ảnh hưởng đến khả năng áp dụng cherry-pick.
1. Xung đột do commit đã rebase: Sau rebase, lịch sử commit bị viết lại, có thể gây vấn đề nếu bạn cố cherry-pick các commit đã bị thay đổi trong quá trình rebase. Bạn có thể gặp xung đột khi cherry-pick cố áp dụng thay đổi không khớp với lịch sử mới. Giải pháp:
- Xem kỹ lịch sử commit sau rebase bằng
git logđể đảm bảo commit bạn định cherry-pick chưa được sửa đổi. - Giải quyết xung đột như trong quy trình
cherry-picktiêu chuẩn, dùnggit statusvà chỉnh sửa thủ công.
2. Commit trùng lặp sau merge: Việc merge có thể dẫn đến tình huống commit bạn muốn cherry-pick đã có trong lịch sử sau khi merge. Cherry-pick thêm lần nữa có thể tạo commit trùng lặp, làm lộn xộn lịch sử và khó theo dõi thay đổi. Giải pháp:
- Trước khi cherry-pick, kiểm tra lịch sử ở cả hai nhánh để xác nhận commit đã được merge hay chưa.
- Tránh cherry-pick cùng commit nếu nó đã có trong nhánh đích.
Cần hoàn tác thay đổi trong Git? Tìm hiểu khi nào nên dùng git reset so với git revert trong hướng dẫn Git reset và revert.
Kết luận
git cherry-pick là cách mạnh mẽ để áp dụng các commit cụ thể từ nhánh này sang nhánh khác mà không cần merge toàn bộ nhánh. Dù bạn đang chuyển một bản sửa lỗi, cập nhật tính năng, hay chỉ áp dụng chọn lọc thay đổi, nó giúp lịch sử Git của bạn sạch và tập trung.
Trong hướng dẫn này, tôi đã trình bày cách cherry-pick một hoặc nhiều commit, xử lý xung đột và tuân thủ thực tiễn tốt nhất để tránh các lỗi thường gặp. Bằng cách dùng cherry-pick một cách khôn ngoan, bạn có thể cải thiện quy trình làm việc đồng thời giữ cho kho của mình ngăn nắp.
Nếu bạn muốn nâng cao kỹ năng Git, hãy xem Foundations of Git để có nền tảng vững chắc. Bạn cũng có thể khám phá Introduction to GitHub Concepts hoặc học theo lộ trình có cấu trúc với GitHub Foundations skill track.
Giờ bạn đã biết cách cherry-pick như một chuyên gia, hãy thử áp dụng trong dự án tiếp theo của bạn!
Câu hỏi thường gặp
Điều gì xảy ra nếu tôi cherry-pick cùng một commit hai lần?
Nếu bạn cố cherry-pick một commit đã được áp dụng vào nhánh đích, Git có thể tạo một commit trùng lặp với hash mới. Để kiểm tra một commit đã được áp dụng hay chưa, dùng:
git log --oneline
Ngoài ra, nếu bạn chưa chắc chắn, hãy dùng:
git cherry-pick -n <commit-hash>
Lệnh này áp dụng thay đổi mà không commit, cho phép bạn xem lại trước khi hoàn tất.
Tôi có thể cherry-pick các commit từ một nhánh đã bị xóa không?
Có! Ngay cả khi nhánh đã bị xóa, các commit vẫn có thể tồn tại trong lịch sử của Git.
Dùng git reflog để tìm hash commit, sau đó cherry-pick như bình thường.
Tuy nhiên, nếu Git đã dọn rác (garbage collect) nhánh đó, các commit có thể bị mất.
Làm thế nào để tôi cherry-pick một commit từ kho khác?
Tôi có thể cherry-pick một commit có bao gồm xóa tệp không?
Có, cherry-pick giữ nguyên tất cả thay đổi trong commit, bao gồm cả việc xóa tệp. Nếu một commit xóa tệp, cherry-pick nó sẽ xóa tệp đó trong nhánh đích.
Làm sao để tôi hoàn tác một cherry-pick?
Sự khác nhau giữa git cherry-pick và git apply là gì?
git cherry-picksao chép một commit cụ thể và áp dụng nó lên nhánh đích đồng thời giữ metadata của commit.git applydùng để áp dụng các tệp vá (tạo bởigit diff) nhưng không tạo commit mới hoặc giữ lịch sử commit.
Làm sao cherry-pick một commit mà vẫn giữ nguyên tác giả gốc?
Tôi có thể cherry-pick nhiều commit không liên tiếp không?
Làm sao để tránh xung đột khi cherry-pick giữa các nhánh?
Khi nào tôi nên tránh dùng git cherry-pick?
Lạm dụng git cherry-pick có thể dẫn đến lịch sử commit lộn xộn với commit trùng lặp giữa các nhánh. Nên tránh khi:
- Thay đổi bao gồm nhiều commit phụ thuộc lẫn nhau —
mergehoặcrebasecó thể phù hợp hơn. - Bạn cần đồng bộ nhánh thường xuyên — rebase hoặc merge giúp lịch sử sạch hơn.
- Commit bao gồm tái cấu trúc lớn, vì cherry-pick chỉ di chuyển các thay đổi cụ thể chứ không mang bối cảnh rộng của nhánh.

Làm việc với các nhánh trong môi trường phát triển phần mềm cộng tác là điều cần thiết để tách biệt tính năng, sửa lỗi hoặc thử nghiệm. Tuy nhiên, đôi khi bạn cần lấy những thay đổi cụ thể từ một nhánh và áp dụng chúng sang nhánh khác mà không merge toàn bộ nhánh. Đây là lúc
git cherry-picktrở nên vô giá.Mục tiêu của hướng dẫn này là cung cấp một cẩm nang toàn diện về cách sử dụng
git cherry-pickhiệu quả. Bạn sẽ học cú pháp lệnh, hiểu cách xử lý xung đột và khám phá các thực tiễn tốt nhất cũng như những sai lầm thường gặp để tránh. Hãy bắt đầu nào!Git Cherry-Pick là gì?
Lệnh
git cherry-picklà một lệnh cơ bản của Git, cho phép nhà phát triển kiểm soát chi tiết mã nguồn của họ.Không giống như các thao tác Git khác như
mergehoặcrebase, vốn làm việc với toàn bộ nhánh,cherry-pickcho phép bạn lấy các commit cụ thể từ một nhánh và áp dụng chúng sang nhánh khác. Điều này mang lại độ chính xác, đặc biệt trong những tình huống bạn chỉ cần tích hợp một số thay đổi nhất định thay vì toàn bộ các chỉnh sửa trong một nhánh.Lệnh
git cherry-pickhoạt động bằng cách sao chép nội dung của các commit đã chọn và tạo commit mới trong nhánh đích, đồng thời duy trì tính toàn vẹn của lịch sử commit.Khi nào nên dùng git cherry-pick
Các trường hợp sử dụng
git cherry-pickbao gồm: