[git] What is the precise meaning of "ours" and "theirs" in git?

This might sound like too basic of a question, but I have searched for answers and I am more confused now than before.

What does "ours" and "theirs" mean in git when merging my branch into my other branch? Both branches are "ours".

In a merge conflict is "ours" always the upper of the two versions displayed?

Does "ours" always refer to the branch that HEAD was pointing to when the merge began? If so then why not use a clear possessive reference like "current branch's" instead of using a possessive pronoun like "ours" that is referentially ambiguous (since both branches are technically ours)?

Or just use the branch name (instead of saying "ours" just say "local master's" or such)?

The most confusing part to me is if I specify in a specific branch's .gitattributes file. Lets say in test branch I have the following .gitattributes file:

config.xml merge=ours

Now I checkout and point HEAD to master then merge in test. Since master is ours, and test's .gitattributes is not checked out, will it even have an effect? If it does have an effect, since master is now "ours", then what will happen?

This question is related to git merge

The answer is


There is no precise meaning, precisely because these terms mean the opposite things depending on whether you are merging or rebasing. THE natural way of thinking about two branches is "my work" and "someone else's work". The choice of terminology that obscures this classification is absolutely THE worst design choice in git. It must have been inspired by accounting's "credit" and "debit" or "assets" and "liabilities" - same headache.


I'll post my memo here, because I have to come back here again and again.

SCENARIO 1. Normal developer: You are developer who can't merge to master and have to play with feature branches only.

Case 1: master is a king. You want to refresh your feature branch (= rebase to master), because master contains new updates of dependencies and you want to overwrite your modest changes.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Case 2: you are a king. You want to rebase your feature branch to master changes. But you did more than your colleagues had and want to use your own changes in a priority.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

IMPORTANT: As you can see normal developers should prefer rebase and repeat it every morning like exercises/coffee.

SCENARIO 2. Merging-sensei: You are a team-lead and want to merge other branches and push a merged result directly to a master. master is a branch you will change.

Case 1: master is a king You want to merge third-party branch, but master is a priority. feature is a branch that your senior did.

git checkout feature
git pull

git checkout master
git merge -X ours feature

Case 2: new changes is a king When your senior developer released a cool feature and you want to overwrite the old s**t in the master branch.

git checkout feature
git pull

git checkout master
git merge -X theirs feature

REMEMBER: To remember in a midnight which one to choose: master is ours ALWAYS. And theirs is a feature that theirs have done.


Just to clarify -- as noted above when rebasing the sense is reversed, so if you see

<<<<<<< HEAD
        foo = 12;
=======
        foo = 22;
>>>>>>> [your commit message]

Resolve using 'mine' -> foo = 12

Resolve using 'theirs' -> foo = 22


I know it doesn't explain the meaning but I've made myself a little image, as reference to remind which one to use:

enter image description here

Hope it helps!

PS - Give a check also to the link in Nitay's answer


I know this has been answered, but this issue confused me so many times I've put up a small reference website to help me remember: https://nitaym.github.io/ourstheirs/

Here are the basics:

Merges:

$ git checkout master 
$ git merge feature

If you want to select the version in master:

$ git checkout --ours codefile.js

If you want to select the version in feature:

$ git checkout --theirs codefile.js

Rebases:

$ git checkout feature 
$ git rebase master 

If you want to select the version in master:

$ git checkout --ours codefile.js

If you want to select the version in feature:

$ git checkout --theirs codefile.js

(This is for complete files, of course)


  • Ours: This is the branch you are currently on.
  • Theirs: This is the other branch that is used in your action.

So if you are on branch release/2.5 and you merge branch feature/new-buttons into it, then the content as found in release/2.5 is what ours refers to and the content as found on feature/new-buttons is what theirs refers to. During a merge action this is pretty straight forward.

The only problem most people fall for is the rebase case. If you do a re-base instead of a normal merge, the roles are swapped. How's that? Well, that's caused solely by the way rebasing works. Think of rebase to work like that:

  1. All commits you have done since your last pull are moved to a branch of their own, let's name it BranchX.
  2. You checkout the head of your current branch, discarding any local changes you had but that way retrieving all changes others have pushed for that branch.
  3. Now every commit on BranchX is cherry-picked in order old to new to your current branch.
  4. BranchX is deleted again and thus won't ever show up in any history.

Of course, that's not really what is going on but it's a nice mind model for me. And if you look at 2 and 3, you will understand why the roles are swapped now. As of 2, your current branch is now the branch from the server without any of your changes, so this is ours (the branch you are on). The changes you made are now on a different branch that is not your current one (BranchX) and thus these changes (despite being the changes you made) are theirs (the other branch used in your action).

That means if you merge and you want your changes to always win, you'd tell git to always choose "ours" but if you rebase and you want all your changes to always win, you tell git to always choose "theirs".


The 'ours' in Git is referring to the original working branch which has authoritative/canonical part of git history.

The 'theirs' refers to the version that holds the work in order to be rebased (changes to be replayed onto the current branch).

This may appear to be swapped to people who are not aware that doing rebasing (e.g. git rebase) is actually taking your work on hold (which is theirs) in order to replay onto the canonical/main history which is ours, because we're rebasing our changes as third-party work.

The documentation for git-checkout was further clarified in Git >=2.5.1 as per f303016 commit:

--ours --theirs

When checking out paths from the index, check out stage #2 ('ours') or #3 ('theirs') for unmerged paths.

Note that during git rebase and git pull --rebase, 'ours' and 'theirs' may appear swapped; --ours gives the version from the branch the changes are rebased onto, while --theirs gives the version from the branch that holds your work that is being rebased.

This is because rebase is used in a workflow that treats the history at the remote as the shared canonical one, and treats the work done on the branch you are rebasing as the third-party work to be integrated, and you are temporarily assuming the role of the keeper of the canonical history during the rebase. As the keeper of the canonical history, you need to view the history from the remote as ours (i.e. "our shared canonical history"), while what you did on your side branch as theirs (i.e. "one contributor's work on top of it").

For git-merge it's explain in the following way:

ours

This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected to the merge result. For a binary file, the entire contents are taken from our side.

This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it.

theirs

This is the opposite of ours.

Further more, here is explained how to use them:

The merge mechanism (git merge and git pull commands) allows the backend merge strategies to be chosen with -s option. Some strategies can also take their own options, which can be passed by giving -X<option> arguments to git merge and/or git pull.


So sometimes it can be confusing, for example:

  • git pull origin master where -Xours is our local, -Xtheirs is theirs (remote) branch
  • git pull origin master -r where -Xours is theirs (remote), -Xtheirs is ours

So the 2nd example is opposite to the 1st one, because we're rebasing our branch on top of the remote one, so our starting point is remote one, and our changes are treated as external.

Similar for git merge strategies (-X ours and -X theirs).


From git checkout's usage:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

When resolving merge conflicts, you can do git checkout --theirs some_file, and git checkout --ours some_file to reset the file to the current version and the incoming versions respectively.

If you've done git checkout --ours some_file or git checkout --theirs some_file and would like to reset the file to the 3-way merge version of the file, you can do git checkout --merge some_file.