# How to resolve git merge conflict markers step by step on a Mac in 2026

> Resolve git merge conflict markers step by step on your Mac. Find the markers, pick the right code, stage the file, and finish the merge safely.

URL: https://www.lazur.app/for/developers/problems/git-merge-conflict-markers-step-by-step
Updated: 2026-11-06

To resolve git merge conflict markers, find each conflict block. It starts with <<<<<<< and ends with >>>>>>>. Choose the code to keep, delete the marker lines, stage the file, and finish the merge. This guide covers each step in Terminal and VS Code on a Mac, plus the checks that stop a bad merge from reaching your branch.

## Quick answer

- Run git status to list the files Git could not merge.
- Open each file, find the block from <<<<<<< HEAD to >>>>>>>, and choose the code you want.
- Delete all three marker lines in every conflict, then search for any that remain.
- Run git add on each fixed file, then git commit or git merge --continue.
- If the merge goes wrong, run git merge --abort to return to where you started.

## What resolving git merge conflicts costs you

- **Paid time, at a rough hourly rate.** Conflict work is paid time. BLS puts the median annual pay for software developers at $135,980 in May 2025. Assuming 2,080 paid hours a year, that works out to about $65 an hour. That hourly figure is our own derivation, not a BLS number. At that rate, half an hour of conflict work costs about $33 in salary time.
- **A pull request that waits.** A conflicted branch cannot merge until someone fixes it. The pull request sits in review. The reviewer loses the thread, and the author switches to other work. Each handoff adds time. None of this shows up on a timer, which is why it is easy to miss.
- **Code that builds but behaves wrong.** The worst cost is a merge that compiles and still behaves wrong. Automatic picks such as -X theirs can drop a useful change without a warning. Your tests may not cover the lost line. You may only find it later, in production or in a customer report.
- **How often AI-written branches collide.** A 2026 arXiv preprint replayed 747 branch pairs from AI-agent pull requests. Textual conflicts appeared in 19.8% of same-agent pairs and 41.7% of cross-agent pairs. The authors call these lower bounds. The preprint is not peer reviewed, so treat the numbers as a signal, not a verdict.

## Why it happens

1. **Both branches changed the same lines.** This is the classic conflict. Git can merge changes that sit in different places. Two edits to the same lines leave it stuck, because Git cannot tell which version you meant. Long-running feature branches make this more likely, since they touch more lines over time.
2. **One branch deleted a file the other edited.** Git calls this modify/delete. One side removes or moves a file while the other side changes it. In the AI-agent pull requests in the 2026 preprint, modify/delete conflicts made up 26.8% of conflicted files. Content conflicts made up 57.6%, so check for both kinds.
3. **Two branches created the same new file.** This is add/add. Each branch creates a file with the same path but different contents. Git cannot pick one without help from you. The same preprint counted 15.1% of its conflicted files as add/add in the AI-agent set.
4. **Source code takes most of the hits.** In that preprint's AI-agent replay, source code made up 84.4% of conflicted files. Configuration and generated files still collide. Code still takes most of the hits, so expect conflicts in the files you edit most.
5. **Tool-generated project files.** Some files are rewritten by tools, such as lock files and Xcode project files. Two branches that each run a tool can produce different output for the same file. The Apple forum thread shows how painful this can feel on a team that merges daily.
6. **Branches that go stale.** A branch that stays open for weeks drifts away from main. Every day it drifts, the chance that someone else touched the same line grows. This cause is one you control. Pull main into your branch often, and conflicts stay small.

## How to fix it

