Após o Git ter se tornado uma das principais ferramentas para o versionamento de código fonte, muitas equipes estão procurando migrar para o git de outros sistemas de controle de versão, porém, lidar com todo o histórico de alterações, tags e branchs pode tornar-se uma dor de cabeça.

Hoje vamos falar sobre a migração de repositórios SVN para GIT.

Este post foi inspirado em um trabalho que realizei recentemente, migrando um fonte com mais de 300Mb em SVN para o GIT. Este trabalho foi feito utilizando uma máquina rodando Windows 10, e, por vezes, utilizei o Bash for Windows. Por conta disso, você verá comandos que serão feitos utilizando o bash e outros feitos utilizando o powershell

O git possuí uma ferramenta para a importação de repositórios SVN, incluindo todo o histórico de alterações no código fonte. Se você estiver utilizando uma máquina Windows, não é necessário fazer instalações adicionais para utilizar a ferramenta git svn via linha de comando, porém, em uma máquina utilizando Ubuntu (ou utilizando o bash dentro do Windows) talvez seja necessário instalar alguns pacotes. Faça estas instalações com o comando

sudo apt-get install git-core git-svn

Em meus testes, a utilização do bash provou-se mais rápida que o mesmo comando utilizando o powershell. Portanto, recomendo que continue no bash enquanto executa o comando de clone do repositório:

SECONDS=0 && git svn clone <caminho para o repositório> <Pasta onde será feito o clone> --stdlayout -r2000:HEAD && echo $SECONDS`

O parâmetro r2000:HEAD irá limitar o histórico para a revisão 2000 até a atual. Este comando, em um repositório com 3856 commits levou cerca de 1h10m.

No SVN, uma tag é uma branch, portanto, após o clone do repositório, quando rodamos o comando

git tag -l

não iremos ver nenhuma TAG, porém, se rodarmos o comando

git branch -r

vamos observar que as branchs remotas (que são as tags do SVN) estarão lá. Para criar tags do git, de acordo com as tags do SVN, rode o seguinte comando na pasta de seu repositório (powershell):

git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags | %{$tag = $_ -split "/" -split " "; 
git tag -a -m 'Import tag from svn' $($tag[1]) $($tag[2])}

Aqui estamos iterando em cada branch remota do nosso repositório e criando uma tag apontando para o commit que esta “branch de tag” esta apontando.

Após isso, precisamos criar branchs locais do git que referencie as reais branchs do nosso repositório SVN. O processo para fazer isso é um pouco mais complexo:

$todasBranchs = git for-each-ref refs/remotes;
$branchsTags = git for-each-ref refs/remotes/origin refs/remotes/tags;
$branchs = New-Object System.Collections.ArrayList;
foreach ($b in $todasBranchs) { if ($branchsTags.contains($b) -eq $false) {$branchs.add($b)}};
$branchs | %{$b = $_ -split '/'; git checkout -b $($b[2]) refs/$($b[1])/$($b[2]); git checkout master}

Após este comando, poderemos observar que os comandos

git tag -l

e

git branch -v

irão se comportar da forma esperada. Estes comandos irão transformar todas as branchs atuais do SVN em branchs no seu repositório git. Caso não seja isso que queira fazer, execute o comando

git checkout <nome da branch> refs/remotes/<nome da branch>

somente para as branchs que você quer manter em seu repositório git. Lembre-se sempre das boas práticas para repositórios git e não mantenha branchs que não são necessárias ou estão a muito tempo sem atualizações.

Não se esqueça do arquivo .gitignore

Lembre-se que o git é uma ferramenta de controle de versão que, por sua natureza, não lida bem com arquivos grandes e/ou arquivos binários, portanto, não deixe de incluir o arquivo .gitignore mais apropriado para o seu código fonte. Isso será assunto para outro post, porém, para garantir que o arquivo .gitignore esta fazendo o seu trabalho corretamente, execute os seguintes comandos:

git rm -r --cached .
git add .
git commit -m "Aplicando o arquivo .gitignore"

Com o repositório em ordem, você poderá fazer o push do seu repositório para o repositório remoto:

git remote add origin <url do repositório remoto>
git push origin --all; git push origin --tags #por padrão o comando git push não empurra as tags para o repositório remoto

(Cross-post de http://blog.gersondias.net/Importando-Repositorios-SVN-GIT/)