Use git-svn to fork a project and keep tracking of it

April 15, 2008 – 12:28 am

gitThe 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:

  1. 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
    
  2. Now you have a git repository locally. Create your own branch for your happy hackings:
    git checkout -b hacking
    
  3. Now do your hacking on the hacking branch and commit locally.
  4. You should still update and merge changes from the official repository constantly, the process is fairly simple:
    1. Commit your local copy to your hacking branch:
      git commit -a
      
    2. Switch to the master branch:
      git checkout master
      
    3. Fetch the changes from remote svn repository:
      git-svn rebase
      
    4. Switch back to your hacking branch:
      git checkout hacking
      
    5. Merge changes to your hacking branch:
      git merge master
      

      You are lucky if everything goes fine. But if conflicts occurred, just resolve them and commit.

  5. 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 the hacking.patch somewhere 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!

:D Now go and fork your favourite project!

  1. 12 Responses to “Use git-svn to fork a project and keep tracking of it”

  2. git非常适合做这个用途。看了你的这份blog才知道svn的repository也支持的很好。

    By yawl on Apr 15, 2008

  3. 我最近也想尝试一下分布式 SCM 工具。

    不知你试用过 bzr 没有? bzr-svn 也有类似的功能。鉴于 bzr 是基于 Python 的,而且有 TortoiseBzr 的支持,对于 Windows 用户可能更友好些。

    By Rhythm on Apr 15, 2008

  4. 哦,对了,小田田前阵子在研究 bzr ,不知道有啥成果没~

    By Rhythm on Apr 15, 2008

  5. @Rhythm,
    还好,我一般都是在 Linux 下开发,Windows 下还是只有 TortoiseSVN 好用一些,尝试过 Mercurial 的 TortoiseHg ,一点都不好用。 bzr 倒是没有用过,原来也是基于 Python 的啊?好像听说速度很慢啊?

    不过真的在 Windows 下做开发的话,索性用 TortoiseSVN 做一个本地的仓库了。不知道你用过 svk 没有,基于 svn 的 DSCM 。

    By pluskid on Apr 15, 2008

  6. 刚才在 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 的文档…… @_@

    By Rhythm on Apr 15, 2008

  7. @pluskid

    建立本地仓库还是比较麻烦的,不方便在 SVN 本地库和远程主库之间做切换。难道要经常 swich 一把?而且依靠 switch 的话, merge 好像也不好做吧?

    SVK 倒是没有用过,看看怎样

    By Rhythm on Apr 15, 2008

  8. @Rhythm,
    很奇怪,我发现用

    git-svn -r HEAD clone http://svn.apache.org/repos/asf/mina/trunk/ trunk
    

    clone 出来的本地仓库根本是个空目录(除了 .git 子目录之外)。如果不加 -r HEAD 选项进行 clone 的话会报一些错:

    $ git-svn clone http://svn.apache.org/repos/asf/mina/trunk/ trunk      Initialized empty Git repository in .git/
    W: Ignoring error from SVN, path probably does not exist: (175007): HTTP Path Not Found: REPORT request failed on '/repos/asf/!svn/bc/100/mina/trunk': '/repos/asf/!svn/bc/100/mina/trunk' path not found
    W: Do not be alarmed at the above message git-svn is just searching aggressively for old history.
    This may take a while on large repositories
    

    而且半天没什么反应,不知道是不是 MINA 的 svn 仓库比较奇怪啊?还是 git-svn 的 bug ? 如果不管用的话或许可以仔细看一下 git-svn 的文档,也许能找到解决办法。我看到它的版本号都到六十多万了,把整个历史 clone 下来太不现实了……

    By pluskid on Apr 15, 2008

  9. @Rhythm,
    还好我在 Windows 下都只需要一些简单的版本控制功能就够了,说实话,我只用过一两次 svn 的 switch 功能,都没啥印象了。 -,-b

    By pluskid on Apr 15, 2008

  10. 啊……得了,我再研究研究~

    By Rhythm on Apr 16, 2008

  11. @Rhythm,
    好像 svn.apache.org 下的其他仓库也不好用 git-svn 来 clone 的样子。 @_@

    By pluskid on Apr 16, 2008

  12. git-svn对binary支持太差了…

    By Jack on Apr 19, 2008

  13. @Jack,

    哦?这个倒是没有注意到过。

    By pluskid on Apr 19, 2008

Post a Comment