git svn
을 설명하는 절을 읽었으면 쉽게 git svn clone
명령으로 저장소를 가져올 수 있다. 가져오고 나서 Subversion 서버는 중지하고 Git 서버를 만들고 사용하면 된다.
만약 히스토리 정보가 필요하면 (느린) Subversion 서버 없이 로컬에서 조회할 수 있다.
하지만 이 가져오기 기능에 문제가 좀 있다. 가져오는데 시간이 많이 드니까 일단 시작하는 것이 좋다.
첫 번째 문제는 Author 정보이다.
Subversion에서는 커밋하려면 해당 시스템 계정이 있어야 한다.
blame
이나 git svn log
같은 명령에서 schacon
이라는 이름을 봤을 것이다.
이 정보를 Git 형식의 정보로 변경하려면 Subversion 사용자와 Git Author를 연결시켜줘야 한다.
Subversion 사용자이름과 Git Author 간에 매핑할 수 있게 해줘야 한다. users.txt
라는 파일을 아래와 같이 만든다.
schacon = Scott Chacon <schacon@geemail.com>
selse = Someo Nelse <selse@geemail.com>
SVN에 기록된 Author 이름을 아래 명령으로 조회한다.
$ svn log --xml --quiet | grep author | sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = /'
우선 XML 형식으로 SVN 로그를 출력하고, 거기서 Author 정보만 찾고, 중복된 것을 제거하고, XML 태그는 버린다.
물론 grep
, sort
, perl
명령이 동작하는 시스템에서만 이 명령을 사용할 수 있다.
이 결과에 Git Author 정보를 더해서 users.txt
파일을 만든다.
이 파일을 git svn
명령에 전달하면 보다 정확한 Author 정보를 Git 저장소에 남길 수 있다.
그리고 git svn
명령의 clone
또는 init
명령에 --no-metadata
옵션을 주면 Subversion의 메타데이터를 저장하지 않는다 (기존 메타데이터를 유지하려면 이 옵션을 사용하지 않아도 괜찮다).
해당 명령은 아래와 같다.
$ git svn clone http://my-project.googlecode.com/svn/ \
--authors-file=users.txt --no-metadata --prefix "" -s my_project
$ cd my_project
my_project
디렉토리에 진짜 Git 저장소가 생성된다.
결과는 아래가 아니라,
commit 37efa680e8473b615de980fa935944215428a35a
Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
아래와 같다.
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Scott Chacon <schacon@geemail.com>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
Author 정보가 훨씬 Git답고 git-svn-id
항목도 기록되지 않았다.
이제 뒷 정리를 할 차례다.
git svn
이 만들어 준 이상한 브랜치나 태그를 제거한다.
우선 이상한 리모트 태그를 모두 진짜 Git 태그로 옮긴다. 그리고 리모트 브랜치도 로컬 브랜치로 옮긴다.
아래와 같이 태그를 진정한 Git 태그로 만든다.
$ for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done
refs/remotes/tags/
로 시작하는 리모트 브랜치를 가져다 Lightweight 태그로 만들었다.
refs/remotes
밑에 있는 Refs는 전부 로컬 브랜치로 만든다.
$ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done
대개 Subversion에서는 브랜치 하나만 보일 진데 @xxx
(xxx는 숫자) 문자로 끝나는 몇 가지 브랜치가 더 보일 것이다.
이런 이름의 브랜치가 존재하는 것은 "peg-revisions" 이라 부르는 Subversion의 기능 때문이며 Git에서는 마땅히 대응되는 기능이 없다.
Subversion에서 peg-revision을 다루기 위해 브랜치 이름 뒤에 버전 숫자를 붙인 것 처럼 git svn
역시 그렇게 하는 것이다.
peg-revision 기능을 사용하지 않는다면 그냥 브랜치를 삭제하면 된다.
$ for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done
이제 모든 태그와 브랜치는 진짜 Git 태그와 브랜치가 됐다.
마지막으로 마무리를 위한 과정이 하나 남았다.
안타깝게도 git svn
명령이 만드는 Subversion의 기본 브랜치인 trunk
브랜치가 있다. trunk
브랜치는 Git의 master
역할을 한다고 보면 된다.
Git에는 master
브랜치가 있기 때문에 여분의 trunk
브랜치는 삭제하자.
$ git branch -d trunk
Git 서버를 새로 추가를 하고 지금까지 작업한 것을 Push 하는 일이 남았다. 아래처럼 리모트 서버를 추가한다.
$ git remote add origin git@my-git-server:myrepository.git
분명 모든 브랜치와 태그를 Push 하고 싶을 것이다.
$ git push origin --all
$ git push origin --tags
모든 브랜치와 태그를 Git 서버로 깔끔하게 잘 옮겼다.