Làm chủ Git Cherry-pick: Cách ‘nhặt’ Commit chuẩn xác và mẹo xử lý Conflict

Git tutorial - IT technology blog
Git tutorial - IT technology blog

Khi nào bạn cần ‘bốc’ một Commit thay vì Merge cả Branch?

Giả sử bạn đang code dở tính năng trên branch feature-xyz suốt cả tuần. Bất ngờ, khách hàng báo một lỗi nghiêm trọng trên Production cần fix ngay lập tức. Bạn nhận ra mình đã vô tình sửa đúng lỗi đó trong một commit lẻ loi nằm giữa đống code chưa hoàn thiện của nhánh feature.

Lúc này, việc merge cả nhánh vào main là không thể vì code tính năng mới chưa test xong. Nếu cố tình đẩy lên, hệ thống rất dễ ‘sập’. Việc copy-paste code thủ công cũng tiềm ẩn nhiều rủi ro sai sót. Đây chính là thời điểm Git Cherry-pick trở thành vũ khí đắc lực. Lệnh này cho phép bạn nhặt chính xác commit fix bug đó và dán vào nhánh main một cách gọn gàng.

Trong thực tế, khi làm việc với các dự án lớn có từ 10-20 nhân sự, Cherry-pick thường xuyên được dùng để ‘backport’ (đưa các bản vá từ phiên bản mới về phiên bản cũ). Nó giúp bạn kiểm soát dòng chảy của code mà không làm xáo trộn lịch sử commit của cả team.

So sánh Cherry-pick với Merge và Rebase

Để dùng đúng lúc, bạn cần phân biệt rõ Cherry-pick với hai người anh em là Merge và Rebase.

  • Git Merge: Gộp toàn bộ lịch sử của nhánh này vào nhánh kia. Cách này giống như bạn đổ cả một xô nước vào chậu lớn, đôi khi mang theo cả những thứ không mong muốn.
  • Git Rebase: Viết lại lịch sử bằng cách đặt các commit của nhánh này lên trên đầu nhánh kia. Nó giúp lịch sử Git thẳng tắp nhưng cực kỳ rủi ro nếu bạn đã push code lên server.
  • Git Cherry-pick: Chỉ chọn đúng một hoặc vài commit cụ thể. Nó giống như việc bạn nhặt một viên gạch ưng ý trong đống đổ nát để mang về xây nhà mình.

Bảng so sánh nhanh:

Tính năng Merge Rebase Cherry-pick
Phạm vi Toàn bộ branch Toàn bộ branch Commit đơn lẻ
Lịch sử Git Tạo merge commit Tuyến tính, sạch sẽ Tạo commit mới (hash mới)
Độ rủi ro Thấp Rất cao Trung bình

Tại sao bạn nên (và không nên) dùng Cherry-pick?

Ưu điểm:

  • Kiểm soát tuyệt đối: Bạn chỉ lấy những gì cần thiết, loại bỏ hoàn toàn code rác.
  • Ứng cứu Production: Giúp triển khai Hotfix nhanh chóng mà không cần chờ đợi các tính năng khác hoàn thiện.
  • Đa phiên bản: Khi dự án chạy song song v1.0 và v2.0, bạn có thể đưa bản vá vào cả hai bản mà không cần code lại hai lần.

Hạn chế:

  • Gây trùng lặp: Cherry-pick tạo ra mã Hash mới. Nếu lạm dụng, git log sẽ đầy rẫy các commit có nội dung giống hệt nhau nhưng khác mã định danh.
  • Dễ xung đột: Nếu commit bạn nhặt phụ thuộc vào một đoạn code cũ mà bạn chưa đưa sang, conflict là điều chắc chắn.

Cách triển khai Git Cherry-pick trong 3 bước

Đầu tiên, hãy tìm mã Hash của commit bạn muốn lấy bằng lệnh:

git log --oneline

Giả sử mã commit cần lấy là a1b2c3d.

1. Cherry-pick một commit

Chuyển sang nhánh đích (ví dụ nhánh main) và thực hiện lệnh:

git checkout main
git cherry-pick a1b2c3d

2. Nhặt nhiều commit cùng lúc

Để nhặt danh sách các commit rời rạc, bạn dùng cú pháp:

git cherry-pick hash1 hash2 hash3

Nếu muốn lấy một dải commit từ A đến B (không bao gồm A), hãy dùng A..B. Để lấy cả commit A, hãy dùng A^..B.

3. Mẹo giữ dấu vết nguồn gốc

Kinh nghiệm xương máu là luôn dùng thêm option -x. Nó sẽ tự động ghi chú commit này được ‘nhặt’ từ đâu vào message.

git cherry-pick -x a1b2c3d

Điều này cực kỳ hữu ích khi sau này bạn cần truy vết lỗi hoặc debug hệ thống.

Xử lý Conflict: Đừng hoảng loạn!

Conflict xảy ra khi dòng code bạn nhặt về đã bị thay đổi ở nhánh đích. Khi thấy thông báo lỗi, hãy bình tĩnh xử lý theo quy trình:

  1. Mở file bị lỗi, tìm các ký hiệu <<<<<<<======= để sửa thủ công.
  2. Lưu file sau khi đã chọn lọc code đúng.
  3. Chạy lệnh git add <tên_file> để đánh dấu đã xử lý xong.
  4. Tiếp tục quá trình bằng lệnh: git cherry-pick --continue.

Nếu thấy quá phức tạp và muốn quay lại trạng thái cũ, bạn chỉ cần gõ git cherry-pick --abort.

Câu chuyện thực chiến: Khi Cherry-pick cứu nguy dự án

Tôi từng làm một dự án Outsourcing với quy trình Git Flow cực kỳ khắt khe. Một đồng nghiệp vô tình commit thẳng code tính năng mới vào nhánh develop, trong khi nhánh này chuẩn bị đóng gói để demo cho khách hàng vào sáng hôm sau. Toàn bộ code tính năng đó vẫn còn dang dở và có thể gây crash ứng dụng.

Thay vì ngồi xóa code tay cho hơn 15 file bị ảnh hưởng, tôi đã xử lý trong 5 phút:

  1. Lấy mã commit sai đó sang nhánh feature đúng bằng Cherry-pick.
  2. Quay lại develop và dùng git revert để đảo ngược thay đổi.

Nhờ vậy, buổi demo diễn ra hoàn hảo. Code tính năng vẫn được bảo toàn để tiếp tục phát triển ở nhánh riêng. Nếu không dùng Cherry-pick, có lẽ cả team đã phải thức trắng đêm để dọn dẹp đống hỗn độn đó.

Lời khuyên cuối:

  • Chỉ Cherry-pick khi thực sự cần thiết. Đừng biến nó thành thói quen thay thế cho Merge.
  • Nếu phải nhặt quá 10 commit cùng lúc, hãy xem lại workflow của team. Có thể bạn đang đi sai hướng.
  • Luôn chạy Unit Test ngay sau khi nhặt commit để đảm bảo mọi thứ vẫn vận hành trơn tru.

Share: