The case is that sometimes you want to add some cool feature to an open source project. But you don't have commit rights to that project. So you checked out a copy of the code and do some local hacking. The problem is that you'll have to track the updates of the original code and merge the changes to your local copy constantly.
One example is the multi-tty support of GNU Emacs (now officially available in Emacs). While the Emacs code base is rapidly evolving, the author of multi-tty branch should track the changes and merge them to his local copy. Another example is YARV when it is still not part of the official Ruby implementation.
Things will be simple if the project is under a distributed version control system (like git), in fact, GitHub is encouraging you to fork the project you want to hack (with simply one click). But the situation is: the official Ruby repository is under subversion while Emacs is still under CVS. :(
But dealing with svn repository is not too hard. The tool to use is git-svn (I still remember that 华华 mentioned the great tool to me). The work flow is simple:
- Check out the repository with git-svn.
git-svn clone http://svn.ruby-lang.org/repos/ruby/trunk ruby19
git-svn try to fetch every history commits of the svn repository. This is a time-consuming process when the repository of that project exists a long time. Generally we don't need the history information, so we can tell git-svn to just retrieve the latest version:git-svn -r HEAD clone http://svn.ruby-lang.org/repos/ruby/trunk ruby19
- Now you have a git repository locally. Create your own branch for your happy hackings:
git checkout -b hacking
- Now do your hacking on the
hackingbranch and commit locally. - You should still update and merge changes from the official repository constantly, the process is fairly simple:
- Commit your local copy to your
hackingbranch:git commit -a
- Switch to the
masterbranch:git checkout master
- Fetch the changes from remote svn repository:
git-svn rebase
- Switch back to your
hackingbranch:git checkout hacking
- Merge changes to your
hackingbranch:git merge master
You are lucky if everything goes fine. But if conflicts occurred, just resolve them and commit.
- Commit your local copy to your
- When you are ready with your hacking and want to release the patch against the latest official repository, just run
git diff:git diff master > hacking.patch
Then put thehacking.patchsomewhere publicly available. Other people with a copy of the official repository of a right revision number can apply your patch by simple:patch < hacking.patch
Cool!
Comments (12)
我最近也想尝试一下分布式 SCM 工具。
不知你试用过 bzr 没有? bzr-svn 也有类似的功能。鉴于 bzr 是基于 Python 的,而且有 TortoiseBzr 的支持,对于 Windows 用户可能更友好些。
@Rhythm, 还好,我一般都是在 Linux 下开发,Windows 下还是只有 TortoiseSVN 好用一些,尝试过 Mercurial 的 TortoiseHg ,一点都不好用。 bzr 倒是没有用过,原来也是基于 Python 的啊?好像听说速度很慢啊?
不过真的在 Windows 下做开发的话,索性用 TortoiseSVN 做一个本地的仓库了。不知道你用过 svk 没有,基于 svn 的 DSCM 。
刚才在 cygwin 下针对 Apache MINA 试用了一下 git-svn ,按照你的描述似乎不起作用啊:
mina$ git-svn -r HEAD clone http://svn.apache.org/repos/asf/mina/trunk/ trunk mina$ cd trunk trunk$ git checkout -b hacking trunk$ fatal: You are on a branch yet to be born
我承认还没怎么看 git 和 git-svn 的文档…… @_@
@pluskid
建立本地仓库还是比较麻烦的,不方便在 SVN 本地库和远程主库之间做切换。难道要经常 swich 一把?而且依靠 switch 的话, merge 好像也不好做吧?
SVK 倒是没有用过,看看怎样
很奇怪,我发现用
clone 出来的本地仓库根本是个空目录(除了
.git子目录之外)。如果不加-r HEAD选项进行 clone 的话会报一些错:而且半天没什么反应,不知道是不是 MINA 的 svn 仓库比较奇怪啊?还是 git-svn 的 bug ? 如果不管用的话或许可以仔细看一下 git-svn 的文档,也许能找到解决办法。我看到它的版本号都到六十多万了,把整个历史 clone 下来太不现实了……
还好我在 Windows 下都只需要一些简单的版本控制功能就够了,说实话,我只用过一两次 svn 的 switch 功能,都没啥印象了。 -,-b
好像 svn.apache.org 下的其他仓库也不好用 git-svn 来 clone 的样子。 @_@
@Jack,
哦?这个倒是没有注意到过。