为什么当前分支在变基时没有移动?

Why current branch is not moved while rebasing?

我目前在 dev 分支上并且在 local/dev 分支上有一些变化。

...

我做了变基:

$ git rebase dev local/dev
Created autostash: 92915886
Applied autostash.
Successfully rebased and updated detached HEAD.

提交已变基,但 dev 指针未更新:

阅读man git rebase

All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area

**这是在第二张图片

上标记为>的提交

The current branch is reset to <upstream> ...

** upstreamdev。所以我现在在dev

The commits are then reapplied to the current branch

** 提交重新应用于 dev

为什么 dev 指针没有用 HEAD 移动到顶部?

我是否应该应用一些选项将我当前的 dev 移动到 HEAD 的顶部?

更新
这是非常非常有策略的。当 devlocal/dev 不同的衬里并且可以快速转发时,然后我的 dev 被移到顶部,因为我期望工作。没有任何额外的

git branch -f dev
git checkout dev

变基之前的历史情况: 以及变基后如何:

local/dev 是远程分支。它不会因为你想改变它而移动。它将在 detached HEAD 完成,然后由您推入 local/dev

git push local -f HEAD:dev

您也可以将dev移动到HEAD然后结帐:

git branch -f dev
git checkout dev

我找不到将 dev 分支自动移动到 HEAD 的选项。

但在变基后我可以返回到 dev 并快进到 c1692f:

$ git checkout dev
$ git merge --ff-only c1692f

结果如下:

为什么 dev 指针没有用 HEAD 移动到顶部? -- 因为它是 而不是 变基期间的当前分支。

仔细阅读documentation of git rebase。它在第一段中解释:

git rebase [-i | --interactive] [<options>] [--exec <cmd>]
        [--onto <newbase> | --keep-base] [<upstream> [<branch>]]`

If <branch> is specified, git rebase will perform an automatic git switch <branch> before doing anything else. Otherwise it remains on the current branch.

用简单的英语来说,如果使用两个分支(<upstream><branch>)调用 git rebase,它首先切换到第二个分支,然后将其重新定位到第一个分支的顶部.*

这意味着:

git rebase dev local/dev

是以下的快捷方式:

git switch local/dev
git rebase dev

变基期间的当前分支是local/dev;它是唯一受变基影响的分支。


* <upstream> 不需要是分支。任何标识提交的引用(分支、标记、提交、HEADHEAD^2HEAD@{1} 等)都可以用作 <upstream>.

另一方面,

<branch> 需要成为一个分支,因为作为 rebase 的结果,它将移动到不同的提交。


更新

您对文档的解释不正确。你在问题中说:

The current branch is reset to <upstream> ...

** upstream is dev. So I am on dev at this point

该点的当前分支不一定是 dev(事实上,如上所述,它是 local/dev)。

“当前分支重置为<upstream>并不是说<upstream>成为当前分支而是当前分支(local/dev) 被移动到由 <upstream> 标识的提交中。 Git 此时所做的相当于 git reset --hard <upstream>.


更新#2

上面的分析忽略了local/dev是远程分支这一事实。我一开始没注意到。
命名遥控器有什么意义 local?这是误导。

因为 local/dev 不是本地分支,git switch local/dev 使回购处于 detached HEAD 状态。 rebase 的其余部分按照文档中的描述发生,但最后你有一个新的历史行并且没有指向它的分支(HEAD 除外)。如果你切换分支,rebase 的结果将丢失。

有两种方法可以解决问题:

  • 在当前提交上移动分支 dev。有几种方法可以做到这一点,但最简单的方法是使用 git branch -f dev.

  • 放弃更改,切换到 dev 分支并正确进行变基:

    git switch dev
    git rebase local/dev
    

真正的解决方案

总而言之,整个情况的出现是因为你在命令行中把分支的顺序放错了。应该是:

git rebase local/dev dev

这会检查 dev 分支,然后将可从 dev 访问但无法从 local/dev 访问的提交移到 local/dev 之上,同时保留 dev 在移动的提交之上分支。快速浏览一下,分支 dev 似乎是从分支 local/dev 的分叉处剪下的,然后该片段被嫁接在 local/dev.

之上

如果您想移动 dev 以获取应用于 local/dev 的修订,您可以这样做:

git checkout dev
git cherry-pick $( git merge-base HEAD local/dev )..local/dev

应该可以