- **Merge main into your branch often.** Merge or pull main into your feature branch every day or two. Small, frequent merges leave fewer overlaps. Run git fetch origin, then git merge origin/main while your branch is clean. Fix each small conflict while the context is still fresh in your head.
- **Turn on the zdiff3 conflict style.** Run git config --global merge.conflictStyle zdiff3 once. Git's manual lists diff3 and zdiff3 as options. The base text shows what each branch changed from. Use it on your next conflict and compare the blocks with the default output.
- **Use the list of unmerged files.** Run git ls-files -u to see each conflicted file and its index stages. Use it to check that you did not miss a file. A file that never appears in that list is not part of the conflict.
- **Choose a side per block, not per file.** Read both sides of each block, then choose. Top is your side, bottom is the incoming side. Edit by hand, or use VS Code's Accept buttons for simple blocks. Reading first avoids the reflex fix that drops a change you needed.
- **Use the VS Code 3-way Merge Editor.** Open the Source Control view and click the conflicted file. Use the 3-way Merge Editor to compare Incoming, Current, and Result. Edit only the Result pane. Click Complete Merge to stage that file, then finish the Git operation in Terminal or Source Control.
- **Use git merge --abort as a reset.** If you feel lost, run git merge --abort. Git returns to the state before the merge. Copy any resolution you want to keep first, because abort drops those edits. Then restart the merge with a clearer plan.
- **Search for markers and run tests before every commit.** Run grep -rnE '^(<{7}|={7}|>{7})' . from the project root, then run your tests. Markers can hide in files you did not open. Tests catch many wrong picks, but not all of them. Read the diff for every file you touched.

## What a merge conflict is and why Git stops

A merge conflict means Git could not combine two sets of changes by itself. Git merges on its own when the edits sit in different places. When two branches change the same lines, Git stops and asks you to decide.

Git does not guess. It leaves your branch where it is, records the other branch in a file called MERGE_HEAD, and marks the trouble spots in your files. Your project is now half merged. Nothing is lost, but nothing is finished either.

That half-merged state is why people panic. The fix is short. Find the conflicts, decide, edit, stage, and commit. The rest of this page walks through that loop with real commands and real menu paths.

