Git branch has diverged after rebase

来源:互联网 发布:淘宝直播底薪一般多少 编辑:程序博客网 时间:2024/06/05 07:27

背景

最近在使用git的过程中遇到了如下问题:

Your branch and 'origin/xxx' have diverged, and have 8 and 4 different commits each ....

这个问题跟前面说的另外一篇文章: Git - Your branch and ‘origin/xxx’ have diverged有点类似,但又有些不同。

先描述一下这个问题产生的背景:

先说说git仓库模型,如下所示:

upstream   |origin   |local

根上游代码upstream准备新开发一个功能,我的直接上游origin master代码始终跟upstream保持一致,这时候为了开发新的功能,在我的本地新建了一个feature分支,做了一些修改,并提交到我的直接上游origin上:

# 当前分支为master,根据master创建新分支my-featuregit branch my-feature# 进行开发...若干提交# git commit -m "init commit message"# ...git push origin my-feature:my-feature

现在这个功能还没到可以提交PR给root master的阶段,过了一段时间,团队里的其他人请求合并自己开发的功能到根上游的master并通过了。这时候为了保证我直接上游和本地master跟根上游上的master代码始终一致,我需要做以下操作:

git checkout mastergit pull # 这一步只是为了确保本地master跟origin master保持一致git fetch upstreamgit merge --ff upstream/mastergit push origin master # 让origin master 跟 upstream master保持同步

接下来,我应该把master合并到我的开发分支my-feature,以便保证我的开发分支是基于master最新代码之上做修改的,为了保证分支线性,避免merge操作带来额外的commit,我采用了如下命令进行合并:

git checkout my-featuregit rebase master

这时候一切正常,使用git status命令查看状态发现:

git statusOn branch my-featureYour branch and 'origin/my-feature' have diverged,and have 8 and 4 different commits each, respectively.  (use "git pull" to merge the remote branch into yours)nothing to commit, working tree clean

到了这一步,便出现了前面提到的问题。

分析

实际上,rebase命令之所以能够保证分支线性,是因为它会改写(涉及到parent commit的修改)commit。

通常以树的形状来描述git分支和git提交历史,我们可以通过下面这张图,更形象地理解到rebase:

diverged_when_git_rebase_master_on_feature_branch

图片来自stackoverflow: http://stackoverflow.com/questions/19016698/git-branch-diverged-after-rebase

实际上在my-feature分支上进行的git rebase master操作,是将我们在my-feature上的commit,给接到master最后一个commit之后,这些commit跟之前在my-feature上的commit是完全不同的(hash值和指向的parent都不一样了)。因为我本地的my-feature分支跟直接上游origin的my-feature分支之间是建立了track关联的,而在我的origin直接上游上的my-feature分支,由于在rebase之前已经push上去,先前的commit跟rebase后的commit不一致,在track关联中被检测到。所以当前使用git status命令查看,就会发现产生了分叉(diverge)。

解决方法

实际上,在团队开发中应该或多或少会遇到这种情况,那么,出现这种情况该如何解决?翻了一下stackoverflow上的一个问题http://stackoverflow.com/questions/19016698/git-branch-diverged-after-rebase,总结如下:

假设只有你一个人在操作这个分支,那么你可以使用git push -f origin my-feature:my-feature,强制push该分支到origin上;但是,如果该分支有其他人跟你一起协作开发,那么,绝对不要使用-f强行push,事实上一开始你就不应该用rebase操作来合并master上的变更,而应该选择merge操作:git merge master

参考

  • 团队开发里频繁使用 git rebase 来保持树的整洁好吗?

  • stackoverflow: git-branch-diverged-after-rebase

  • git-scm:Git-Branching-Rebasing