GIT版本控制 — GIT與SVN的相互轉換 (三)

git-svn

 

git-svn用於Git和SVN的轉換,可以把Git倉庫遷移成SVN倉庫,反之亦可。

詳細介紹可見[1],或者命令行輸入git-svn。

 

Bidirectional operation between a Subversion repository and git.

git svn can track a standard Subversion repository, following the common "trunk/branches/tags" layout,

with the --stdlayout option. It can also follow branches and tags in any layout with the -T/ -t/ -b options.

Once tracking a Subversion repository, the git repository can be updated from Subversion by thefetch

command and Subversion updated from git by the dcommit command.

 

Git遷移到SVN

 

把Git遷移到SVN?沒錯,還真有這種需求,雖然較少:)

Git has a feature to work with SVN repositories, git-svn, but that's intended to check out

existing code from SVN and work on it, not publishing an existing Git tree into a SVN repository.

 

(1) 依賴包

需要安裝subversion-perl、perl-TermReadKey。

Git中帶有git-svn,需要確定它的路徑可在PATH中找到。

 

(2) 建立svn項目

在svn服務器中新建svn項目proj。

# svnadmin create proj

 

(3) svn項目的本地初次提交

# svn mkdir http://IP:PORT/svn/proj/trunk \

                     http://IP:PORT/svn/proj/branches \

                     http://IP:POPT/svn/proj/tags \

                     http://IP:PORT/svn/proj/docs -m "Initial import"

 

(4) 提交Git proj項目到SVN proj

進入Git proj項目。

# git-svn init -s http://IP:PORT/svn/proj // -s表示svn爲標準佈局

    標準佈局的意思就是:

    trunk分支爲:proj/trunk,可以用-T另外指定

    branches分支爲:proj/branches,可用-b另外指定

    tags分支爲:proj/tags,可用-t另外指定

 

# git-svn fetch // 獲取SVN proj的更新

    r1 = 79563196f21ce4699a04fa4ae24d0ca916bf3acf (refs/remotes/trunk)

    trunk分支代表SVN proj的trunk分支

 

# git-svn dcommit // 提交Git proj的更新

    注意!這個時候會報錯:

    Unable to determine upstream SVN information from HEAD history.

    Perhaps the repository is empty. at /usr/local/git/libexec/git-core/git-svn line 852.

   

因爲現在Git proj的commits不知道要放到SVN proj的哪個版本之後,即Git proj的這些提交要

放在SVN哪個版本之後(顯然是放到SVN的初始提交之後,但是Git proj就是不知道,因爲設計者

並不考慮把Git proj轉爲SVN proj的情況:)

 

以下是詳細描述:

This fails since the git svn command can't figure out which commits to push: there's no link

between our original Git repository and the Subversion heads.

To fix this, we can use a Git graft to link them. We'll tell Git the commit which created the SVN

folder in which we want to store the project is the parent commit of the first commit in our Git

repository.

 

解決方法

# git show-ref trunk // 顯示SVN proj trunk分支的HEAD,即r1

   79563196f21ce4699a04fa4ae24d0ca916bf3acf refs/remotes/trunk

# git log --pretty=oneline master | tail -n 1 // 顯示Git proj 的第一個commit

    561c439a15f807b8d62551a0c64f939c15489899 initial import

# echo "561c439a15f807b8d62551a0c64f939c15489899 79563196f21ce4699a04fa4ae24d0ca916bf3acf" >> .git/info/grafts

    把Git proj從561c43開始的提交,添加到SVN proj在795631之後的提交。

# git-svn dcommit // 提交Git proj的更新到SVN proj中

    這個時候就把Git proj完整的轉化成SVN proj,後者完全符合SVN的規範了。

 

(5) 把git分支提交到svn的分支

如果原來的git倉庫不僅有master,還有其它分支,那麼怎麼把git的分支提交爲svn的分支呢?

這個時候就要用到git rebase了。

 

過程如下:

在遠端svn倉庫中創建一個新分支。

# svn cp URL/trunk URL/branches/remote-branch

更新本端Git倉庫。

# git-svn fetch

切換到本端的分支。

# git checkout local-branch

創建一個用於臨時用的分支,其實和local-branch是一樣的。

# git checkout -b temp-local-branch

關鍵點來了,把本端分支的所有修改,合併到遠端分支。

# git rebase remotes/remote-branch

完成上一步以後,遠端分支已經含有本端分支的所有commit。

接着可以把修改提交到svn倉庫了。

# git svn dcommit

最後把本端的臨時分支刪除。

# git branch -D temp-local-branch

 

此時再查看svn倉庫,就會發現branch/remote-branch已經是原來的git分支了。

不過svn分支的日誌順序,相較於原來git分支的可能會有所不同,這是由rebase引起的,正常現象。

 

(6) 從git分支更新svn分支

修改.git/config,添加遠程分支:

[svn-remote "branch"]

url = URL/proj/branches/branch

fetch = :refs/remotes/branch

綁定本地分支和遠程分支:

[branch "local-branch"]

remote = .

merge = refs/remotes/branch

 

修改了本地分支local-branch後,可以直接提交到遠端svn的branch分支了。

# git-svn dcommit

 

SVN遷移到Git

 

相比之前介紹的Git遷移到SVN,SVN遷移到Git纔是主流趨勢,也更加容易,因爲這是git-svn的主要目的。

同樣用git-svn來完成遷移:

git-svn primarily can be used to checkout a Subversion repository to a local Git repo and then

push your changes back to the original Subversion repository.

 

克隆SVN倉庫,可以使用-T trunk、-b branches、-t tags來指定對應分支,-s表示採用標準佈局。

# git-svn clone -s URL/proj proj

相當於執行了git-svn init和git-svn fetch。

 

把SVN倉庫的更新同步到Git。

# git-svn rebase

 

創建.gitignore文件。

# git-svn create-ignore

 

將Git的更新提交到SVN倉庫。

# git-svn dcommit

 

Author

 

zhangskd @ csdn blog

 

Reference

 

[1]. https://www.kernel.org/pub/software/scm/git/docs/git-svn.html

[2]. http://plpatterns.com/post/234334879/how-to-convert-a-local-branch-in-git-to-a-remote

[3]. http://www.cnblogs.com/kym/archive/2010/08/12/1797937.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章