从Perforce到Git的迁移

公司经过多次兼并、收购之后,开发团队使用的工具自然会出现鱼龙混杂的现象。就拿源代码管理工具来说,我们同时在使用的就有Perforce、Team Foundation、Subversion等。为了节省成本,也为了统一工程实践(以提高工作效率),我们决定让所有团队迁移到Git。

%title插图%num

之所以选择Git,是因为:

它是主流的;
它是免费、开源的;
它支持分布式开发——这一点特别适合跨国团队;
它支持离线环境下的开发(因为每台开发机本地都有一个代码仓库depository);
它是跨平台的(支持Windows、MAC、Linux)。
Git工具可以到http://git-scm.com/上去下载。为了方便操作,也可以使用一些带图形界面的Git工具。关于Git的介绍,网上可以找到很多资料。(顺便推荐一下中文版的《Pro Git》:http://git-scm.com/book/zh。)我想在这里分享的是,我们是怎么把一大堆老项目(主要在Perforce上)迁移到Git的。(Perforce用了将近9年,终于要说“bye-bye”啦……)

在Perforce上,我们为每个产品建立了一个顶级目录。然后,在它下面分别有Main、Work、ThirdParty、Release等子目录。Main里存放一个产品的主要代码,大部分人直接在这上面工作;Work里存放一些试验性质的代码,或者自己开发的小工具;ThirdParty里存放来自第三方的SDK;而Release里存放从Main派生出来的各个版本,典型情况下是为各个客户做的定制和发布,我们一般把它们命名为RelCustomerXV1、RelCustomerXV2、RelCustomerYV1、RelCustomerZV3……整个代码结构看起来是这样的:

%title插图%num

在往Git迁移的过程中,Perforce上每个Changelist的历史记录是移不过去的(或许只是我们不知道……)。我们的办法是:在公司里仍然保留一台Perforce服务器,并开放有限的几个账号,必要时可以提供查询功能;将Perforce上*新的一份代码放到Git上去,并且以后所有的开发都在Git上进行。

我们的迁移是这么做的:首先,由管理员在Git服务器上为每个产品建立一个空的代码仓库,比如ios.git、android.git、pcmac.git等;然后,由各个产品的开发主管负责代码的上传与分支的建立。这里的焦点问题是:如何处置那些RelCustomerXXX分支?因为Perforce的分支概念与Git的有较大的区别:Perforce做的是实实在在的代码拷贝,而Git在创建分支时保存的只是指针或引用。要在Git里为每一个RelCustomerXXX创建分支吗?这样的话,服务器上的分支看起来会比较多(通过git branch -a命令查看),容易造成日后的混淆。经过团队讨论,我们*终决定把这些RelCustomerXXX都建在master上(不另外创建分支),由此带来的问题是:master的体量比较大,在开发人员*次做git clone的时候会比较耗时。忍了!

往Git上传代码的过程是在Git Bash(Windows | All Programs | Git)里通过执行一系列git命令来完成的。具体步骤如下(以iOS产品为例):

%title插图%num

假设你的工作目录(Working Directory)在D:\GitWorkspace。在运行Git Bash之后,你需要执行cd D:\GitWorkspace进入该目录。然后执行git clone命令将空的代码仓库克隆到本地:

git clone <server URL>:ios.git

克隆完成之后,执行cd命令进入本地仓库(你可以看到默认指向了master)。然后,在文件浏览器里,将Perforce上拿到的*新的产品代码拷贝到D:\GitWorkspace\ios\main中,并且在D:\GitWorkspace\ios\customer_releases\下面建立子目录、拷入各个RelCustomerXXX分支的代码,还有其他一些文件(比如work、thirdparty)都拷入D:\GitWorkspace\ios\……当所有文件都准备好之后,在Git Bash里依次执行下面的命令:

git add -A

git commit -m “the initial porting from Perforce”

git remote add origin <server URL>:ios.git

git push origin master

如果上传的代码比较多,上述过程会比较耗时。至于日后在Git上的产品开发,我们决定采用“Gitflow工作流程”。因此,在完成上述的代码上传之后,每个产品的开发主管须立即创建一个develop分支:

git branch develop
git push -u origin develop

*后,别忘了让另一个开发人员在他的机器上拉一下代码(执行git clone或git pull命令),然后试着编译一下,看看是否有部分文件遗漏了。(完)

Perforce的各种命令

