Fix: CONFLICT (content): Merge conflict in file — fix conflicts and then commit the result
The Error
You run a Git operation and see one of these messages:
During a merge:
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js
Automatic merge failed; fix conflicts and then commit the result.During a rebase:
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js
error: could not apply 3a1f29c... Add new feature
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".During a cherry-pick:
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js
error: could not apply 7b2e4d1... Fix login bug
hint: After resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'During a pull:
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js
Automatic merge failed; fix conflicts and then commit the result.The wording varies slightly, but the cause is the same: Git found changes on both sides that touch the same lines, and it cannot decide which version to keep.
Why This Happens
Git tracks changes as diffs — additions, deletions, and modifications to lines. When you merge two branches (or rebase, cherry-pick, or pull), Git attempts a three-way merge. It compares each side’s changes against the common ancestor commit and applies both sets of changes automatically.
A conflict occurs when both sides modify the same lines in the same file. Git has no way to know which change is correct. It could be that one side renamed a variable while the other side changed the logic on that same line. Applying both would produce broken code, so Git stops and asks you to decide.
Conflicts can also happen with file-level operations: one side deletes a file while the other side modifies it, or both sides add a file with the same name but different contents. These produce CONFLICT (modify/delete) or CONFLICT (add/add) messages.
The error is not a sign that something is wrong with your repository. It is a normal part of collaborative development. If you have worked with a team or maintained long-lived branches, you will encounter this regularly. The key is knowing how to resolve conflicts efficiently. If your repository itself seems broken, check Fix: fatal: not a git repository first to rule out structural issues.
Fix 1: Understand Conflict Markers
Before resolving anything, you need to understand what Git puts in your files. When a conflict occurs, Git inserts markers that look like this:
<<<<<<< HEAD
const API_URL = "https://api.example.com/v2";
const TIMEOUT = 5000;
=======
const API_URL = "https://staging.example.com/v1";
const TIMEOUT = 10000;
>>>>>>> feature-branchHere is what each section means:
<<<<<<< HEADmarks the start of your current branch’s version (the branch you are merging into).=======separates the two versions.>>>>>>> feature-branchmarks the end of the incoming branch’s version (the branch you are merging from).
During a rebase, the labels are swapped because rebase replays your commits on top of the target branch. HEAD refers to the target branch (not your branch), and the bottom section shows the commit being replayed.
Your job is to edit the file so it contains exactly the code you want, and then remove all three marker lines. You can keep one side, keep the other, keep both, or write something entirely new.
Fix 2: Manually Resolve Conflicts
This is the most common fix and works in every situation.
Step 1: Identify conflicting files:
git statusFiles with conflicts appear under “Unmerged paths” and are marked as both modified, both added, or deleted by us/deleted by them.
Step 2: Open each conflicting file in your editor. Search for <<<<<<< to find every conflict block. Edit the file to contain the correct final content. Remove all <<<<<<<, =======, and >>>>>>> lines.
For example, if you want to keep the production URL but use the longer timeout:
const API_URL = "https://api.example.com/v2";
const TIMEOUT = 10000;Step 3: Stage the resolved files:
git add src/app.jsStep 4: Complete the merge with a commit:
git commitGit pre-fills a merge commit message. You can keep it or edit it. If you want to add context about how you resolved the conflict, add it to this message.
Fix 3: Use VS Code Merge Editor
VS Code detects conflict markers automatically and provides an inline interface. When you open a file with conflicts, VS Code shows buttons above each conflict block: Accept Current Change, Accept Incoming Change, Accept Both Changes, and Compare Changes.
For more complex conflicts, use the dedicated merge editor:
- Open the file with conflicts.
- Click Resolve in Merge Editor at the bottom of the conflict notification.
- The three-pane editor shows: the current branch (left), the incoming branch (right), and the result (bottom).
- Check the boxes next to the changes you want to accept, or edit the result pane directly.
- Click Complete Merge when finished.
- Stage and commit as usual.
This visual approach makes it much easier to handle files with multiple conflict blocks or conflicts in code you are not familiar with.
Fix 4: Use git mergetool
Git can launch an external merge tool to help resolve conflicts. If you have a diff tool configured (such as meld, kdiff3, vimdiff, or p4merge), run:
git mergetoolGit opens each conflicting file in the configured tool one at a time. The tool typically shows a three-way diff: the base version (common ancestor), the local version, and the remote version. You resolve the conflict in the tool, save, and close it. Git marks the file as resolved.
To configure a default merge tool:
git config --global merge.tool meldAfter the tool finishes, Git creates .orig backup files. To disable these:
git config --global mergetool.keepBackup falseThen commit the result:
git commitFix 5: Accept Theirs or Ours (Bulk Resolution)
Sometimes you know that one side is entirely correct and you want to discard the other side’s changes for specific files. Git provides shortcuts for this.
Accept the incoming branch’s version (theirs):
git checkout --theirs src/app.js
git add src/app.jsAccept your current branch’s version (ours):
git checkout --ours src/app.js
git add src/app.jsYou can apply this to multiple files at once:
git checkout --theirs src/config.js src/utils.js src/routes.js
git add src/config.js src/utils.js src/routes.jsOr accept one side for all conflicting files:
git checkout --theirs .
git add .Warning: This discards all changes from one side across every conflicting file. Only use it when you are certain that one branch’s version is completely correct. After resolving, commit the result with git commit.
Important note on rebase: During a rebase, --ours and --theirs are swapped compared to merge. In a rebase, --theirs refers to your branch (the commits being replayed), and --ours refers to the target branch. This is a common source of confusion.
Fix 6: Abort the Merge
If the conflicts are too complex or you started the merge by mistake, you can abort and return to the state before the merge began:
git merge --abortThis resets your working tree and index to the pre-merge state. No changes are lost from either branch — the merge simply did not happen.
For a cherry-pick:
git cherry-pick --abortFor a pull that resulted in conflicts (since git pull is essentially git fetch + git merge):
git merge --abortAborting gives you time to review the branches, coordinate with teammates, or restructure your approach before trying again. This is particularly useful if you realize the merge needs more planning. If you are working in a CI/CD pipeline and conflicts cause a build failure, aborting and fixing locally before pushing is the right approach.
Fix 7: Rebase Conflicts (git rebase --continue)
Rebase conflicts are different from merge conflicts because rebase replays commits one at a time. You may need to resolve conflicts multiple times — once for each commit that conflicts.
Step 1: Resolve the conflict in the current file (see Fix 2).
Step 2: Stage the resolved files:
git add src/app.jsStep 3: Continue the rebase:
git rebase --continueGit applies the next commit. If that commit also conflicts, you repeat the process. This continues until all commits have been replayed.
Skip a commit entirely:
If a commit’s changes are no longer relevant (they were already incorporated into the target branch), skip it:
git rebase --skipAbort the entire rebase:
git rebase --abortThis returns everything to the state before you started the rebase. No commits are lost.
Tip: If you are rebasing a long branch with many conflicts, consider using git merge instead. A merge produces a single merge commit and requires resolving conflicts only once, while a rebase may require conflict resolution for each individual commit.
Fix 8: Pull Conflicts (git pull --rebase)
When git pull causes conflicts, it is because the remote branch and your local branch both have new commits that touch the same lines.
Option A: Pull with merge (default behavior).
Resolve the conflicts as described in Fix 2, then commit. This creates a merge commit.
Option B: Pull with rebase instead.
If you prefer a linear history without merge commits:
git pull --rebaseIf conflicts occur during the rebase, resolve them and continue:
git add src/app.js
git rebase --continueOption C: Fetch first, review, then merge.
This is the safest approach and helps prevent surprises:
git fetch origin
git log HEAD..origin/main --oneline
git diff HEAD...origin/mainThis lets you see exactly what changed on the remote before you integrate. If you see potential conflicts, you can plan your resolution strategy. Then merge or rebase when ready:
git merge origin/mainIf you encounter permission errors while pushing or pulling, resolve those authentication issues before attempting the merge again.
Fix 9: Prevent Conflicts (Fetch and Review First)
The best conflict is one that never happens. While you cannot always avoid conflicts, you can minimize them:
Fetch and review before merging:
git fetch origin
git log --oneline HEAD..origin/main
git diff HEAD...origin/main -- src/Review what changed on the remote. If you see modifications to files you also changed, you know a conflict is coming and can prepare.
Pull frequently. The longer your branch lives without integrating upstream changes, the more conflicts you accumulate. Pull or rebase daily on active projects.
Communicate with your team. If two people are working on the same file, coordinate. Code ownership conventions and smaller, more focused pull requests reduce conflict frequency.
Keep branches short-lived. Feature branches that live for weeks accumulate massive diffs. Break large features into smaller, incremental pull requests.
Use .gitattributes for merge strategies. For files that always conflict unnecessarily (like lock files or generated files), you can tell Git how to handle them:
# Always take ours for the lock file
package-lock.json merge=oursIf you run into issues where your shell cannot execute Git commands at all, check Fix: bash permission denied to make sure your environment is properly configured.
Fix 10: Resolve Binary File Conflicts
Binary files (images, PDFs, compiled assets) cannot be merged line-by-line. When Git detects a conflict in a binary file, it does not insert conflict markers. Instead, it tells you there is a conflict and leaves both versions available.
warning: Cannot merge binary files: assets/logo.png (HEAD vs. feature-branch)
CONFLICT (content): Merge conflict in assets/logo.pngYou must choose one version or the other:
# Keep the version from the current branch
git checkout --ours assets/logo.png
git add assets/logo.png
# Keep the version from the incoming branch
git checkout --theirs assets/logo.png
git add assets/logo.pngIf you need to combine changes from both versions (for example, two different edits to an image), you must do this manually outside of Git using the appropriate editor for that file type. Extract both versions, combine them in your image editor, save the result, and stage it.
For projects with many binary assets, consider using Git LFS (Large File Storage), which handles binary files more efficiently and provides better conflict workflows.
Fix 11: Large-Scale Conflicts with git rerere
If you frequently resolve the same conflicts — for example, when maintaining multiple long-lived branches or doing repeated merges during integration testing — Git’s rerere (“reuse recorded resolution”) feature can help.
Enable rerere:
git config --global rerere.enabled trueOnce enabled, Git records how you resolve each conflict. The next time it encounters the same conflict (the same two conflicting hunks), it applies your previous resolution automatically.
How it works:
- You resolve a conflict and commit.
- Git records the resolution in
.git/rr-cache/. - Later, the same conflict appears again (perhaps during a re-merge or when another branch hits the same conflict).
- Git applies the recorded resolution automatically and tells you:
Resolved 'src/app.js' using previous resolution. - You still need to verify and stage the file, but the editing is done.
View recorded resolutions:
git rerere status
git rerere diffClear a bad recorded resolution:
git rerere forget src/app.jsThis is especially useful in workflows where you rebase feature branches onto a frequently updated main branch. The first rebase requires manual resolution; subsequent rebases reuse your decisions.
If you are dealing with merge conflicts inside a stash pop operation, the resolution process is similar but has some additional considerations around stash management.
Still Not Working?
Conflict markers left in committed files
If you accidentally committed a file that still contains <<<<<<< markers, the conflict is “resolved” from Git’s perspective but your code is broken. Fix the file, stage it, and create a new commit:
git add src/app.js
git commit -m "Fix unresolved conflict markers in app.js"To prevent this, add a pre-commit hook that checks for conflict markers:
git diff --cached --checkThis command detects leftover conflict markers in staged files and exits with an error if any are found.
CONFLICT (modify/delete)
This means one side modified a file while the other side deleted it. Git does not know whether to keep the modified version or honor the deletion.
To keep the file:
git add src/app.jsTo accept the deletion:
git rm src/app.jsThen continue with git commit (for merge) or git rebase --continue (for rebase).
CONFLICT (rename/delete)
One side renamed a file while the other deleted the original. Similar to modify/delete, decide whether the renamed file should exist:
# Keep the renamed file
git add src/newname.js
git rm src/oldname.js
# Or accept the deletion
git rm src/newname.jsMerge says “Already up to date” but branches differ
If git merge feature-branch says “Already up to date” but you know the branches have different content, it means the current branch already contains all commits from the feature branch (the feature branch is an ancestor). This is not a conflict — it means the merge was already completed at some point, or the feature branch was branched from a point that is behind your current HEAD.
Check the commit history:
git log --oneline --graph --allConflicts reappear after resolution
If you resolve conflicts, commit, and then see the same conflicts again on the next merge, it usually means the branches continue to diverge. Each new merge only resolves conflicts for the commits involved at that point. New commits on either branch can introduce new conflicts. Enable git rerere (Fix 11) to automate re-resolution of identical conflicts.
Repository seems corrupted
If Git itself is throwing unexpected errors beyond merge conflicts — such as complaints about missing objects or corrupted refs — you may have a different problem. See Fix: fatal: not a git repository for diagnosing repository structure issues.
Related: Fix: git stash pop – CONFLICT | Fix: Permission denied (publickey) | Fix: fatal: not a git repository | Fix: GitHub Actions process completed with exit code 1 | Fix: bash permission denied
Related Articles
Fix: fatal: not a git repository (or any of the parent directories): .git
How to fix the 'fatal: not a git repository' error in Git by checking your working directory, initializing a repo, recovering a deleted .git folder, and resolving submodule, CI/CD, and IDE path issues.
Fix: git stash pop – CONFLICT, local changes would be overwritten, no stash entries found
How to fix git stash errors: 'CONFLICT' after git stash pop, 'Your local changes to the following files would be overwritten', 'No stash entries found', and 'Could not restore untracked files from stash entry'. Covers stash pop vs apply, conflict resolution, recovering dropped stashes, and stashing untracked files.
Fix: You are in 'detached HEAD' state
How to fix Git's 'detached HEAD' state, 'HEAD detached at xxx', 'HEAD detached from xxx', and 'Warning: you are leaving X commits behind'. Covers creating a branch, saving commits, recovering lost work with reflog, and when detached HEAD is intentional.
Fix: CONFLICT (content): Merge conflict in [file] – Automatic merge failed
How to fix Git merge conflicts: 'CONFLICT (content): Merge conflict in [file]', 'Automatic merge failed; fix conflicts and then commit the result', 'You have unmerged paths', and 'needs merge'. Covers manual resolution, VS Code, --theirs/--ours, merge --abort, mergetool, rebase conflicts, and prevention.