Step-by-step
-
1
Trigger the merge and read the error
When Git detects a conflict during
git mergeorgit pull, it stops mid-merge and prints the conflicting files. Nothing has been committed yet.bashgit merge feature/user-auth # CONFLICT (content): Merge conflict in src/auth.js # Automatic merge failed; fix conflicts and then commit the result. -
2
Identify every conflicted file
git statuslists all conflicted files under Unmerged paths. These are the only files you need to edit — everything else has already been merged cleanly.bashgit status # both modified: src/auth.js # both modified: config/app.js -
3
Read the conflict markers
Open each conflicted file. Git wraps the two competing versions in markers: everything between
<<<<<<< HEADand=======is what your current branch has; everything between=======and>>>>>>> feature/user-authis what the incoming branch has.bash<<<<<<< HEAD const timeout = 3000; ======= const timeout = 5000; >>>>>>> feature/user-auth -
4
Edit the file to the correct final state
Delete the conflict markers and all three delimiter lines. Write exactly what the file should contain — which may be one side, the other, or a combination of both. Save the file.
bash// Resolved: keep the longer timeout from the feature branch const timeout = 5000; -
5
Mark each file resolved and commit
After saving, stage the resolved file with
git add. Once all conflicted files are staged, finalise the merge commit. Modern Git usesgit merge --continue; older versions just usegit commit.bashgit add src/auth.js git add config/app.js # Modern Git (2.12+) git merge --continue # Or simply: git commit -
6
Use VS Code as a visual merge tool
Visual tools eliminate the risk of accidentally leaving a marker in the file. Configure VS Code as your default mergetool, then let it open each conflict with Accept Current / Accept Incoming / Accept Both buttons.
bashgit config --global merge.tool vscode git config --global mergetool.vscode.cmd 'code --wait $MERGED' # Then during a conflict: git mergetool -
7
Abort the merge entirely if needed
If the conflict is too complex to resolve right now, bail out completely. This resets both files and the index back to the state they were in before you ran
git merge.bashgit merge --abort # The repo is back to the pre-merge state -
8
Enable rerere to remember resolutions
rerere(reuse recorded resolution) records how you resolved a conflict so Git can replay the same resolution automatically if the same conflict appears again — common on long-lived feature branches that are rebased repeatedly.bashgit config --global rerere.enabled true # From now on, resolved conflicts are recorded in .git/rr-cache/ # and replayed automatically on future identical conflicts.
Tips & gotchas
- Pull from the base branch frequently (<code>git pull origin main</code>) to keep your feature branch close to main — smaller diffs mean fewer conflicts.
- Keep branches short-lived. A branch open for two weeks is a conflict waiting to happen.
- If a conflict spans hundreds of lines, <code>git merge --abort</code> and talk to the author of the conflicting change before proceeding.
- Search for leftover markers before committing: <code>grep -r "<<<<<<<" .</code>
Wrapping up
Merge conflicts are a normal part of collaborative development — not an emergency. The workflow is always the same: read git status, fix the markers, git add, git merge --continue. The best long-term strategy is prevention: short branches, frequent pulls, and rerere enabled so repeated conflicts resolve themselves.