skip to content

In a conflicted Git merge, what does git checkout --ours path/to/file actually do?

level: middleimportance: should knowfreq 40%

answer

  1. The versions come from the index, not from disk
  2. Granularity is the catch
  3. Non-conflicting edits by the other side vanish
  4. It is not the last step
  5. The markers can be regenerated afterwards

basics

~20 s

It replaces the whole working-tree file with the version from your side of the merge, taken from the index. It is file-level, not hunk-level: every change the other side made to that file is discarded, and you still have to stage the file.

solid answer

~50 s

During a conflict the index holds three versions of the path — base at stage 1, ours at stage 2, theirs at stage 3. `git checkout --ours <file>` writes stage 2 over the working-tree file; `--theirs` writes stage 3. The critical property is granularity: this is a **whole-file** choice, not a per-hunk one. If the other side also made ten unrelated, non-conflicting edits to that file, `--ours` throws all of them away silently — Git will not warn you, and the merge result may quietly lose work. It also does not resolve anything by itself: the path stays unmerged until you `git add` it. `git restore --ours <file>` is the modern spelling. If you decide you took the wrong side, `git checkout -m <file>` regenerates the conflict markers from the same index stages so you can resolve properly.

go deeper

for a junior

Know that this takes one whole version of the file and that you still have to stage it afterwards. Treat it as a blunt tool rather than a shortcut through a conflict.

for a middle

Explain the index stages it reads from, why the whole-file granularity silently drops the other side's clean changes, and how to regenerate the markers if you picked wrong.

for a senior

Show judgement about when a whole-side take is correct — binary or generated files — versus when it is a quiet data-loss event, and how you would notice the loss before it ships.

for a principal

Frame it as a class of silent-loss operation: decide which file categories should be resolved wholesale by convention, and how the repo makes that safe rather than relying on each engineer's care.

## Where the two versions come from A conflicted path is not stored once in the index; it is stored up to three times. Stage 1 is the merge base, stage 2 is *ours*, stage 3 is *theirs*. `git ls-files -u <file>` prints those entries. The side selectors are simply a way to copy one of those stages into the working tree: `git checkout --ours <file>` writes stage 2, `git checkout --theirs <file>` writes stage 3. The modern equivalents are `git restore --ours <file>` and `git restore --theirs <file>`. ## The granularity trap The reason this command deserves an interview question is that people reach for it expecting hunk-level behaviour and get file-level behaviour. Consider a file where both sides edited the same function — the actual conflict — while the other side *also* added three new functions elsewhere in the file that merged cleanly. Choosing `--ours` does not keep the clean parts and resolve only the disputed hunk; it discards the entire other-side version of the file, new functions included. Nothing warns you. The merge commit looks legitimate, the build may even pass, and the lost code surfaces days later as a mysterious regression. This is why the safe default is to edit the conflict hunks by hand, or open a merge tool, and reserve the side selectors for cases where taking a whole file is genuinely what you mean: a generated file, a lock file you intend to regenerate, a vendored artifact, or a file one side rewrote wholesale. ## It does not resolve the path Copying a stage into the working tree changes only the working tree. The index still has the path at stages 1, 2 and 3, so `git status` still lists it as unmerged and `git commit` still refuses. You must `git add <file>` to collapse the stages into a single stage-0 entry. Forgetting this leads to the confusing situation where the file *looks* fine and Git still insists the merge is incomplete. ## Undoing a wrong choice Because all three versions remain in the index until you stage, a bad choice is fully reversible. Run the other selector to take the opposite side, or `git checkout -m <file>` (also spelled `git restore --merge <file>`) to regenerate the conflict markers and resolve properly. After you have staged the path, those stages are gone; from there recovery means `git merge --abort` (or `git rebase --abort`) and starting the merge again. ## The rebase inversion The selectors name positions, not branches, so during a rebase they follow the checked-out side: `--ours` yields the upstream base and `--theirs` yields the commit being replayed from your own branch. Using them mid-rebase without thinking is a reliable way to discard exactly the work you were trying to preserve. ## Marker-free conflicts When a path is *deleted by us* or *deleted by them*, one of the stages simply does not exist, so the side selectors are not the right tool — resolve with `git rm <file>` or `git add <file>` to record deletion or retention. For binary files the selectors are often exactly right, since a line-wise resolution is impossible and taking one whole version is the only meaningful outcome. ## Command shape One practical note: these forms operate on paths, and the paths must be unmerged. Running the selector on a path with no conflict does nothing useful. And they take paths explicitly — resolving a directory's worth of conflicts by taking one side wholesale is a decision worth making file by file, because the granularity trap scales with the number of files you sweep. ## What good answers include A strong answer says three things: the versions come out of the index stages, the choice is whole-file so non-conflicting changes from the other side are lost, and staging is still required afterwards. Adding that the labels invert under rebase, and that `git checkout -m` restores the markers if you change your mind, shows the candidate has actually used it rather than read about it.

  • You ran the wrong side selector on a file. Can you undo it without aborting the merge?
    Yes, as long as you have not staged the path. All three versions are still in the index, so you can run the opposite selector, or `git checkout -m <file>` to regenerate the conflict markers and resolve by hand. Once `git add` collapses the stages, only aborting the merge restores the choice.
  • When is taking a whole side genuinely the right resolution?
    When the file has no meaningful line-level merge: binary assets, generated files, lock files you intend to regenerate afterwards, or a file one side rewrote wholesale. In those cases hunk-level resolution produces nonsense, and choosing a whole version — then regenerating if needed — is the correct outcome.

saying these in an interview costs you the question

  • Thinks it keeps our hunks and their non-conflicting hunks
  • Believes it marks the file resolved on its own
  • Assumes ours means the feature branch during a rebase
  • Applies it across many files to clear conflicts fast
  • Cannot say where the two versions are stored

context