在以前的公司代码控制用的是CVS,到这家公司用的是Perforce,中国恐怕没有几家公司用这个玩意,老美的爱好,又或者是Expedia那帮MS出身的爱好。

今天对于Perforce的命令行稍做了些研究,主要用到了以下这些常用的命令:
[color=blue]p4 user
p4 client
p4 add, p4 edit, p4 open
p4 submit
p4 revert
p4 integrate
p4 resolve[/color] 等等.

重点是理解Perforce里面的Integration/Branch机制。在以前,并没有接触过通过SCM来进行代码的版本控制,这是*次真正地使用到。

[color=blue]p4 integrate a.txt b.txt[/color]
执行这条命令的具体效果分几种情况:
1. 如果b.txt不存在, 或者之前并不作为a.txt的分支存在, 那么integrate命令将做branch动作, 即将b.txt生成为a.txt的branch. 注意, 这里如果b.txt之前存在并且不作为a.txt的branch存在, 必须增加 -i 参数强制将其作为a.txt的branch.
2. 如果b.txt已经存在, 并且之前已经是a.txt的branch, 那么integrate命令将做merge动作, 将a.txt的修改更新到b.txt上, 并更新b.txt的版本号.

以上两种情况, 只要b.txt以前已经存在, 都有可能涉及到resolve来解决代码冲突.
关于resolve, p4提供了一系列的选项, 无非就是accept who了, 这里就不细说了.

integrate 还有一种用法, 如下:
[color=blue]p4 integrate -b aBranch[/color]

其中aBranch是事先用这个命令定义的:
p4 branch aBranch
在aBranch的view当中将定义代码间的integrate关系, 这样做的好处是可以在一个branch中定义多个integrate关系, 然后利用p4 integrate -b aBranch一次性integrate多个文件, 省去了一个一个文件更新的步骤.

如在aBranch中定义view时这样定义:
[color=blue]//depot/a.txt… //depot/b.txt
//depot/c.txt… //depot/d.txt[/color]

这样integrate这个branch时, 就可以一次性integrate两个文件了.

integrate的几个常用参数:
-i target之前与source无版本关联, 强制target成为source的branch;
-f 不比较target branch的版本是否与source版本对应, 强制执行integrate;
-d 当source文件删除时, integrate将删除target对应文件; 当target文件删除, integrate将re-branch source的对应文件到target.

对于其他SCM工具的版本控制, 日后还要多多研究, 估计大同小异.

Perforce的环境变量配置

1. 如果使用的是Perforce的可视化的Client的话,

Connection, user,name,password等都是可以在页面上设置的

可以如果想使用command的操作或是自动化代码更新的话, 就要配置相应的环境变量了

 

在系统的环境变量中加入以下配置:

P4PORT=IP:port(Port default as 1666)

P4USER=

P4CLIENT=

 

可以使用p4 info查看当前的信息

 

 

然后使用命令: P4 login 登录看看是否可以成功。如果遇到字符集的原因不能登陆的话, 就要配置

 

P4CHARSET=

P4COMMANDCHARSET=

 

设置成和P4服务匹配的字符集

字符集的设置有:

none, utf8, utf8-bom, iso8859-1, shiftjis, eucjp, iso8859-15,
iso8859-5, macosroman, winansi, koi8_r, cp1251,
utf16, utf16-nobom, utf16le, utf16le-bom, utf16be,
utf16be-bom, utf32, utf32-nobom, utf32le, utf32le-bom, utf32be,
or utf32be-bom

Linux 下 perforce命令行工具 p4的配置

去perforce 网站 http://www.perforce.com/downloads/Perforce/Customer 下载,或者直接在linux终端用wget 下载,加上执行权限,并放到/usr/local/bin下。

$ wget http://filehost.perforce.com/perforce/r14.1/bin.linux26x86/p4
$ chmod u+x p4
$ sudo cp p4 /usr/local/bin/

编辑 ~/.bashrc 文件加入下面一些变量
export P4USER=jschen
export P4PORT=192.1.1.1:1666
export P4EDITOR=vim
export P4IGNORE=p4ignore
export P4CLIENT=jschen-fedora

登录perforce服务器,设置workspace
[jschen@10.12.6.197:~]$ p4 login
Enter password:
User jschen logged in.
[jschen@10.12.6.197:~]$ p4 client

更改 Root 和View选项
Client: jschen-fedora
Root: /back/code/
View:
//my_project/… //jschen-fedora/my_project/…