Batch fix merge conflict khi merge hàng loạt PR
Mục lục
Chạy lệnh merge tất cả Pull Request đang mở, mình thấy 4 trong 6 PR báo đỏ "conflict". Cảm giác đầu tiên là ngán: hình dung phải mở từng file, đọc từng dòng <<<<<<<, đoán bên nào đúng. Nhưng sau vài lần va, mình nhận ra batch fix merge conflict kiểu này hầu hết không phải xung đột logic — nó là "merge race" ở file tự sinh. Phân loại đúng thì fix cả loạt nhanh hơn hẳn. Bài này mình chia sẻ lại cách làm thật, từ lúc bấm lệnh tới lúc push sạch.
Bối cảnh: một lệnh merge cả loạt PR
Mình gom thao tác merge hàng loạt vào một shortcut nội bộ (đặt tên prm). Ý tưởng đơn giản: liệt kê mọi PR đang mở, cái nào CI xanh thì squash-merge lên main, rồi để deploy tự chạy. Đây là kiểu workflow "gom một lượt" quen thuộc với ai làm blog/tool nhiều nhánh song song.
Vấn đề là khi có nhiều PR mở cùng lúc, mỗi lần một PR merge vào main sẽ làm các PR còn lại bị lệch nền (stale base). Cái này khớp với những gì mình từng ghi lại ở bài giải quyết merge conflict tự động trong CI/CD — càng nhiều PR chờ, xác suất đụng nhau càng cao.
Vì sao PR "sạch" bỗng conflict
Đây là hiểu lầm phổ biến nhất, nên mình nói kỹ. CI xanh chỉ chứng minh một điều: nhánh đó nhất quán với chính nó tại thời điểm chạy. Nó không chứng minh nhánh còn merge sạch với main ở hiện tại.
Trong lúc PR nằm chờ, main vẫn chạy tiếp: các hook/cron sinh lại file dữ liệu, PR khác merge trước và đổi cùng vùng file. Kết quả là nhánh của bạn dựa trên một bản main cũ. Đến lúc merge, git so bản nền cũ với main mới → phát sinh conflict. Bản chất là merge race, không phải code sai.
Điểm mình muốn nhấn: một PR chuyển sang trạng thái conflict sau khi đã QA xanh gần như luôn là dấu hiệu nền cũ, chứ không phải bug mới. Cách nghĩ này giúp bớt hoảng và đi thẳng vào việc phân loại. Bài kiểm tra trạng thái PR sau khi merge mình từng viết cũng xoay quanh thói quen này: đọc trạng thái trước, sửa sau.
Bước 1: Phân loại conflict trước khi đụng tay
Trước khi resolve bất cứ gì, mình luôn hỏi: file nào conflict, và file đó từ đâu ra? Kinh nghiệm cho thấy conflict rơi vào ba nhóm rất khác nhau:
- File tự sinh (generated): các file dữ liệu JSON do script/CI build lại (index bài viết, references, scores, report…). Đặc điểm: diff chỉ khác timestamp hoặc vài entry, và nội dung thật của PR không hề đụng.
- File nội dung (content): bài viết markdown do người viết. Đây mới là "tài sản" thật, cần giữ.
- File template / mã nguồn: HTML template, CSS/SCSS, script. Nhóm này nguy hiểm nhất vì lấy mù một bên dễ làm vỡ build.
Trong phiên vừa rồi của mình, cả bốn PR conflict thì hầu hết chỉ đụng đúng một file index tự sinh. config, template, style đều tự merge sạch (git ghép được các hunk không chồng lấn). Nghĩa là "4 PR đỏ" trông đáng sợ nhưng thực chất là cùng một loại race nhẹ.
Batch fix merge conflict: chiến lược resolve theo từng nhóm
Sau khi phân loại, mỗi nhóm có một cách xử lý cố định. Mình dán bảng này ngay đầu việc để khỏi phân vân:
| Nhóm file | Chiến lược | Lý do |
|---|---|---|
| Data JSON tự sinh (index, references, scores) | Lấy bản main rồi để CI build lại | Là artifact, không phải nguồn sự thật; regenerate sẽ khớp state mới |
| Bài viết markdown | Giữ bản PR (trừ khi bài đã có sẵn trên main) | Nội dung là tài sản thật của nhánh |
| Template / SCSS / mã nguồn | Resolve từng vùng, không lấy mù | Lấy một bên dễ mất hunk của phía kia hoặc vỡ cú pháp |
Hai cái bẫy mình luôn kiểm tra thêm, vì chúng lọt qua cả khi không còn conflict marker:
- Link nội bộ trỏ tới bài chưa tồn tại: nếu bản PR thêm liên kết tới một bài mà nhánh khác chưa publish, build sẽ đỏ. Cách phòng nằm ở bài git merge và xử lý conflict — verify đích của mọi link trước khi tin.
- Cú pháp template sai sau khi ghép: một dòng template ghép nhầm là đủ kéo sập build của mọi PR khác, đúng như case study một dòng Tera parse lỗi kéo theo 5 PR fail. Bài học: conflict-free không đồng nghĩa build-safe.
Bước 3: Quy trình thực tế mình làm
Vì máy local thường đang mở dở một nhánh khác, mình không muốn checkout qua lại làm bẩn cây làm việc. Cách gọn nhất là dùng git worktree (tài liệu chính thức) — tạo một thư mục làm việc riêng cho từng nhánh, xử lý xong thì xoá.
Các bước mình lặp cho từng PR conflict:
git fetch origin mainđể chắc chắn đang so vớimainmới nhất.- Tạo worktree riêng cho nhánh PR (tránh đụng cây làm việc đang mở).
git merge origin/mainvào nhánh — để git tự ghép phần ghép được.- Với file tự sinh còn conflict: lấy bản
main(git checkout --theirs <file>),git add. - Với template/nội dung nếu có: resolve từng vùng, giữ đúng hai phía.
- Commit merge, rồi push lại lên đúng nhánh PR.
Điểm hay của worktree: mình mở song song nhiều nhánh mà không sợ lẫn. Nếu một nhánh đang bị session khác giữ worktree, mình dùng worktree ở chế độ detached tại commit remote rồi push thẳng lên ref của nhánh — không cần chiếm quyền checkout của nhánh đó.
Bước 4: Verify trước khi push (đừng bỏ qua)
Đây là phần mình từng lười và trả giá. Một PR không còn marker vẫn có thể vỡ build. Checklist tối thiểu trước khi push:
- Quét sạch marker: không còn dòng nào bắt đầu bằng
<<<<<<<,>>>>>>>hay=======. - Chạy checker link nội bộ — bắt link trỏ tới bài/asset không tồn tại.
- Chạy QA scoped cho phạm vi đã đụng (không cần build toàn bộ nếu chỉ chạm một phần).
- Để CI lo phần build đầy đủ — mình không build nặng ở local, coi CI là nguồn xác nhận chính thức.
Về việc "vì sao không build local", mình theo hướng giảm tải máy và tin CI, giống tinh thần bài checklist theo dõi deploy sau khi merge tới production: push xong thì theo dõi trạng thái, không ngồi build tay từng lần.
Bài học rút ra
Sau vài phiên "merge cả loạt", mình gói lại mấy điều tự nhắc:
- Đừng sợ màu đỏ. Bốn PR conflict phần lớn là cùng một race ở file tự sinh — phân loại xong là thấy nhẹ.
- Đừng tin nền cũ. PR chuyển
conflictsau khi QA xanh gần như luôn là stale base, không phải bug. - Đừng lấy mù một bên cho template và nội dung — chỉ làm vậy với artifact tự sinh.
- Đừng bỏ verify. Marker sạch chưa chắc build sạch; luôn quét link nội bộ và cú pháp template.
Nói ngắn gọn: batch fix merge conflict không phải trò đọc từng dòng, mà là trò phân loại rồi áp chiến lược. Khi bạn nhìn conflict qua lăng kính "file này từ đâu ra", tốc độ xử lý cả loạt PR tăng lên rõ rệt mà rủi ro vẫn thấp.
Đọc tiếp
Nếu bạn đang xây một blog/tool nhiều nhánh song song và hay gặp cảnh này, mình gợi ý đọc thêm hai hướng: tự động hoá bớt phần lặp trong giải quyết merge conflict tự động CI/CD, và giữ thói quen kiểm trạng thái ở kiểm tra trạng thái PR sau khi merge. Bạn cũng có thể xem thêm các bài cùng chuyên mục tại chuyên mục Công nghệ hoặc lướt tất cả bài viết để tìm chủ đề Git/CI/CD khác.
Liên kết bên ngoài được sử dụng trong bài viết
Bài viết hiện chưa có nguồn ngoài được khai báo riêng.
Liên kết nội bộ liên quan
Bản quyền & Ghi nguồn
Bài viết được biên tập và tổng hợp bởi Duy Nguyen/SEOMONEY. Nội dung chỉ mang tính tham khảo, không thay thế nguồn chính thức hoặc tư vấn chuyên môn.
Bình luận
Đang tải bình luận…
Chưa có bình luận nào. Hãy là người đầu tiên chia sẻ ý kiến.
Đăng nhập để tham gia thảo luận.
Đăng nhập bằng Google để bình luậnChỉ dùng để bình luận. Không truy cập trình soạn thảo/CMS.
Không kết nối được máy chủ. Vui lòng thử lại.