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.
The reason for error messages like these is rather simple: you have local changes that would be overwritten by the incoming new changes that a "git pull" would bring in. For obvious safety reasons, Git will never simply overwrite your changes.
Git pull rebase is a method of combining your local unpublished changes with the latest published changes on your remote. Let's say you have a local copy of your project's main branch with unpublished changes, and that branch is one commit behind the origin/main branch.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With