Why dev
pointer is not moved to top with HEAD
? — because it is not the current branch during the rebase.
Read the documentation of git rebase
carefully. It explains in the first paragraph:
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase> | --keep-base] [<upstream> [<branch>]]`
If
<branch>
is specified,git rebase
will perform an automaticgit switch <branch>
before doing anything else. Otherwise it remains on the current branch.
In plain English, if git rebase
is invoked with two branches (<upstream>
and <branch>
), it first switches to the second branch then rebase it on top of the first branch.*
This means that:
git rebase dev local/dev
is a shortcut for:
git switch local/dev
git rebase dev
The current branch during the rebase is local/dev
; it is the only branch that is affected by the rebase.
* <upstream>
does not need to be a branch. Any reference that identifies a commit (branch, tag, commit, HEAD
, HEAD^2
, [email protected]{1}
etc) can be used as <upstream>
.
<branch>
, on the other hand, needs to be a branch because, as a result of the rebase, it will move to a different commit.
Update
You interpret the documentation incorrectly. You say in the question:
The current branch is reset to
<upstream>
…** upstream is dev. So I am on dev at this point
The current branch on that point is not necessarily dev
(it is, in fact, local/dev
as explained above).
“The current branch is reset to <upstream>
“ does not mean that <upstream>
becomes the current branch but that the current branch (local/dev
) is moved to the commit identified by <upstream>
. What Git does at this point is equivalent to git reset --hard <upstream>
.
Update #2
The analysis above ignores the fact that local/dev
is a remote branch. I didn’t notice that initially.
What’s the point of naming a remote local
? It is misleading.
Because local/dev
is not a local branch, git switch local/dev
brings the repo in a detached HEAD
state. The rest of the rebase happens as described in the documentation but in the end you have a new history line and no branch that points to it (except for HEAD
). If you switch the branch the result of the rebase is lost.
There are two ways to fix the things:
Move the branch
dev
on the current commit. There are several ways to do this but the easiest way is to usegit branch -f dev
.Abandon the changes, switch to the
dev
branch and do the rebase correctly:git switch dev git rebase local/dev
The real solution
All in all, the entire situation appeared because you put the branches in the incorrect order in the command line. It should be:
git rebase local/dev dev
This checks out the dev
branch then moves the commits accessible from dev
and not accessible from local/dev
on top of local/dev
while it preserves the dev
branch on top of the moved commits. On a quick glance it looks like the branch dev
is cut from where it forks from branch local/dev
and the piece is then grafted on top of local/dev
.
CLICK HERE to find out more related problems solutions.