- **1,717,800** US software developer jobs, May 2025 (BLS) ([source](https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm))
- **19.8%** Textual conflict rate for same-agent branch pairs in a 747 pair replay of AI-agent pull requests ([source](https://arxiv.org/html/2607.04697))
- **41.7%** Textual conflict rate for cross-agent branch pairs in the same replay, a lower bound ([source](https://arxiv.org/html/2607.04697))

## Before you start: check where you are

Open Terminal and change into the project folder. Run git status first. Git lists every file it could not merge under a heading called Unmerged paths, and it names the branch in progress. Write that branch name down.

Run git branch --show-current to confirm which branch you are on. A merge into the wrong branch makes the conflict harder to read and harder to undo. If you are on the wrong branch, abort first with git merge --abort, then switch with git switch.

Commit or stash your own unsaved work before you merge. Git refuses some merges when your local edits overlap the incoming changes. A clean state makes the conflict list easier to trust.

## Step 1 to 3: find every conflicted file

Run git status again once the merge stops. Look for files marked both modified. Those files hold conflict markers. For a precise list, run git ls-files -u. Each line names a file and an index stage number.

Git keeps three versions of a conflicted file in its index. Stage 1 is the common ancestor, the point where the branches split. Stage 2 is your side, HEAD. Stage 3 is the incoming side, MERGE_HEAD. You do not need to work with stages directly. Knowing they exist helps when markers look confusing.

![Programmer at a laptop reviewing code before a git merge](https://lfobmih1tpj3sgpo.public.blob.vercel-storage.com/content-images/problem/git-merge-conflict-markers-step-by-step/how-to-resolve-git-merge-conflict-markers-1-b0f285.jpg)

## Step 4: read the conflict markers

Open a conflicted file in any editor. Git writes three marker lines around each conflict. Lines between <<<<<<< HEAD and ======= come from your branch. Lines between ======= and >>>>>>> come from the branch you merged in.

| Marker line | What it marks | What you do |
| --- | --- | --- |
| <<<<<<< HEAD | Start of your side, the current branch | Read it, then decide whether to keep it |
| ======= | Divider between the two versions | Delete it when you finish the block |
| >>>>>>> feature/login | End of the incoming side, with the branch name | Delete it when you finish the block |

_The three marker lines Git writes around each conflict._

Some setups add a fourth marker, |||||||, that shows the original text. You can turn that on, and the zdiff3 section below explains how. Your file may have several blocks. Treat each block as its own decision.

## Step 5: edit the file and delete the markers

Decide what the final code should be. You can keep your side, keep the incoming side, or write a mix. Then delete every marker line in that block, along with the code you rejected. Leave only the code you want.

Here is a small example. Your branch sets a timeout to 30. The other branch sets it to 45 and adds a retry count. The right answer may be 45 with the retry count. Type that line yourself. Git will not check whether the value makes sense.

Save the file, then run your build and tests. A file with no markers can still be wrong. Treat the edit like any other code change.

Search for leftover markers from the project root with grep -rnE '^(<{7}|={7}|>{7})' . If the command prints nothing, no marker lines remain. Lines that are only seven equal signs in docs can give false matches, so read any hit before you delete it.

## Step 6: stage the file and finish the merge

1. Run git add with each fixed file path, for example git add src/config.js.
2. Run git status. Fixed files should show as staged, and Unmerged paths should be gone.
3. Run git commit. Git opens the merge message with default text. Edit it if needed, then save and close.
4. Or run git merge --continue, which finishes the merge once every file is staged.
5. Run git log --oneline -3 to confirm the merge commit sits on top.

If Vim opens for the message, press Esc, type :wq, and press Return. That saves and exits. If another editor opens, save the message and close the window.

## Use zdiff3 to see what each branch changed

The default style shows only your side and the incoming side. It hides the original text. Set a better style once with git config --global merge.conflictStyle zdiff3. Git then adds the base text between ||||||| and =======.

The zdiff3 style also trims lines that match on both sides at the edges of a conflict, so each block is shorter. The base text often answers the first question people ask: what did each branch change?

No published test I found measures whether zdiff3 cuts resolution time. Git's manual documents the option. Try it on a few real conflicts, then decide for yourself.

## Use -X ours or -X theirs with care

Git can pick a side for you. git merge -X theirs feature/login chooses the incoming side for each conflicting hunk. It still keeps non-conflicting changes from both sides. The -X ours option picks your side the same way.

The risk is silent loss. Git picks a whole hunk, so a useful change inside the losing side disappears. Git gives no warning. Check the result with git diff HEAD^ HEAD before you push, then read the changed lines.

![Developer at a desk coding on a Mac with a code editor open](https://lfobmih1tpj3sgpo.public.blob.vercel-storage.com/content-images/problem/git-merge-conflict-markers-step-by-step/how-to-resolve-git-merge-conflict-markers-2-5a707a.jpg)

Never use -s ours for a normal merge. Git's docs say that strategy discards the other branch's changes entirely. That is a different tool from -X ours, and the two names are easy to mix up.

## Back out with git merge --abort

If the conflicts feel too big, back out. Run git merge --abort. Git restores the state you had before the merge. The edits you made while resolving conflicts go with it, so copy any file you want to keep first.

Use git merge --quit if you want to forget the merge but keep the index and working tree. It is a narrower tool. Use it only when you know what is staged.

Aborting is not failure. Many people abort, read the conflict list again, and come back with a clearer plan. A clean retry costs less than a bad commit.

## Resolve the conflict in VS Code on Mac

VS Code shows conflicts inline. Above each block you see buttons. Accept Current Change keeps your side. Accept Incoming Change keeps the other side. Accept Both Changes keeps both. Compare Changes opens a side-by-side diff.

Accept Both is not a finish line. The VS Code docs warn that you may still need to remove duplicate lines or combine the logic by hand. Read the result before you move on.

For a bigger view, open the 3-way Merge Editor. Incoming sits on the left, Current on the right, and Result on the bottom. Result is the file Git saves. The Complete Merge button stages that file only. The rest of the Git operation still needs finishing.

To find the files, open the Source Control view from the sidebar and look under Merge Changes. For settings, use Code > Settings > Settings and search for merge. VS Code's docs also describe git mergetool with a vscode merge tool. Git does not open it on its own.

## When GitHub's web editor is enough

GitHub's web editor handles simple conflicts. GitHub says it resolves only simple competing line change conflicts. For anything else, GitHub tells you to use the command line or another Git client. In Chrome, check that your conflict is simple before you open it.

Resolving on GitHub merges the entire base branch into your head branch. If the head branch is protected, GitHub asks you to create a new branch. Plan for that before you start clicking.

## Xcode project files and pbxproj conflicts

Xcode projects add a tricky file, project.pbxproj. Two branches that add files or targets can both edit it. In a March 2018 Apple Developer Forums thread, one developer said they spent hours fixing these conflicts by hand on a team that merges daily. The only reply pointed to WWDC 2017 session 405.

The sources checked for this guide do not confirm a documented Xcode merge tool. Check Apple's documentation before you rely on one. For now, resolve the markers by hand, rebuild the project, and check that targets and file references still match.

## Mistakes people make when they resolve a conflict

- Deleting the markers without choosing. The file keeps both versions stacked, and that often breaks the build.
- Keeping one side by reflex. Read the other side first, since it may hold a fix you need.
- Skipping git add. Git keeps the merge open until every fixed file is staged.
- Committing with markers still in a file. Run the grep check before every commit.
- Using -s ours for a normal merge. The other branch's changes are discarded.
- Aborting after hours of edits without a copy. Abort also drops the resolution edits you made.

## A worked example from start to finish

Say you run git merge feature/login on main. Git reports a conflict in src/auth.js. You run git status and see both modified: src/auth.js. You open the file. The top block sets the token timeout to 30 minutes. The bottom block sets it to 45 and adds a refresh call.

![Person using a MacBook on a desk to fix a git merge conflict](https://lfobmih1tpj3sgpo.public.blob.vercel-storage.com/content-images/problem/git-merge-conflict-markers-step-by-step/how-to-resolve-git-merge-conflict-markers-3-040b08.jpg)

You keep 45 and the refresh call, then delete the three marker lines in that block. You save and run the tests. The tests pass. The grep check prints nothing. You run git add src/auth.js, then git commit, and save the message.

Run git log --oneline -3 and the merge commit sits on top. The time this takes depends on how many files overlap. A small conflict like this one can finish in a few minutes once you know the loop.

## Check your work before you push

Run the tests and the build again. Then run git show --stat HEAD to list the files the merge commit touched. If a file appears that you did not expect, open it and read the diff before you push.

Ask a teammate to review the merge commit when it touches shared code. A second reader often spots a wrong pick that the author has stopped seeing.

## Where Lazur helps, and where it does not

Lazur is a voice assistant for the Mac that lives in the notch. Hold ⌥⌘ to ask about anything on screen, and Lazur answers out loud. Ask where the next marker is, and Lazur draws a circle and a label around it.

Ask how to accept a change, and Lazur guides you one click at a time, waiting for each click. Lazur does not click buttons, edit files, or run Git for you. You make every choice in the file yourself.

Hold fn to dictate a merge commit message at the cursor. Dictation is unlimited on the paid plans. For longer writing, read the [AI dictation guide for developers](https://www.lazur.app/blog/ai-dictation-for-developers). Plans and trial terms are on the [pricing page](https://www.lazur.app/pricing).

## What to do after your first conflict

- Write down the branch names before you merge, so you know what to abort to.
- Set merge.conflictStyle to zdiff3 once, then review the base text on each block.
- Add the grep check to your routine, and run it before each commit.
- Practice in a throwaway repo, so a bad resolution costs nothing.

## With Lazur

Lazur is a voice assistant for the Mac that lives in the notch. Hold ⌥ ⌘ and ask; it sees your screen, answers out loud, points at buttons and walks you through apps. Hold fn to dictate. Free for 3 days, then $18/month: https://www.lazur.app/download

- “What do these conflict markers mean?”: Lazur explains that the top block is your branch and the bottom block is the branch you merged in. It points at the marker lines. (Explains what's on screen)
- “Hold ⌥⌘ and ask what these conflict markers mean.”: Lazur answers out loud from what is on your screen. You learn that the top block is your branch and the bottom block is the incoming branch.
- “Ask Lazur where the next conflict marker is.”: Lazur draws a circle and a label around the marker line, so you can find it in a long file.
- “Ask how to accept the incoming change in VS Code.”: Lazur guides you one click at a time, waiting for each click. It does not click for you.
- “Hold fn and dictate your merge commit message.”: Your words land at the cursor as clean text, in the commit message box or any other field you pick.
- “Ask Lazur to draft a short note on what you kept from each side.”: Lazur drafts the text, and you paste it or edit it. Useful for pull request descriptions, where reviewers want to know which side won.

## A plan you can start this week

- **Day 1: Practice in a throwaway repo.** Create a test folder with git init. Make two branches that edit the same line of one file. Run git merge, then resolve the conflict with the steps above. Finish with git commit and read the result in git log.
- **Day 2: Turn on zdiff3 and compare.** Run git config --global merge.conflictStyle zdiff3. Repeat the Day 1 test and compare the base text with the default output. Note which style makes each choice faster for you.
- **Day 3: Practice abort and quit.** Start a conflicting merge, then run git merge --abort. Confirm with git status that you are back where you began. Repeat the test with git merge --quit and see what stays staged.
- **Day 4: Resolve one real conflict in VS Code.** Pick a small, low-risk conflict on your team branch. Use the Accept buttons for simple blocks and the 3-way Merge Editor for one file. Run the grep check and your tests before you commit.
- **Day 5: Make the routine stick.** Add the grep check and the git status step to your team's pull request checklist. Ask one teammate to review your next merge commit. Note any file that surprised you, and why.

## FAQ

### What does <<<<<<< HEAD mean in a file?

It marks the start of your side of a conflict. HEAD is the name Git uses for your current branch tip. The lines below it, down to =======, are the code from your branch. The lines between ======= and >>>>>>> come from the branch you merged in.

### Can I just delete the markers and commit?

You can, but you should not. Deleting the markers keeps both versions stacked in the file. That often breaks the build. Choose the right code first, then delete the marker lines.

### How do I list every file that has a conflict?

Run git status and look under Unmerged paths. For a precise list, run git ls-files -u. Each conflicted file appears with its index stages. Run it again after each fix to see what remains.

### What is the difference between git merge --abort and git merge --quit?

Abort restores the state from before the merge. Quit forgets the merge but keeps the index and working tree as they are. Use abort when you want a clean start. Use quit only when you know what is already staged.

### Is -X theirs safe for a whole merge?

Not without a check. It picks the incoming side for each conflicting hunk, so a useful change can disappear without a warning. Use it only when you know the other side should win, and review the diff afterward.

### Does Lazur resolve merge conflicts for me?

No. Lazur does not click buttons, edit files, or run Git. It can explain what the markers mean, point at the next conflict on screen, and guide you one click at a time. You make every choice.

### Which Git version should I use?

The git-merge manual documents Git 2.54.0 and says its steps still apply through 2.56.0. Run git --version in Terminal to see what you have installed.

## Sources

1. [BLS Occupational Outlook Handbook: Software Developers](https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm), U.S. Bureau of Labor Statistics, checked 2026-11-07
2. [AI Agent Pull Requests on GitHub: Frequency, Structure, and Merge Conflict Rates](https://arxiv.org/html/2607.04697), arXiv (preprint), checked 2026-11-07
3. [Git documentation: git-merge](https://git-scm.com/docs/git-merge), Git project, checked 2026-11-07
4. [GitHub Docs: Resolving a merge conflict on GitHub](https://docs.github.com/en/pull-requests/how-tos/merge-and-close-pull-requests/resolving-a-merge-conflict-on-github), GitHub, checked 2026-11-07
5. [VS Code docs: Merge conflicts](https://code.visualstudio.com/docs/sourcecontrol/merge-conflicts), Microsoft (Visual Studio Code), checked 2026-11-07
6. [Apple Developer Forums: Merge Project File Conflicts](https://developer.apple.com/forums/thread/98535), Apple Developer Forums, checked 2026-11-07
