skip to content

In Git, what do the <<<<<<<, =======, and >>>>>>> markers in a conflicted file mean?

level: juniorimportance: must knowfreq 85%

answer

  1. Two candidate versions, inline in the file
  2. Seven-character lines at column one
  3. The label after the opener names your side
  4. Staging is what resolves it
  5. git status lists unmerged paths

basics

~20 s

Git writes both versions of a region it could not merge into the file. Text between <<<<<<< and ======= is the side you are on; text between ======= and >>>>>>> is the incoming side. You edit the file to the final content, delete the markers, and stage it.

solid answer

~50 s

When both sides changed the same region of a file differently, Git cannot pick a winner, so it writes a **conflict hunk** into the working-tree file. The `<<<<<<<` line opens it and carries a label for your current side (usually `HEAD`); `=======` separates the two versions; `>>>>>>>` closes it with a label for the incoming commit or branch. Regions only one side touched are merged silently, so a conflicted file usually contains mostly normal content with a few marked hunks. Meanwhile Git records the path as unmerged in the index, holding three stages: base, ours, theirs — `git status` lists it under *Unmerged paths* as *both modified*. Resolution means editing the file to the content you actually want, removing all three marker lines, then `git add <file>` and finishing with `git commit` or `git rebase --continue`.

go deeper

for a junior

Be able to read a conflict hunk aloud: which half is your branch, which is incoming, and that both are candidates rather than one being right. Then show the resolve-edit-add-commit loop without hesitating.

for a middle

Explain the index side of a conflict — stages 1, 2 and 3, why plain commit refuses, and why staging is the only thing that marks a path resolved. Mention delete/modify and binary conflicts as marker-free cases.

for a senior

Show that you treat resolution as a code change: build and test afterwards, watch for semantic conflicts that merge cleanly but break behaviour, and guard against committed markers with a repeatable check rather than discipline.

for a principal

Frame conflicts as a signal about how work is partitioned. Be ready to discuss where repeated conflict hotspots point at file or ownership structure, and what guardrails belong in the repo versus in individual habits.

## What a conflict actually is A merge in Git is a three-way operation: for each file it compares your side and the incoming side against their **common ancestor** (the merge base). Region by region, if only one side changed a region, Git takes that side without asking. If both sides changed the *same* region to *different* content, Git has no rule that decides which is correct, so it stops and hands the decision to you. That handover has two halves: markers written into the working-tree file, and an unmerged entry in the index. ## Anatomy of a conflict hunk Inside the file, each unresolvable region is wrapped in three marker lines, each seven characters long and starting at column one: - `<<<<<<<` followed by a label for **your** side. During a merge on a branch this is normally `HEAD`. - `=======` — the divider between the two candidate versions. - `>>>>>>>` followed by a label for the **incoming** side — a branch name, or a commit hash and subject. Everything between the opener and the divider is your version of that region; everything between the divider and the closer is theirs. A file can contain many such hunks, and the untouched parts of the file around them are already merged. Note that the markers are plain text: they are not a special file format, and nothing in Git prevents you from committing them by accident. ## The index during a conflict Normally each path sits at **stage 0** in the index — one resolved entry. A conflicted path instead occupies up to three stages: stage 1 is the merge-base version, stage 2 is *ours*, stage 3 is *theirs*. `git ls-files -u` prints them, and `git status` shows the path under *Unmerged paths*, usually as *both modified*. This is why a plain `git commit` refuses to run while a conflict is outstanding — the index is not in a committable shape. Staging the file with `git add` is what actually resolves it: the three stage entries collapse into a single stage-0 entry holding whatever bytes are in the working tree at that moment. Git does not inspect those bytes, which has a direct consequence covered below. ## Finishing the resolution The loop is always the same: 1. Open each conflicted file and edit the region to the content you intend to ship — which is frequently neither side verbatim but a combination. 2. Delete all three marker lines. 3. `git add <file>` for each resolved path. 4. `git commit` to complete a merge (the message is pre-filled from `.git/MERGE_MSG`), or `git rebase --continue` if the conflict arose during a rebase. `git status` remains the checklist: it keeps listing unmerged paths until every one is staged. ## What Git will not do for you Git never validates your resolution. If you stage a file that still contains `<<<<<<<`, Git commits it happily — this is one of the most common self-inflicted breakages, and it is why teams grep for marker lines before committing or wire that check into a client-side hook. Git also cannot see **semantic** conflicts: two sides can touch different regions, merge with zero markers, and still produce code that does not compile or behave correctly (one side renames a function, the other adds a call to the old name). Building and running the tests after resolving is part of the resolution, not an optional extra. ## Conflicts without markers Not every conflict produces markers. If one side deleted a file and the other modified it, `git status` reports *deleted by us* or *deleted by them*, and you resolve by choosing `git rm` or `git add`. Binary files cannot be merged line-wise, so Git leaves one version in place and asks you to pick a whole file. Both are still unmerged index entries, and both still finish with `git add`. ## Aborting instead Markers are not a trap you must fight through. Until you commit, the pre-merge state is recoverable — `git merge --abort` (or `git rebase --abort`) puts you back where you started. Recognising that early is the difference between a two-minute detour and a mangled working tree.

  • How does Git know a file is still conflicted if the markers are just text?
    It does not use the text. The index holds the path at stages 1, 2 and 3 (base, ours, theirs) instead of stage 0, and `git status` reports it as unmerged. `git add` collapses those stages to a single stage-0 entry, which is what marks it resolved — regardless of what the bytes actually contain.
  • What happens if you commit a file that still has conflict markers in it?
    Git commits it without complaint, because staging is the only resolution signal it looks at. The markers become ordinary lines of source and normally break the build. Teams defend against this by grepping for the marker lines in a pre-commit hook and by running the test suite before finishing a merge.
  • Why do some conflicted files show no markers at all?
    Because the conflict is not line-level. Delete-versus-modify conflicts are reported as *deleted by us* or *deleted by them* and are resolved with `git rm` or `git add`. Binary files cannot be merged textually, so Git leaves one version and expects you to choose a whole file. Both are still unmerged index entries.

saying these in an interview costs you the question

  • Thinks the top half is always the correct version
  • Deletes one side wholesale without reading either
  • Believes committing is blocked while markers remain in text
  • Assumes a clean merge means the code still works
  • Cannot say what git add does to a conflicted path

context