20.3 StGit和Quilt

一个复杂功能的开发一定是由多个提交来完成的,对于在以接收和应用补丁文件为开发模式的项目中,复杂的功能需要通过多个补丁文件来完成。补丁文件因为要经过审核才能被接受,因此针对一个功能的多个补丁文件一定要保证各个都是精品:补丁1用来完成一个功能点,补丁2用来完成第二个功能点,等等。一定不能出现这样的情况:补丁3用于修正补丁1的错误,补丁10改正了补丁7中的文字错误,等等。这样就带来补丁管理的难题。

实际上基于特性分支的开发又何尝不是如此?在将特性分支归并到开发主线前,要接受团队的评审,特性分支的开发者一定想将特性分支上的提交进行重整,把一些提交合并或拆分。使用变基命令可以实现提交的重整,但是操作起来会比较困难,有什么好办法呢?

20.3.1 StGit

StGit[1]是Stacked Git的简称。StGit就是解决上面提到的两个难题的答案。实际上StGit在设计上参考了一个著名的补丁管理工具Quilt,并且可以输出Quilt兼容的补丁列表。在本节的后半部分会介绍Quilt。

StGit是一个Python项目,安装起来还是很方便的。在Debian/Ubuntu下,可以直接通过包管理器安装:


$sudo aptitude install stgit stgit-contrib


下面还是用hello-world版本库,进行StGit的实践。

(1)首先检出hello-world版本库。


$cd/path/to/my/workspace/

$git clone file:///path/to/repos/hello-world.git stgit-demo

$cd stgit-demo


(2)在当前工作区初始化StGit。


$stg init


(3)现在补丁列表为空。


$stg series


(4)将最新的三个提交转换为StGit补丁。


$stg uncommit-n 3

Uncommitting 3 patches…

Now at patch "translate-for-chinese"

done


(5)现在补丁列表中有三个文件了。

第一列是补丁的状态符号。加号(+)代表该补丁已经应用在版本库中,大于号(>)用于标识当前的补丁。


$stg ser

+fix-typo-help-to-help

+add-i18n-support

>translate-for-chinese


(6)现在查看master分支的日志,发现和之前没有两样。


$git log-3—oneline

c4acab2 Translate for Chinese.

683448a Add I18N support.

d81896e Fix typo:-help to—help.


(7)执行StGit补丁出栈的命令,会将补丁撤出应用。使用-a参数会将所有补丁撤出应用。


$stg pop

Popped translate-for-chinese

Now at patch "add-i18n-support"

$stg pop-a

Popped add-i18n-support—fix-typo-help-to-help

No patch applied


(8)再来看看版本库的日志,会发现最新的三个提交都不见了。


$git log-3—oneline

10765a7 Bugfix:allow spaces in username.

0881ca3 Refactor:use getopt_long for arguments parsing.

ebcf6d6 blank commit for GnuPG-signed tag test.


(9)查看补丁列表的状态,会看到每个补丁前都用减号(-)标识。


$stg ser

-fix-typo-help-to-help

-add-i18n-support

-translate-for-chinese


(10)执行补丁入栈,即应用补丁,使用命令stg push或stg goto,注意stg push命令和git push命令风马牛不相及。


$stg push

Pushing patch "fix-typo-help-to-help"…done(unmodified)

Now at patch "fix-typo-help-to-help"

$stg goto add-i18n-support

Pushing patch "add-i18n-support"…done(unmodified)

Now at patch "add-i18n-support"


(11)现在处于应用add-i18n-support补丁的状态。这个补丁有些问题,本地化语言模板有错误,我们来修改一下。


$cd src/

$rm locale/helloworld.pot

$make po

xgettext-s-k_-o locale/helloworld.pot main.c

msgmerge locale/zh_CN/LC_MESSAGES/helloworld.po locale/helloworld.pot-o locale/temp.po

.完成。

mv locale/temp.po locale/zh_CN/LC_MESSAGES/helloworld.po


(12)现在查看工作区,发现工作区有改动。


$git status-s

M locale/helloworld.pot

M locale/zh_CN/LC_MESSAGES/helloworld.po


(13)不要提交,而是执行stg refresh命令更新补丁。


$stg refresh

Now at patch "add-i18n-support"


(14)这时再查看工作区,发现本地修改不见了。


$git status-s


(15)执行stg show会看到当前的补丁add-i18n-support已经更新。


$stg show


(16)将最后一个补丁应用到版本库,遇到冲突。这是因为最后一个补丁是对中文本地化文件的翻译,因为翻译前的模板文件被更改了所以造成了冲突。


$stg push

Pushing patch "translate-for-chinese"…done(conflict)

Error:1 merge conflict(s)

CONFLICT(content):Merge conflict in

src/locale/zh_CN/LC_MESSAGES/helloworld.po

Now at patch "translate-for-chinese"


(17)这个冲突文件很好解决,直接编辑冲突文件helloworld.po即可。编辑好之后,注意一下第50行和第62行是否像下面写的一样。


50 "hello-h,—help\n"

51 "显示本帮助页。\n"

61 msgid "Hi,"

62 msgstr "您好,"


(18)执行git add命令完成冲突解决。


$git add locale/zh_CN/LC_MESSAGES/helloworld.po


(19)不要提交,而是使用stg refresh命令更新补丁,同时更新提交。


$stg refresh

Now at patch "translate-for-chinese"

$git status-s


(20)看看修改后的程序,是不是都能显示中文了。


$./hello

世界你好。

(version:v1.0-5-g733c6ea)

$./hello Jiang Xin

您好,Jiang Xin.

(version:v1.0-5-g733c6ea)

$./hello-h


(21)导出补丁,使用命令stg export。导出的是Quilt格式的补丁集。


$cd/path/to/my/workspace/stgit-demo/

$stg export-d patches

Checking for changes in the working directory…done


(22)看看导出补丁的目标目录。


$ls patches/

add-i18n-support fix-typo-help-to-help series translate-for-chinese


(23)其中文件series是补丁文件的列表,列在前面的补丁先被应用。


$cat patches/series

This series applies on GIT commit d81896e60673771ef1873b27a33f52df75f70515

fix-typo-help-to-help

add-i18n-support

translate-for-chinese


通过上面的演示可以看出StGit可以非常方便地对提交进行整理,整理提交时无须使用复杂的变基命令,而是采用提交StGit化、修改文件、执行stg refresh的工作流程即可更新补丁和提交。StGit还可以将补丁导出为补丁文件,虽然导出的补丁文件没有像git format-patch那样加上代表顺序的数字前缀,但是用文件series标注了补丁文件的先后顺序。实际上可以在执行stg export时添加-n参数为补丁文件添加数字前缀。

StGit还有一些功能,如合并补丁/提交,插入新补丁/提交等,请参照StGit帮助,恕不一一举例。

[1]http://www.procode.org/stgit/