Git merge conflict markers (<<<<<<< HEAD, =======, >>>>>>>) explained, and how to resolve them
Git merges most changes by itself. When two branches changed the same lines differently, it stops, writes both versions into the file between marker lines, and asks you to choose. The markers are plain text that you delete once you have decided.
Reading the markers
<<<<<<< HEAD
const timeout = 30;
=======
const timeout = 60;
>>>>>>> feature/slow-network
<<<<<<< HEADstarts your side: the branch you were on when you rangit merge(“ours”).=======separates the two sides.>>>>>>> feature/slow-networkends their side: the branch or commit being merged in (“theirs”).
The right answer might be one side, the other, or a mix of both (perhaps const timeout = 60; plus a comment from your side). Git can’t know; that’s why it asks.
Resolve, step by step
git status # lists "both modified:" files
# edit each file: keep what you want, delete the 3 marker lines
git diff # check what you're about to accept
git add src/config.js # marks that file as resolved
git commit # finishes the merge (message is pre-filled)
Rebasing instead? After git add, run git rebase --continue; git may stop again for the next commit. Cherry-picking: git cherry-pick --continue.
Changed your mind? Back out
git merge --abort # puts everything back as before the merge
git rebase --abort # same for a rebase
git cherry-pick --abort
Ours and theirs flip during a rebase
| Operation | HEAD / “ours” | “theirs” |
|---|---|---|
git merge feature (on main) | main, where you are | feature, coming in |
git rebase main (on feature) | main, plus your commits replayed so far | your feature commit being replayed |
git pull (merge mode) | your local branch | the remote branch |
git stash pop | your current files | the stash (labelled Stashed changes) |
A rebase replays your commits on top of the other branch, so “HEAD” is the other branch and your own work is “theirs”. That’s why git checkout --ours seems backwards during a rebase.
Take one whole side of a file
git checkout --ours path/to/file # keep my version (merge)
git checkout --theirs path/to/file # take the incoming version (merge)
git add path/to/file
Handy for generated files. For lockfiles (package-lock.json, poetry.lock, yarn.lock) don’t hand-edit markers: take either side, then rerun npm install (or your tool’s equivalent) so it regenerates the file from the merged manifest.
See the original too: diff3 and zdiff3
git config --global merge.conflictStyle zdiff3 # git 2.35+; use diff3 on older git
Now conflicts include a third section, ||||||| base, showing what the lines looked like before either branch changed them. Knowing that the original was 30, and only one side changed it, often makes the choice obvious. To compare the two sides at leisure, paste them into the text diff tool.
Markers that slipped into a commit
Leftover markers break things in loud ways: SyntaxError: Unexpected token << in JavaScript, Unexpected token < in JSON, YAML that won’t parse, or a web page showing =======. Find them:
git diff --check # warns about leftover conflict markers in unstaged changes
git diff --cached --check # same, for what you're about to commit
git grep -nE '^(<{7}|={7}|>{7})( |$)' # search the whole repo
A broken JSON or YAML file is quickest to check by pasting it into the JSON formatter or YAML to JSON converter, which point at the line that fails. See also Unexpected token in JSON.
Fewer conflicts next time
- Merge or rebase from main often, so the two sides never drift far apart.
- Keep formatting tools (Prettier, Black) on the same settings for everyone; a reformat touches every line and conflicts with everything.
git config --global rerere.enabled truemakes git remember how you resolved a conflict and replay it if the same conflict comes back (common when rebasing a long branch repeatedly).- Line-ending changes cause whole-file conflicts; see LF will be replaced by CRLF.
Got here from a git pull that complained about divergent branches? Pick a pull strategy first.
Related
local changes would be overwritten by merge · All guides
Questions
What does <<<<<<< HEAD mean in git?
It marks the start of a merge conflict. The lines after it, up to =======, are the version from your current branch (HEAD). The lines after ======= up to >>>>>>> are the incoming version. You choose, delete the marker lines, then git add the file.
How do I finish resolving a merge conflict?
Edit every conflicted file so it has no marker lines left, run git add on each, then git commit to finish a merge, or git rebase --continue during a rebase.
How do I cancel a merge with conflicts?
Run git merge --abort (or git rebase --abort for a rebase). Git returns your branch and working files to how they were before you started.
Why are ours and theirs reversed during a rebase?
A rebase replays your commits on top of the other branch, so HEAD is the other branch and the commit being applied, your own, counts as theirs.
Published .