git-svn: fetch history from git clone

On http://trac.webkit.org/wiki/UsingGitWithWebKit there is a very useful trick:

If you want to be able to commit changes to the Subversion repository, or just want to check out branches that aren’t contained in WebKit.git, you will need track the Subversion repository. To do that, inform git-svn of the location of the WebKit SVN repository, and update the branch that git-svn uses to track the Subversion repository so that it will re-use the history that we’ve already cloned from git.webkit.org rather than trying to fetch it all from Subversion:

cd WebKit
git svn init --prefix=origin/ -T trunk http://svn.webkit.org/repository/webkit
git config --replace svn-remote.svn.fetch trunk:refs/remotes/origin/master

This will add the following section to your .git/config:

[svn-remote "svn"]
url = http://svn.webkit.org/repository/webkit
fetch = trunk:refs/remotes/origin/master

You can then run the following command to have git-svn rebuild its metadata from your local repository, and to pull any recent commits from the WebKit SVN repository.

git svn fetch

So, let’s say you have a subversion repository:

svn://svn.openwrt.org/openwrt/trunk

and you also have a git clone of that repository:

git://nbd.name/openwrt.git

(Obviously these examples come from OpenWrt)
Now if you don’t want to fetch the whole history from svn, which will take forever, here is what you can do:

mkdir openwrt;cd openwrt;
git svn init --prefix=svn/ svn://svn.openwrt.org/openwrt/trunk
git remote add nbd.name git://nbd.name/openwrt.git
git fetch nbd.name
git config --replace svn-remote.svn.fetch trunk:refs/remotes/nbd.name/master
git svn fetch
  1. The git config line tells git-svn to use the history in nbd.name, so you won’t need to checkout the same commits from svn.
  2. Use --prefix=svn/ to separate nbd.name upstream and svn upstream.
Advertisements

git clone –mirror

It seems there will be a new option for git-clone, ‘–mirror’. The command line

$ git clone --mirror $URL

is now a short-hand for

$ git clone --bare $URL
$ (cd $(basename $URL) && git remote add --mirror origin $URL)

Refer to http://kerneltrap.org/mailarchive/git/2008/8/2/2793244 about this.

This is extremely useful if you need to check the contents of different branches in different directories at the same time. Each directory will be a local git clone -l -s, and git push will use –mirror as well by default.

git first, git-svn later.

the whole story is that I started a project locally and I used git as my SCM. now I’m going to put it into a svn repository with full history but I still want to use git.

normally you should make this decision at the beginning. that means you

git-svn clone http://svn.somewhere.com/myproject

first, then you use git as usual, do git-svn rebase and git-svn dcommit. you have to do this because git-svn must know where to start, namely you should have at least one git-svn-id in your git log to start with.

here is how I add svn support into an existing git repository. basically it’s easy, you just

git-svn init http://svn.somewhere.com/myproject
git-svn fetch

now git branch -r should tell you there is a branch called git-svn. you git rebase git-svn your current master. if it succeeded then you’re all set.

however, in order to do this, there must be a point back in time that these two branches are the same. if it’s not the case, you’re in trouble. you have to use git-svn set-tree to force a svn commit to be your starting point. in my case, the svn repository started out empty, so I forced the first commit in my git. after that git rebase succeeded like I expected.

git-svn

像 subversion (svn) 這類集中式的 scm 一定要有網路連線才能 commit ,這是很討厭的一件事情,尤其是很多人都會用 notebook 工作,不見得需要長時間連結網路,或者是並沒興趣修改 svn 上的版本。這時候像老牌的 monotone 或是現在的 git 以及 Mercurial 這種分散式的版本管理系統就很好用。這陣子在改一個 project,他已經有 svn 在 googlecode 上,看來已經很久沒人 maintain. 我當然還不需要 svn write 權限,但是我仍然希望在自己 local 端有版本管理,這樣我如果幹了什麼蠢事才救得回來。

此時 git-svn 這種工具就真的很好用。基本使用方式是

# Clone a repo (like git clone):
        git-svn clone http://svn.foo.org/project/trunk
# Enter the newly cloned directory:
        cd trunk
# You should be on master branch, double-check with git-branch
        git branch
# Do some work and commit locally to git:
        git commit ...
# Something is committed to SVN, rebase your local changes against the
# latest changes in SVN:
        git-svn rebase
# Now commit your changes (that were committed previously using git) to SVN,
# as well as automatically updating your working HEAD:
        git-svn dcommit
# Append svn:ignore settings to the default git exclude file:
        git-svn show-ignore >> .git/info/exclude

日後如果我想要把修改 commit 到 upstream 去,我在這段時間的修改記錄仍然可以保留。相當有彈性的作法。