DEV Community

Deep Fix
Deep Fix

Posted on

How to Resolve Git Merge Conflicts in CI/CD Pipelines – Automated Fixes & Best Practices

Introduction

Merge conflicts are inevitable when multiple developers push changes to the same codebase, but they become a pipeline blocker in CI/CD environments. This article walks you through diagnosing, fixing, and automating conflict resolution so your builds stay green.


Why Conflicts Break CI/CD

  1. Stalled pipelines – A failed merge prevents downstream stages (tests, deployments) from running.
  2. Manual overhead – Engineers spend valuable time resolving conflicts locally instead of delivering features.
  3. Inconsistent state – Different branches may contain divergent logic, leading to flaky builds.

Step‑by‑Step: Detecting Conflicts in the Pipeline

1. Add a pre‑merge check (GitHub Actions example)

name: Pre‑merge Conflict Check
on: [pull_request]
jobs:
  conflict-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - name: Attempt merge with target
        run: |
          git fetch origin ${{ github.base_ref }}
          git checkout ${{ github.head_ref }}
          if ! git merge --no-commit --no-ff origin/${{ github.base_ref }}; then
            echo "::error::Merge conflict detected"
            exit 1
          fi
Enter fullscreen mode Exit fullscreen mode

If the job fails, GitHub will flag the PR with a conflict error, stopping the pipeline early.


2. Surface the conflict in the CI log

Make sure your CI provider prints the conflicting files:

git diff --name-only --diff-filter=U
Enter fullscreen mode Exit fullscreen mode

The output helps developers know exactly which files need attention.


Automated Resolution Strategies

A. Use a merge driver for specific file types

Create a .gitattributes entry:

*.json merge=ours
Enter fullscreen mode Exit fullscreen mode

Add a custom driver in .git/config:

[merge "ours"]
    name = Keep ours version during merge
    driver = true
Enter fullscreen mode Exit fullscreen mode

This tells Git to automatically keep the current branch version for JSON files, useful for generated configuration.


B. Apply a scripted fallback (example Bash script)

#!/usr/bin/env bash
# resolve-conflict.sh – run inside CI after a merge conflict is detected
set -euo pipefail

# 1. List conflicted files
conflicted=$(git diff --name-only --diff-filter=U)

# 2. Attempt automatic resolution using ours/theirs strategies
for file in $conflicted; do
  case "$file" in
    *.md) git checkout --theirs "$file" ;;   # Keep incoming docs
    *.go) git checkout --ours "$file"   ;;   # Keep current Go code
    *)    echo "Manual resolution required for $file"; exit 1 ;;
  esac
done

git add -u
git commit -m "ci: auto‑resolved merge conflicts"
Enter fullscreen mode Exit fullscreen mode

You can drop this script into your repo and invoke it from the pipeline. Download the pre‑configured script here.


Full CI Example (GitLab CI)

stages:
  - check
  - build
  - test

conflict_check:
  stage: check
  image: alpine/git
  script:
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
    - git checkout $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
    - |
      if ! git merge --no-commit --no-ff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME; then
        echo "Merge conflict detected"
        exit 1
      fi
  allow_failure: false

build_job:
  stage: build
  script: echo "Building..."
  needs: [conflict_check]
Enter fullscreen mode Exit fullscreen mode

The conflict_check job must succeed before any build runs, guaranteeing a clean merge.


Best Practices Checklist

  • Fail fast: Detect conflicts in the PR validation stage.
  • Keep CI fast: Use lightweight merge‑driver tricks for auto‑resolvable files.
  • Provide clear logs: Print conflicted file names and suggested actions.
  • Version‑control the resolution script: Store it in the repo so every pipeline uses the same logic.
  • Educate the team: Share guidelines on writing conflict‑friendly code (e.g., avoid large, unrelated changes in a single PR).

Real‑World Example

A microservice team integrated the above checks into their GitHub Actions workflow. After the first week, merge‑related pipeline failures dropped from 27% to 3%, and the average time to resolve a conflict fell from 45 minutes to under 5 minutes.


Get the Complete Toolkit

For a ready‑to‑use set of scripts, CI templates, and a sample repository, grab the resources below:

Implement these patterns today and keep your CI/CD pipelines humming without interruption.

Top comments (0)