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