I faced this issue for many times, so I want to share with you to get what's wrong with my approach.
I have two branches in the remote repository, dev
and master
. dev
was originated from the master
and have got 2 new commits. (which is common)
Now I wanted to update remote dev
branch with a few more commits and make a merge request to update the remote master
branch eventually.
So I did the following
dev
. e.g: git fetch & git checkout dev
dev
, in the meanwhile remote master
was updated by another team mate and it has 3 new commitsmaster
and pulled the latest origin master
. e.g: git checkout master & git pull origin master
dev
against the local master
.
e.g: git rebase master dev
dev
to the remote dev
. e.g: git push origin dev
But it gave me an error
Updates were rejected because the tip of your current branch is behind its remote counterpart.
Even though git push -f
will work, as far as I understood, my local dev
was originated from the remote dev
and has new commits, so it can't be behind the remote one.
my local dev was originated from the remote dev and has new commits, so it can't be behind the remote one.
Yes it can and it is, in the sense that Git means it.
After the pull, I rebased the local dev against the local master. e.g: git rebase master dev
That's the reason. Rebasing changes history. Simply, it replaces the rebased commits with new ones. You cannot move a commit, ever, not with rebase or anything else; you can only copy the commit as a different commit. It may have the same commit message but that's just part of what was copied.
Do you see? No? Okay, let's start before your step 1, where dev split off from master and had two new commits. Call those commits A and B. It was like that on the remote, and (1) you fetched and checked out that, so it was like that on your local dev too: your dev has the same A and B since the split from master.
(Now ignore everything else you did locally with dev...)
Then (2) master grew and (3) you pulled it and (4) rebased dev onto it. That replaced your A and B with new commits; call them AA and BB.
Now (5) you try to push dev. But the remote dev still has the old A and B. And your local dev doesn't! So the remote dev has commits that you don't have in your local dev, and the push is rejected. You cannot push without force unless your history is a continuation of the remote's history — and it isn't.