Migrando de SVN/Mercurial para Git: ferramentas e estratégias

1. Planejamento da Migração

Antes de iniciar qualquer conversão, é essencial planejar cuidadosamente cada etapa. A migração de um sistema de controle de versão centralizado (SVN) ou descentralizado (Mercurial) para Git envolve decisões que impactam diretamente a integridade do histórico e a produtividade da equipe.

1.1. Avaliação do repositório atual

Levante informações sobre o repositório de origem: número de commits, branches ativos, tags, quantidade de autores e tamanho total. Ferramentas como svn info e hg summary ajudam nesse diagnóstico. Identifique também arquivos binários grandes que podem exigir Git LFS após a migração.

1.2. Escolha da ferramenta de conversão

Para SVN, a ferramenta oficial é git-svn, distribuída com o próprio Git. Para Mercurial, recomenda-se hg-fast-export (parte do projeto git-remote-hg). Avalie também alternativas como svn2git (Ruby) para SVN com layout complexo.

1.3. Preparação do ambiente de destino

Configure o Git com suas credenciais e crie um repositório remoto vazio (GitHub, GitLab ou servidor próprio). Decida se fará migração incremental ou corte definitivo.

# Exemplo de configuração inicial
git config --global user.name "Seu Nome"
git config --global user.email "seu@email.com"

2. Migração de SVN para Git com git-svn

2.1. Clonagem incremental do repositório SVN

O comando git svn clone baixa todo o histórico do SVN e o converte para commits Git. Use -s para layout padrão (trunk, branches, tags) ou --stdlayout explicitamente.

# Clonagem de repositório SVN com layout padrão
git svn clone https://svn.exemplo.com/projeto -s projeto-git
cd projeto-git

Para repositórios com muitos commits, use -r para clonar apenas revisões recentes e depois buscar o restante incrementalmente.

2.2. Mapeamento de autores e branches SVN

Crie um arquivo authors.txt no formato:

joao = João Silva <joao@exemplo.com>
maria = Maria Souza <maria@exemplo.com>

Passe o arquivo durante a clonagem:

git svn clone https://svn.exemplo.com/projeto -s --authors-file=authors.txt projeto-git

Branches SVN são convertidos automaticamente para branches Git. Tags SVN viram branches de tag; posteriormente você pode convertê-las em tags Git leves ou anotadas.

2.3. Finalização e limpeza

Remova os metadados SVN e envie para o repositório remoto:

git svn fetch
git branch -r  # lista branches remotas SVN
git push origin --all
git push origin --tags

Para limpar referências SVN, use git svn gc e remova a configuração remota SVN com git config --remove-section svn.

3. Migração de Mercurial para Git com hg-fast-export

3.1. Instalação e preparação do ambiente

Clone o repositório git-remote-hg (ou hg-fast-export) e instale as dependências:

git clone https://github.com/frej/fast-export.git
cd fast-export
# Dependências: Python, Mercurial, Git
pip install mercurial

3.2. Execução da conversão

Crie um diretório vazio para o repositório Git de destino e execute o script:

mkdir projeto-git
cd projeto-git
git init
../fast-export/hg-fast-export.sh -r /caminho/para/repositorio-hg

O script converte todo o histórico, preservando branches, bookmarks e tags. Use -A authors.txt para mapear autores.

3.3. Verificação pós-conversão

Após a conversão, verifique a integridade:

git log --oneline | head -5
git branch -a
git tag -l

Compare o número de commits com o repositório Mercurial original. Se houver discrepância, revise o arquivo de mapeamento de autores.

4. Estratégias para Preservação do Histórico

4.1. Conversão de commits e mensagens

Tanto git-svn quanto hg-fast-export preservam autor, data e mensagem originais. Certifique-se de que o fuso horário seja mantido corretamente.

4.2. Tratamento de branches e tags

Branches SVN com nomes como branches/feature-x viram branches Git feature-x. Tags SVN (diretório tags/) viram branches tag/; converta-os para tags Git:

git for-each-ref refs/remotes/origin/tags | while read sha1 type ref; do
  git tag -a -m "Tag migrada" "${ref#refs/remotes/origin/tags/}" "$sha1"
done

4.3. Lidando com merge commits e conflitos

Em repositórios SVN com merges manuais, git-svn pode não detectar todos os pais. Use --follow-parent para melhor rastreamento. Para Mercurial, merges são convertidos naturalmente.

5. Pós-Migração: Validação e Ajustes

5.1. Verificação de integridade

Execute git fsck para detectar objetos corrompidos:

git fsck --full

Compare o hash do último commit com uma referência confiável. Se possível, faça um diff entre a árvore de trabalho do repositório original e do convertido.

5.2. Correção de autores e metadados

Use git filter-repo (recomendado) para ajustes em massa:

git filter-repo --mailmap <(echo "Nome Antigo <email_antigo> Nome Novo <email_novo>")

Evite git filter-branch em repositórios grandes, pois é lento e propenso a erros.

5.3. Documentação e comunicação

Atualize o README com os novos comandos Git, revise pipelines de CI/CD e agende treinamentos para a equipe. Crie um guia de transição com exemplos práticos.

6. Boas Práticas e Armadilhas Comuns

6.1. Evitando perda de histórico

Sempre faça backup completo do repositório original antes de qualquer conversão. Use git clone --mirror para criar uma cópia exata do repositório Git convertido.

6.2. Problemas com arquivos grandes e binários

Após a migração, migre arquivos grandes para Git LFS:

git lfs migrate import --include="*.psd,*.zip" --everything

Verifique o tamanho do repositório com git count-objects -vH.

6.3. Migração contínua vs. corte definitivo

Se a equipe ainda usa SVN/Hg, planeje um período de congelamento. Alternativamente, use git svn fetch para sincronizar alterações incrementais até o corte final.

7. Casos Especiais e Ferramentas Alternativas

7.1. Repositórios SVN com layout não padrão

Use opções específicas para mapear diretórios:

git svn clone https://svn.exemplo.com/projeto \
  --trunk=main --branches=releases --tags=versions \
  projeto-git

7.2. Migração de Mercurial com extensões

Extensões como evolve e mq (patch queues) podem complicar a conversão. Para mq, exporte patches manualmente antes de converter. Para evolve, use hg evolve --cleanup antes da migração.

7.3. Ferramentas complementares

Considere git-remote-svn para acesso bidirecional (leitura/escrita) entre Git e SVN. svn2git (versão Ruby) é útil para repositórios SVN com histórico muito antigo. cvs2git atende quem ainda usa CVS.

Referências