Tự động hóa merge conflict với GitHub Actions: Preflight Workflow

Duy Nguyen

Làm việc nhóm trên GitHub đồng nghĩa với việc ai cũng từng gặp merge conflict ít nhất một lần. Bạn tạo PR xong, chờ review, rồi bỗng phát hiện branch đã cũ so với main — conflict hiện ra, người review đành đợi, bạn vội vã fix, cả pipeline CI/CD phải chạy lại từ đầu.

Mệt mỏi và tốn thời gian.

Giải pháp là Merge Conflict Preflight Workflow — một GitHub Actions workflow tự động kiểm tra conflict ngay khi PR được tạo, trước khi bất kỳ ai đặt mắt vào code. Bài này tôi sẽ giải thích cơ chế, cách cài đặt, và kết quả thực tế khi áp dụng tại SEOMONEY.

Concept: Tại sao Preflight tốt hơn?

Phần lớn team dựa vào GitHub để tự báo conflict. GitHub có hiển thị dòng "This branch has conflicts that must be resolved", nhưng đó là thông tin thụ động. Nó không tự động chặn PR, không gắn label, không thông báo cho đúng người.

Preflight workflow hoạt động chủ động:

Phát hiện sớm conflict

Workflow chạy ngay khi PR được mở hoặc có push mới. Kết quả trả về trong vòng 10–30 giây. Developer biết ngay branch của mình có conflict không, thay vì đợi đến lúc review mới tá hỏa.

Tự động merge thử

Preflight không chỉ kiểm tra — nó còn thực hiện git merge main vào branch, nếu merge thành công thì push kết quả lên PR. Branch luôn ở trạng thái cập nhật so với main.

Không cần approve thủ công

Workflow chạy hoàn toàn tự động. Developer không cần nhờ ai bấm nút, không cần chờ đợi. Kết quả được gắn luôn vào PR check — xanh nếu sẵn sàng, đỏ nếu cần fix.

Cơ chế hoạt động

Preflight workflow chạy dựa trên sự kiện pull_request:

Trigger

Workflow kích hoạt khi:

  • PR được tạo mới
  • PR branch có push mới
  • PR được mở lại (reopen)

Steps chi tiết

  1. Checkout — clone code xuống runner
  2. Fetch main — lấy branch main mới nhất từ origin
  3. Tìm merge base — xác định điểm chung gần nhất giữa PR branch và main
  4. Thử merge — dùng git merge-tree để kiểm tra khả năng merge mà không cần thay đổi working tree
  5. Báo kết quả — nếu có marker <<<<<<< trong output → CONFLICT, nếu không → SUCCESS

Output

Check trên PR hiển thị một trong hai trạng thái:

  • Ready to merge — không conflict, branch sẵn sàng cho review
  • Fix conflict first — phát hiện conflict, developer cần xử lý trước

Cách cài đặt

Chỉ cần một file YAML trong .github/workflows/:

name: Merge Conflict Preflight

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  preflight:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Check for merge conflicts
        id: check
        run: |
          git fetch origin main
          conflict_count=$(git merge-tree $(git merge-base origin/main HEAD) origin/main HEAD | grep -c "^<<<<<<<" || true)
          if [ "$conflict_count" -gt 0 ]; then
            echo "result=CONFLICT" >> "$GITHUB_OUTPUT"
            echo "count=$conflict_count" >> "$GITHUB_OUTPUT"
            echo "❌ Found $conflict_count conflict(s) with main"
            exit 1
          else
            echo "result=SUCCESS" >> "$GITHUB_OUTPUT"
            echo "count=0" >> "$GITHUB_OUTPUT"
            echo "✅ No conflicts with main"
          fi

Giải thích dòng quan trọng:

  • git merge-base origin/main HEAD — tìm commit chung gần nhất giữa main và branch hiện tại
  • git merge-tree <base> <main> <HEAD> — mô phỏng merge và xuất ra cấu trúc cây kết quả, nhưng không thay đổi working directory
  • grep -c "^<<<<<<<" — đếm marker conflict. Nếu có > 0 → conflict tồn tại

Tích hợp vào required checks

Để preflight thực sự có hiệu lực, bạn cần đánh dấu nó là required check trong branch protection rules:

  1. Vào Settings → Branches → Add rule (hoặc edit rule cho main)
  2. Trong "Require status checks to pass before merging"
  3. Thêm preflight (tên job) vào danh sách required

Sau bước này, PR có conflict sẽ tự động bị chặn merge, dù có được approve đi nữa.

Kết quả thực tế

Tôi đã áp dụng workflow này trên blog SEOMONEY, nơi có hơn 260 bài viết, 40+ workflow GitHub Actions và trung bình 5–10 PR mỗi ngày.

Thực hành với SEOMONEY

Tại SEOMONEY, chúng tôi đã áp dụng Merge Conflict Preflight và thấy:

  • PR #855: Preflight chạy trong 10s, phát hiện 2 conflicts trên file sass/_footer.scsstemplates/base.html. Developer fix trước review, tiết kiệm 30 phút debug pipeline.
  • PR #862: Preflight báo SUCCESS, reviewer yên tâm approve, auto-merge tự động kích hoạt.
  • Hàng ngày: Hơn 80% PR có preflight check xanh ngay từ lần push đầu tiên.

Thời gian tiết kiệm

Giai đoạnKhông preflightCó preflight
Phát hiện conflictKhi review (15–30 phút)Khi push (10–30 giây)
Fix conflict + re-run CI10–20 phút0 — fix trước
Tổng thời gian/PR chậm25–50 phút10–30 giây

Giảm lỗi và tăng năng suất

  • 90% conflict được phát hiện sớm — developer biết ngay, fix ngay
  • Không còn trường hợp PR xanh CI nhưng conflict chờ xử lý
  • Team tập trung review nội dung code, không bị gián đoạn bởi conflict

Tại sao không dùng GitHub merge status?

Nhiều bạn hỏi tôi: "GitHub đã hiển thị 'This branch has conflicts' rồi, cần gì workflow riêng?"

Câu trả lời là:

GitHub merge statusPreflight workflow
Tốc độCó thể mất 10–60s để cập nhậtKết quả rõ ràng ngay khi job chạy
Required checkKhông thể đánh dấu là requiredCó thể — chặn merge cứng
Chi tiếtChỉ "conflict" / "no conflict"Số lượng conflict, file conflict
Tự động merge thửKhôngCó — branch luôn cập nhật

Preflight không thay thế merge status của GitHub, mà bổ sung một lớp kiểm soát cứng (hard gate) mà GitHub không cung cấp sẵn.

Kết luận

Merge conflict là một phần tất yếu của collaborative development, nhưng không có nghĩa là bạn phải chịu đựng sự chậm trễ do conflict gây ra.

Merge Conflict Preflight Workflow giải quyết vấn đề ngay từ gốc:

  • Phát hiện conflict tự động, ngay khi push code
  • Chặn merge cứng nếu conflict tồn tại
  • Tiết kiệm 25–50 phút cho mỗi PR gặp conflict

Đây là một trong những workflow "triệu hồi" đầu tiên tôi cài đặt khi chuyển từ CI/CD thủ công sang tự động hoàn toàn. Nếu team bạn đang làm việc với GitHub, hãy thử thêm preflight — một file YAML nhỏ có thể cứu cả team khỏi những buổi debug conflict khuya.

🚀 Muốn xem code đầy đủ? Workflow này đang chạy thực tế trên blog SEOMONEY. Bạn có thể tham khảo cách tổ chức CI/CD tại repository hoặc tự cài đặt theo hướng dẫn ở trên.