Git切换分支状态异常:为何需用-b参数重复指定分支?
场景还原
执行git branch -a输出如下:
* master remotes/origin/HEAD -> origin/master remotes/origin/feature remotes/origin/master remotes/origin/origin/feature
分支结构:
--> F --> G origin/feature / A --> B --> C --> D --> E master
遇到的问题:
- 不清楚为何同时存在
remotes/origin/feature和remotes/origin/origin/feature - 执行
git checkout 'origin/feature'后文件处于节点B的状态,而非G - 执行GitLab GUI提示的
git checkout -b 'origin/feature' 'origin/feature'后,文件才处于节点G的状态,疑惑为何明明分支已存在还需用-b并重复指定分支
问题解答
1. 为什么会出现两个类似的远程分支?
这是团队成员的误操作导致的命名混乱。Git的远程跟踪分支命名规则是remotes/<远程仓库名>/<远程分支名>,所以:
remotes/origin/feature对应远程仓库中名为feature的分支remotes/origin/origin/feature对应远程仓库中名为origin/feature的分支
大概率是有人在推送分支时,错误地将本地分支命名为origin/feature并推送到了远程仓库,导致远程多了一个奇怪命名的分支;或是在远程仓库手动创建分支时误写了名字。
2. 为什么git checkout 'origin/feature'会停在节点B?
你执行的这个命令,实际切换到的是本地缓存的remotes/origin/feature远程跟踪分支,而这个分支的指针还停留在节点B——可能是很久没拉取更新,或是这个远程分支本身就没有同步到G节点的提交。
真正指向G节点的是remotes/origin/origin/feature这个远程跟踪分支,只是你没指定正确的分支名。
3. 为什么GUI生成的-b命令能切换到G节点?
这个命令的本质是创建一个新的本地分支origin/feature,并基于指定的远程分支初始化。这里的第二个origin/feature,Git实际解析的是remotes/origin/origin/feature(因为本地没有名为origin/feature的分支,Git会自动匹配远程跟踪分支)。
之所以要加-b,是因为你之前没有本地的origin/feature分支——之前看到的remotes/origin/feature是远程跟踪分支,不是本地可直接切换的分支;重复指定分支名是GUI的简化写法,实际等价于:
git checkout -b origin/feature remotes/origin/origin/feature
切换目标分支并合并到master的正确步骤
- 先拉取最新的远程分支信息:
git fetch origin
- 创建本地分支跟踪
remotes/origin/origin/feature:
git checkout -b feature-from-origin origin/origin/feature
(这里把本地分支命名为feature-from-origin避免混淆,你也可以用其他名字)
3. 切换到master分支并合并:
git checkout master git merge feature-from-origin
- 确认无误后推送到远程master:
git push origin master
内容的提问来源于stack exchange,提问作者flappix

