The first time Git says CONFLICT, it feels like something broke. Nothing broke. A conflict just means two branches changed the same lines and Git refuses to guess which change you want. You are the missing piece of the algorithm.
Slow down and look at the state#
git status
This lists the conflicted files under “Unmerged paths”. Everything else already merged cleanly - the conflict is usually much smaller than the panic suggests.
Read both sides#
Open a conflicted file and you find the markers:
<<<<<<< HEAD
Route::get('/invoices', [InvoiceController::class, 'index']);
=======
Route::resource('invoices', InvoiceController::class);
>>>>>>> feature/invoice-crud
HEAD is your side - the branch you are merging into. The other side is the incoming branch. The decision is rarely “pick one”: most of the time the right answer is a combination, and in this example it is deleting both lines and writing the single route the app actually needs. Edit the file until it reads correctly and every marker is gone.
Then finish properly#
git add routes/web.php
git merge --continue
Two habits make this safe:
- Search for leftover markers before committing:
git diff --checkflags them, and a quickgrep -r '<<<<<<<' app routesconfirms none survived. - Run the test suite after resolving, not before. The resolved state is the code that has to pass.
If it goes wrong#
git merge --abort puts everything back to before the merge, any time before you commit the result. Knowing the exit exists makes the whole thing less tense. And if a conflict was resolved badly and committed, the tools from When to Reset, Restore, or Revert and the reflog get you out.
Fewer conflicts, not zero#
Conflicts scale with how long branches live and how much they overlap. Small, short-lived branches - the same habit that keeps pull requests reviewable - turn most conflicts into thirty-second events. The ones that remain are usually telling you something useful: two people edited the same code because the code needed one decision, not two.
Share this post
Keep reading
Annotating Commits with git notes: Metadata Without Rewriting History
Some things belong on a commit but not in it: review links, benchmark results, the ticket nobody remembered to reference. git notes adds them after the fact, no rebase required.
Backing Up Your Git Server So It Actually Restores
Every clone is a partial backup - but hooks, config and server state live outside the repo. Mirror, bundle, copy off-site, and rehearse the restore.
Cherry-Picking: One Commit Without the Branch
Cherry-pick copies a single commit onto your branch and leaves the rest behind. Right for hotfixes across release branches, wrong as a sync strategy.