SCM:代码基线升级--三线法

来源:互联网 发布:金大川和melody知乎 编辑:程序博客网 时间:2024/05/21 18:46
  不知道前人有没有总结类似的方案,仅在这里就自身的经验给大家提供一个参考。我把这个方法叫做“三线法”,主要用作代码基线升级和上游分支管理。

一 使用背景
     OEM/ODM公司在获得上游源代码之后,定制自己的所需要添加的部分,但是同时要求和上游源代码所在的分支保持同步更新。

二 "三线法"主要原理
     针对某一个项目的代码,给它建立三条分支:upstream branch、baseline branch、main branch(上游分支、基线分支、主开发分支)。其中上游分支即为源代码所在分支,该分支不在我们自己建立的代码仓库内;基线分支,用于保存上一次代码升级的上游分支状况,也是代码升级过程中的中转分支;主开发分支,我们自己建立的仓库内给研发使用的开发分支,它是基线分支+定制代码。

三 “三线法”的优点
     最大的优点是避免交错的历史;另一个优点是简化多个项目共用同一个基线时升级操作。

四 具体升级的步骤
针对于不同的上游公司,可能它们管理给客户代码的方式不一样,有一些是提供的镜像仓库,而有一些则是直接提供完整源代码的压缩包。
以下先看看提供镜像仓库的做法:
1.获得上游分支最新代码
通过repo工具manifest列表直接同步下来一套完整的代码。这个同步的方法需要上游公司提供,但是不外乎:
$ repo init
$ repo sync
可能太抽象,举个栗子:
$ repo init -u git://codeaurora.org/platform/manifest.git -b release -m [manifest] --repo-url=git://codeaurora.org/tools/repo.git --repo-branch=caf-stable
$ repo sync
这是某芯片厂商,对外开放的代码网站上的Android代码拉取方式。
同步完成之后,为所有仓库打上一个tag,标识该版本上游分支的代码状态(往往上游分支已经存在这样一个tag了则不需再打)。
若上游分支没有tag,打tag:
$ repo forall -c "pwd;git tag -am  "tag_messagetag_name"
若已存在,验证某个tag是否标识当前upstream代码:
$ repo forall -c "git diff HEAD tag_name"

2.把自家的代码仓库内的代码基线分支(baseline branch)更新到最新状态
a)在1步骤完成过后的代码目录内,利用repo forall -c "source add_remote.sh"给所有仓库添加自家仓库的remote,给大家一个小脚本:
add_remote.sh:
#!/bin/bash
GIT_HOST="local git@host:/path/"
REMOTE_PATH=$REPO_PROJECT
git remote add $GIT_HOST$REMOTE_PATH
ps:斜体根据实际情况修改。remote简称自己定义,git@host为git服务器地址,path为项目代码存放在服务器上的位置(总目录)。

b)添加自家仓库的remote之后,把自家仓库内旧的baseline分支同步到相同目录内
$ repo forall -c "pwd;git remote update local"
  切换到baseline分支准备对它进行升级
$ repo forall -c "git checkout -b baseline local/baseline"

c)升级baseline分支
$ repo forall -c "pwd ; git rebase tag_name baseline"
这一步骤按理说不会有冲突或错误,log都应该是Fast forward... 或者 Already updated...
把更新之后的baseline分支push到服务器
$ repo forall -c "git push local baseline:baseline"
建议把该版本的上游分支的tag也push到服务器:
$ repo forall -c "git push local tag_name"

3.升级主开发分支
a)说到这里肯定要说下自家仓库的分支布署状况:main branch 是基于 baseline branch 之上做的开发分支。从自家服务器上拉下来的整套代码内应该即含有开发分支又有基线分支。它们的区别在于主开发分支上含有我们自己提交的代码,而基线分支则只是保留存了纯粹的上游代码。

b)在进行开发分支升级时建议另起一个目录从自家服务器上拉下来的整套代码。
$ repo init ...(省略)
$ repo sync

c)
切出两个分支主开发分支,基线分支。并且最终立于更新最新upstream代码之后的基线分支上。
$ repo forall -c "pwd; git checkout -b mainbranch local/mainbranch"
$ repo forall -c "pwd ; git checkout -b baseline local/baseline
(You must stand on baseline branch,then do this)
$ repo forall -c "pwd; git merge mainbranch"
该步骤可能会产生冲突,解决他们,然后push升级之后的新开发分支到服务器
$ repo forall -c "pwd; git push local baseline:manbranch"
ps:这里把baseline推送到远程local manbranch分支之上是正确的,可以查看的到这里名为baseline的本地分支,是经过merge主分支上的自家提交的代码产生的。它就是升级之后的新的主开发分支。

对于提供完整代码压缩包的:
   与之前不同的是对于这种状况我们可以直接虚拟一个upstream分支,然后其他步骤与镜像库采取相同操作即可。在这里我仅提供一个流程:
第一次导入代码:
1 获得完全代码压缩包
2 解压
3 向上游公司获取参考manifest(若他们内部开发也是用git+repo 来管理的话)
4 通过manfiest 自己init一套空的仓库,只含目录与.git,.repo
5 把解压出来的代码拷贝到4步骤init出来的一套空仓库目录内
6 对所有仓库进行一次提交
$ repo forall -c "pwd; git add -f *"
$ repo forall -c "git commit -m "Import code""
7 把当前做出来的分支push为base分支main分支
8 打个tag记录当前状态并push

之后对上游分支进行升级:
1 获得新的完全代码压缩包
2 解压
3 获取baseline分支的一套代码
4 提取baseline分支这套代码所有.repo .git目录 以及他们的parent目录结构到一个新的目录new
5 把解压出来新的代码拷贝到new目录之下
7 对所有仓库进行一次提交,若该目录没有更新则显示nothing to commit
8 把新的baseline分支push到服务器上
9 就当前代码打一个tag推送到服务其上,便于以后标识
9 与镜像库方式相同的方法升级主分支mainbranch

五 以下是三线法原理的简要图表:其中A`B`C`是自家的提交。


新萌的欢迎大家讨论交流!微信号 ts74108520

20150119Harrytan

0 0
原创粉丝点击