13

I rebased to master on my local branch. Meanwhile someone did changes on this branch on remote. I am doing git pull --rebase. I don't understand how git interprets this command when it comes to the naming of current and incoming, as well as ours and theirs.

Which should I choose to always keep my local changes? Also, after my first rebase with master, there are dozens of conflicts. Is there a command to make git pull --rebase just keep all my local changes, instead of having to do it manually? I know about ours and theirs, but I don't know how to incorporate those keywords in git pull --rebase command.

This stuff is confusing as hell, since all those keywords get reversed between merge and rebase, and then there is pull with rebase to add extra confusion.

1
  • 4
    For git pull --rebase, to keep "my" changes, use git pull --rebase -Xtheirs. For git pull without --rebase, to keep "my" changes, use git pull -Xours.
    – ElpieKay
    Commented Aug 27, 2020 at 8:43

1 Answer 1

37

The command to favor the changes in your local branch is:

git pull --rebase -X theirs

The reason why you have to say "theirs" when, intuitively, you'd like to say "ours" is because the meaning of "ours" and "theirs" is swapped during a rebase compared to a merge. Let me explain.

Ours and Theirs in a Merge vs. Rebase

When you do a merge, you're always merging into the current branch; in case of a conflict, "ours" means the branch you're on, while "theirs" means the branch you're merging. Exactly as you would expect.

A rebase is different. Let's say that you're rebasing a branch called local onto master.

        master
        ⌄
o---o---o
    \
     A---B---C ‹ local

During a rebase, Git creates a sort of "temporary branch" to do the work1. It starts by moving HEAD to the tip of the branch you're rebasing onto, in this case master:

        master
        ⌄   
o---o---o ‹ HEAD
    \
     A---B---C ‹ local

Then, it cherry-picks the commits from local one at a time:

        master
        ⌄   
o---o---o---A'---B' ‹ HEAD
    \
     A---B---C ‹ local

Now, let's image that commit C has a conflict:

        master
        ⌄             X
o---o---o---A'---B'---C' ‹ HEAD
    \
     A---B---C ‹ local

In this case, "ours" indicates the temporary branch Git is working on, while "theirs" is the branch from which the commit was cherry-picked, which is local.

If you wanted to keep the changes in your local branch, you'd have to choose the "theirs" side. If, instead, you wanted to keep the changes in master, you'd choose the "ours" side.

Once the conflict has been resolved, Git completes the rebase operation by moving local to point to where HEAD is:

        master
        ⌄             
o---o---o---A'---B'---C' ‹ HEAD, local
    \
     A---B---C

Given that no branch is left referencing commit C, those commits become unreachable and will eventually be deleted:

        master
        ⌄             
o---o---o---A'---B'---C' ‹ HEAD, local

1 It's really just a detached head, but for the purpose of this explanation, you can think of it as a temporary branch, even though no branch reference is being created.

Not the answer you're looking for? Browse other questions tagged or ask your own question.