
September 10, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
Two developers edit the same line in routes/web.php, and your next git merge stops cold. That is a merge conflict — Git refusing to guess which change wins. To resolve Git merge conflicts like a pro, you need a repeatable workflow, not panic edits. This guide walks through real markers, three-way merges, tool choices, and the checks I run before any merge or rebase lands on main. Whether you ship Laravel apps, WordPress themes, or CI pipelines, the mechanics are identical; only the file paths change.
git add, then finish with git merge --continue or git commit after running tests.What causes Git merge conflicts during a merge or pull?
Git merges when histories diverge. It auto-combines changes that touch different lines or different files. A conflict appears when both branches change the same hunk and Git cannot pick a winner without losing work.
Common triggers on production teams include parallel feature branches, hotfixes on main while a long-lived branch rots, and formatting sweeps that rewrite entire files. Renames and moves cause painful conflicts too — Git may treat a moved file as delete-plus-add.
On a legal-tech portal I built, two developers edited the same Blade partial for a booking form. One added Khalti payment fields; the other refactored validation markup. Same file, overlapping lines — classic conflict material.
Understanding the trigger helps you prevent repeats. Short-lived branches, smaller commits, and consistent branching strategy choices reduce conflict volume more than any mergetool ever will.
How do you read Git conflict markers in a file?
Conflicted files contain marker blocks. Git inserts them; you must remove every marker before committing. Leaving even one marker breaks PHP parsing and fails CI instantly.
Standard marker anatomy
A typical block looks like this inside a Laravel controller:
<<<<<<< HEAD
return redirect()->route('bookings.index')
->with('success', 'Booking saved.');
=======
return redirect()->route('bookings.show', $booking)
->with('status', 'Booking created.');
>>>>>>> feature/booking-redirect
The rules are fixed:
<<<<<<< HEADstarts your current branch version (where you ran merge).=======separates the two sides.>>>>>>> branch-nameends the incoming branch version.- Everything outside the markers is already merged — do not delete unrelated lines.
HEAD during a merge is the branch you checked out before merging. If you run git merge feature/x on main, HEAD is main. That trips people who merge in the wrong direction. Run git branch --show-current first.
Multiple conflicts in one file
Large files may contain several marker blocks. Search for <<<<<<< until zero remain. A regex tester helps validate patterns if you script checks in CI.
What is the step-by-step workflow to resolve Git merge conflicts?
Pros follow the same sequence every time. Speed comes from habit, not shortcuts that skip verification.
- Confirm state. Run
git status. Git lists unmerged paths under "Unmerged paths". - Choose scope. Decide whether to finish, abort, or use a mergetool.
- Edit each file. Open conflicted paths. Combine logic; delete markers.
- Stage resolved files. Run
git add path/to/file.phpper file. - Complete the merge. Run
git merge --continueor commit if Git opens an editor. - Verify. Run tests, lint, and a quick smoke test on affected routes.
Commands you will use daily
# See conflicted files
git status
# List only unmerged paths
git diff --name-only --diff-filter=U
# Abort and return to pre-merge state
git merge --abort
# After fixing each file
git add app/Http/Controllers/BookingController.php
# Finish when all conflicts are staged
git merge --continue
# See conflict hunks with more context
git diff
During a Deployer 7 deploy on shared EC2 infrastructure, I once merged a hotfix while a feature branch was mid-merge locally. Staging only the resolved files — not unrelated WIP — kept the merge commit clean and avoided pushing half-fixed conflict markers to GitLab CI.
Using git mergetool
GUI tools show base, ours, and theirs side by side. Configure once:
git config --global merge.tool vimdiff
# or: meld, kdiff3, vscode (via extension)
git mergetool
Mergetool writes resolved files and often stages them. Still run git status before continuing. Official reference: git-merge documentation.
Should you keep ours, theirs, or rewrite the conflict hunk?
Blindly picking one side loses work. The goal is a correct third version, not speed.
| Situation | Best action | Example |
|---|---|---|
| Same bug fix, different wording | Pick one clean version | Identical validation rule in a Form Request |
| Additive features on same area | Merge both logically | Payment gateway + SMS notification in checkout |
| Refactor vs feature | Re-apply feature on new structure | Controller split while another dev added a method |
| Config/env values | Never auto-merge secrets | .env.example keys from both branches manually |
Lock files (composer.lock) | Regenerate after merge | Run composer update nothing or reinstall deps |
| Binary assets (PNG, PDF) | Choose one file or external asset | Logo swap — Git cannot merge pixels |
For composer.lock on Laravel 13 projects (PHP 8.3+), I resolve composer.json by hand, delete the lock conflict, then run:
composer install
composer update package/name --with-dependencies # only if needed
git add composer.json composer.lock
Never commit a lock file you did not regenerate locally. Production drift causes deploy failures that look like application bugs.
On projects using secrets scanning in Git and CI, scan again after resolving .env.example or config conflicts. A bad paste can expose API keys.
Checkout shortcuts (use with care)
# Take entire file from current branch
git checkout --ours path/to/file.php
# Take entire file from incoming branch
git checkout --theirs path/to/file.php
# Then edit if needed and stage
git add path/to/file.php
These commands replace the whole file. They work for generated assets or when one branch clearly owns the file. They are dangerous for controllers where both sides added methods you still need.
How do you resolve merge conflicts during rebase, pull, and cherry-pick?
Conflict markers look the same. Only the Git command to finish or abort changes.
git pull(merge mode): finish withgit merge --continueafter staging.git pull --rebase: fix files,git add, thengit rebase --continue. Abort withgit rebase --abort.git rebase main: conflicts replay commit by commit. You may fix the same file multiple times.git cherry-pick <sha>: one commit applied; continue withgit cherry-pick --continue.
Rebase rewrites history. If you already pushed the branch, you need a force push — coordinate with your team first. Read when to rebase versus merge before choosing a default workflow.
During rebase, HEAD moves through replayed commits. Marker labels still say branch names, but "ours" and "theirs" swap meaning compared to a merge. When confused, read the hunk content — not the label alone.
What advanced techniques prevent repeat merge conflicts?
Resolution skill matters. Prevention saves more hours across a team.
Enable rerere for repeated conflicts
git rerere (reuse recorded resolution) stores how you fixed a conflict. Git replays that fix if the same conflict appears again — common during long rebases.
git config --global rerere.enabled true
git config --global rerere.autoupdate true
It is not magic. It helps when the same hunk fights you on every rebase of a stale branch.
Merge main into feature often
Sync early and often:
git checkout feature/booking-flow
git fetch origin
git merge origin/main
# resolve small conflicts now, not one giant conflict at PR time
This pairs well with Git hooks that run checks before push. Catch syntax errors from bad merges before they hit remote.
CI and pipeline gotchas
After resolving conflicts in GitLab CI config or Deployer recipes, run the pipeline on your branch. I have seen merged .gitlab-ci.yml files with duplicate job keys that passed locally but failed on the runner.
File-permission conflicts on Linux deploy targets are a separate problem. If merges touch executable bits, see how to stop Git from tracking file permissions to reduce noise.
Recover when a merge goes wrong
If you committed a bad resolution, git reflog shows prior HEAD positions. You can reset to pre-merge state if you have not pushed yet:
git reflog
git reset --hard HEAD@{1}
Details: recover lost commits with git reflog. After push, prefer a revert commit over force-pushing shared branches.
Platform-specific notes
Azure DevOps and GitHub both surface conflicts in the web UI for simple line edits. For Laravel apps with nested Blade logic, resolve locally. Web editors miss context from related partials and service providers.
Teams on Azure Repos with branch policies may require merge commits or squash merges. Know your target format before you start — squash merges hide intermediate conflict commits but still require clean resolution in the final diff.
Real project patterns
On trek booking systems with Livewire components, conflicts cluster in Livewire classes and shared Blade layouts. Fix the PHP class first, then re-run frontend builds with Vite 8.x if JS imports changed.
On legal information portals, content and routing conflicts often overlap. Keep slug changes from one branch and new route definitions from another — broken routes hurt SEO faster than a failed deploy.
For ongoing maintenance, many clients use support and maintenance retainers partly because merge debt on long-lived forks costs more than proactive syncs.
Key Takeaways
- Run
git statusfirst; know whether you are in merge, rebase, or cherry-pick before editing. - Delete every
<<<<<<<,=======, and>>>>>>>marker — leftover markers break builds. - Combine both sides when features are additive; regenerate
composer.lockinstead of hand-merging it. - Use
git merge --abortorgit rebase --abortwhen you are on the wrong branch or need a reset. - Always run tests and CI after resolution; merge commits with conflict fixes still need the same quality bar as feature work.
- Prevent conflicts with short-lived branches, frequent syncs from main, and a team-wide branching policy.
People Also Ask
Can Git resolve merge conflicts automatically?
Git auto-merges non-overlapping changes in the same file. When the same lines change, it stops and marks the file conflicted. Tools like git mergetool assist you, but a human (or carefully configured rerere) must confirm the final logic. No reliable tool understands your business rules.
What happens if I commit without fixing conflict markers?
PHP, JavaScript, and YAML parsers fail on marker lines. CI fails immediately. In production, you might ship a white screen or 500 error. Some teams add a pre-commit hook searching for <<<<<<< — cheap insurance.
Is it better to merge or rebase to avoid conflicts?
Neither avoids conflicts when the same lines change. Rebase replays commits and can multiply conflict rounds. Merge produces one conflict session but adds a merge commit. Pick based on team policy and whether the branch is shared — not based on conflict avoidance myths.
How do I resolve conflicts in a pull request on GitHub?
GitHub offers "Resolve conflicts" in the web UI for simple text files. Use it for copy or config tweaks. For application code with tests and dependencies, check out the branch locally, resolve with your IDE, run the test suite, then push. The PR updates automatically.
Ship clean merges on every project
Merge conflicts are normal on active codebases — Laravel apps, WooCommerce shops, and CI-driven deploy pipelines all hit them. The difference between a ten-minute fix and a production incident is process: read markers carefully, merge intent not labels, regenerate lock files, and verify before push. If you want help tightening Git workflow, deploy pipelines, or custom software delivery on your stack, get in touch via the contact page. You can also browse the portfolio for examples of production systems maintained with GitLab CI and Deployer, or read more on the blog about AI-assisted code review in CI and fixing Git ignore problems that often surface during messy merges.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

