Git: Handling Merge Conflicts Using "Ours" and "Theirs"

Nothing is certain, except death and taxes and merge conflicts. -Benjamin Franklin
  • by Tyler (250)
  • Time to complete: 3 minutes

If you've arrived on this page, you're probably in the middle of a merge conflict as we speak. To fix conflicts, we often have to open the file and manually sort out each conflicts, but sometimes we're lucky and we can keep one version and throw out the other entirely. To do this, we can use git checkout with one of two flags: --ours or --theirs.

Convenient, right? Maybe not.

The usage of --ours and --their might be a little confusing at first, so lets dive in and learn by example.

tl;dr

With feature branch checked out.

git merge mastergit rebase master
Keep changes from master--theirs--ours
Keep changes from feature--ours--theirs

Continue reading for an explanation.

1

Technically speaking, use of git checkout --ours/--theirs is only applicable during a merge. You might be wondering about rebases, and I'll explain that in the next step.

For simplicity, let's start with a basic merge conflict. Imagine our git history looks like this:

          A---B---C feature
         /
    D---E---F---G master

The letters signify a commit, and each commit includes changes to our file: myscript.py.

So changes were made to myscript.py in both master and feature branches. A common strategy is to routinely merge changes from master into your feature branch during development to keep the feature branch from getting too far out of date. But when we go to merge master into feature, we're going to run into trouble:

(feature) $ git merge master
Auto-merging myscript.py
CONFLICT (content): Merge conflict in myscript.py
Automatic merge failed; fix conflicts and then commit the result.

In most cases, you'd want to open myscript.py and sort out the merge conflicts. But in some cases, you'll want to completely disregard one version and keep the other. This is where git checkout --ours/--theirs comes into play.

Use --ours keep the version in the current branch

Since we have our feature branch checked out, we can use --ours to keep the version of myscript.py that resides in the feature branch, and disregard the version from master.

git checkout --ours myscript.py

Use --theirs to keep the version from the branch being merged in

And --theirs accomplishes the opposite. If we want to discard the version of myscript.py that resides in our current branch and keep the version from master, we can use --theirs.

git checkout --theirs myscript.py
2

When we run into merge conflicts during a rebase, we are effectively in the middle of a merge, so the rules for git checkout --ours/--theirs from above still apply. But, the tricky part is identifying the "current" branch. Let me explain what happens during a rebase.

What happens during a rebase?

Again, let's assume the following history:

          A---B---C feature
         /
    D---E---F---G master

When we rebase master "into" feature, what we are really doing is this:

"Roll back" to the common ancestor and save the diff

In our case, we roll back to commit E, and save the diff of each commit introduce by the feature branch.

    A---B---C (saved in temporary files)

           feature         
         /
    D---E---F---G master
Reset the feature branch to the current commit from master

The feature branch now has the same history as master.

    A---B---C (saved in temporary files)

                   feature         
                 /
    D---E---F---G master
Apply the saved changes from the feature branch

Now each change from the feature branch (A, B, and C) will be applied to the new feature branch once again. It's important to note, for the sake of this guide, that this is accomplished through a merge.

The new history looks like this:

                   A---B---C feature
                 /
    D---E---F---G master

Ok, so how do I use git checkout --ours/--theirs during a rebase?

The point of that long winded explanation was to show that when you are fixing merge conflicts in the middle of a rebase, your "current" branch is not longer your original feature branch but rather a new branch that is up to date with master. And the commits being merge into the current branch are the commits from your original feature branch. So --ours and --theirs will appear to be flipped around.

Use --ours to keep changes from the branch being rebased onto (master)

At the beginning of the rebase, we had feature branch checked out, so it may seem backward, but we will use --ours to keep changes from master.

git checkout --ours myscript.py

Use --theirs to keep the changes from the "current" branch (feature)

And naturally, the opposite is true. Use --theirs to keep changes from the feature branch.

git checkout --theirs myscript.py
3

I know this can be confusing, so please let me know in the comments below if you thought this guide was helpful or if you could use further clarification!