关于branch XYZ is published (but not merged) and is now N commits behind错误的一点分析

来源:互联网 发布:淘宝如何进入卖家中心 编辑:程序博客网 时间:2024/06/07 04:42
文章部分资料参考自老罗的博客:http://blog.csdn.net/luoshengyang/article/details/18195205,在此感谢老罗无私分享

一 背景

       众所周知Android源码是由repo管理的一堆git仓库,我在参与Android Framework开发工作的时候经常sync code遇到如题目所描述的错误。作为repo和git双小白的我看到网上对此问题的答案大概分两种:1,不用理他,继续自己的工作就行;2,通过git命令将当前分支rebase到远端分支,git rebase origin/$branchName。我也不明白这两种解决方法是为啥,一直迷糊。直到看到老罗分享的repo源码解析,终于下决心搞明白这个错误的来龙去脉。

二 问题分析

        既然错误日志是由repo打印出来的当然去repo仓库源码中寻找线索(repo的安装方法不在此赘述)。最终搜索到本段log是由.repo/repo/project.py打印出来的
    upstream_gain = self._revlist(not_rev(HEAD), revid)    pub = self.WasPublished(branch.name, all_refs)    if pub:      not_merged = self._revlist(not_rev(revid), pub)      if not_merged:        if upstream_gain:          # The user has published this branch and some of those          # commits are not yet merged upstream.  We do not want          # to rewrite the published commits so we punt.          #          syncbuf.fail(self,                       "branch %s is published (but not merged) and is now %d commits behind"                       % (branch.name, len(upstream_gain)))        return
        由本段代码可见,在pub && not_merge && upstream_gain 的情况下才会打印错误log并且直接返回,根据开头引用老罗的文章分析,当前远端代码已经fetch完毕,但是没有检出到工作区,因此工作区中的内容并不是我们要sync的目标,这里就有可能会因为代码不一致而埋下编译运行时的bug.

举个例子:
        远端有两个分支:Branch A,Branch B
        本地有一个分支:Branch A 本地A分支追踪到远端A分支并且保持一致。
提交记录为
        Branch A:A -> B -> C -> D
        Branch B:A -> B -> E -> F

        此时位于分支Branch A,Manifest内该项目所指定的revision为Branch B,执行命令 repo sync .,就会报出如题目所描述的错误。
        因为此时Branch A的提交已经发布到远端,并且没有和Branch B 进行merge,并且Branch A相对两分支共同父节点B领先两个提交(C,D),此时repo就会报错退出。当前工作区的内容依然是Branch A,没有检出Branch B,因此工作区的内容和Manifest指定的revision不一致。这就是产生bug的隐患。
 实际操作中的结果:
     
如上例所示:
        当前处于分支newMTK,追踪到远端origin/test/m-rel-mtk6755
        manifest指定的revision是origin/test/m-rel-mtk6755+test-volte
此时执行repo sync . 就会报出题目中描述的错误.

三 解决方案

        问题明确以后我们就先分析网上流行的解决方案可行性。

方案一:直接略过

        此方案明显不行,因为sync运行失败,没有检出我们指定的revision到工作区,因为代码不是我们指定的版本,最终编译运行都有可能产生bug,不满足我们的要求。pass!

方案二:和远端进行rebase

        这是一个更加流行的方案,通过和远端进行rebase达成merge的目标,打破了条件  pub && not_merge && upstream_gain 之一 not_merge.此时重新进行repo sync肯定不会再报错,但是这样也不能达成我们的目标。
先看rebase的结果
        Branch A: A -> B -> E -> F -> C -> D
相对我们需要的版本多了两个提交C,D。同样这两个提交也有可能为我们埋下新的bug,并且此操作也不会修改Branch A指向的远端分支。git pull之类的命令还是不能用。同样pass

方案三:创建新分支,追踪到远端分支Branch B,并切换到新分支。

        repo start Local_Branch_B
        此时可以直接创建新的本地分支Local_Branch_B,并且此分支会追踪到远端分支Branch B,此时再进行Sync或者git pull都可以下载到我们需要的代码版本,完美解决问题。

        PS:这样可以最终解决问题,但是如果后续有切换回指向Branch A的manifest,会报出同样的错误。还是同样的原因。建议对于自己不会进代码的分支,删掉全部的本地分支。此时再进行repo sync的时候就可以fetch到manifest指定的revision,并且进入分离头指针状态,一劳永逸。至于为什么,请前去学习老罗的博客。


四 后记

        如repo 代码注释描述,对于已发布未合并的提交,repo不会直接覆盖,也不会去帮你merge,所以它选择狗带,交给终端用户手动解决。
        战斗力为渣渣的我不能像罗升阳大神一样逐行分析repo 代码,只能靠着可读性比较好的代码表面意思加上自己手动实验的结果分析出这么点东西。做个笔记,同时也算抛砖引玉,希望有大神给出更明确的答案。如有错误,欢迎拍砖。



0 0
原创粉丝点击