Desenvolvimento

8 mar, 2016

Importando uma árvore Git para um repositório Subversion

Publicidade

Recentemente, trabalhei em um novo projeto e, como sempre, eu criei um repositório Git local para iniciar. Depois de trabalhar nele por vários dias, criando muitos commits, tive que publicá-lo em um repositório central Subversion (que é uma das VCSs que temos). Eu poderia ter feito isso criando uma nova pasta no SVN e adicionando a versão mais recente de todos os arquivos do projeto para ela, mas dessa forma toda a história teria sido perdida, o que eu não gostaria que acontecesse.

Git tem um recurso para trabalhar com repositórios SVN, git-svn, mas que tem a intenção de pegar o código existente a partir do SVN e trabalhar nele, não publicar uma árvore Git existente em um repositório Subversion.

A primeira abordagem bastante ingênua não deu certo (como esperado), mas depois eu descobri como conseguir fazer isso.

Como um teste, vamos primeiro criar um repositório SVN vazio e um repositório Git com alguns commits:

$ svnadmin create repo
$ svn co file:///Users/nicolas/Temp/git_to_svn/repo svn_repo
Checked out revision 0.
$ cd svn_repo
$ svn mkdir trunk tags branches
A         trunk
A         tags
A         branches
$ svn commit -m "Create repository structure"
Adding         branches
Adding         tags
Adding         trunk

Committed revision 1.
$ cd ..

$ mkdir project; cd project
$ git init
Initialized empty Git repository in /Users/nicolas/Temp/git_to_svn/project/.git/
$ echo "foo" > test.txt; git add test.txt; git commit -m "Initial version"
master (root-commit) 88464cf] Initial version
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 test.txt
$ echo "bar" > test.txt; git commit test.txt -m "Second version"
master cb62866] Second version
 1 files changed, 1 insertions(+), 1 deletions(-)

Nós agora podemos configurar o git-svn:

$ git svn init -s file:///Users/nicolas/Temp/git_to_svn/repo/
$ git svn fetch
r1 = 741ab63aea786882eafd38dc74369e651f554c9c (trunk)

Dependendo do layout do seu projeto SVN, você pode precisar deixar de lado o parâmetro -s e adicionar as flags -t, -T ou -B – consulte a página do manual do git-svn.

Um pouco ingênuo seria tentar o push no repositório SVN agora:

$ git svn dcommit
Unable to determine upstream SVN information from HEAD history.
Perhaps the repository is empty. at /opt/local/libexec/git-core/git-svn line 439.

Isso iria falhar, uma vez que o comando git svn não consegue descobrir em quais os commits teria que fazer o push: não há nenhuma ligação entre o nosso repositório Git original e as heads do Subversion.

Para corrigir isso, podemos usar um enxerto Git para fazer a ligação. Nós vamos dizer ao Git que o commit que criou a pasta SVN em que desejamos armazenar o projeto é o commit pai do primeiro commit no nosso repositório Git:

$ git show-ref trunk
741ab63aea786882eafd38dc74369e651f554c9c refs/remotes/trunk
$ git log --pretty=oneline master | tail -n1
88464cfdf549a82b30ee7c52e53e2b310f0d9ec4 Initial version
$ echo "88464cfdf549a82b30ee7c52e53e2b310f0d9ec4 741ab63aea786882eafd38dc74369e651f554c9c" >> .git/info/grafts

Se agora você executar o git log, verá que o SVN commit “Create repository structure” é exibido logo após o nosso commit “Initial version”.

Fazer o push para SVN agora funcionará muito bem:

$ git svn dcommit
Committing to file:///Users/nicolas/Temp/git_to_svn/repo/trunk ...
	A	test.txt
Committed r2
	A	test.txt
r2 = 8c72757dd3a7d550ed8ef393bb74c0350d22dbac (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk
test.txt: locally modified
	M	test.txt
Committed r3
	M	test.txt
r3 = ca0fc06d477bcd4dd5c6f6d2ae6d94356b510280 (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk

Tudo pronto 🙂

***

Nicolas Trangez faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://eikke.com/importing-a-git-tree-into-a-subversion-repository/index.html