Migrando repositorio Git
Luiz Bernardo
Posted on March 22, 2023
Com as constantes aquisições de empresas no mercado de TI é bem comum ter que migrar o repositório de código que estava em um repositório remoto para outro, às vezes em produtos diferentes.
Pensando no cenário de migração de repositório remoto de soluções diferentes, do GitHub para o Azure Devops, por exemplo, a migração pode se tornar um pouco mais complexa. Veja, você precisa migrar o histórico do projeto por completo com branchs, tags e notes.
Primeiro, crie o repositório de destino para nossa migração, vamos utilizar ele no script.
Para isso criei um pequeno script bash na qual vou explicar aqui linha a linha antes de mostrar por completo, vejamos:
set -eufo pipefail
O comando "set -eufo pipefail" é um conjunto de opções que pode ser usado em scripts de shell, como o Bash, para modificar o comportamento padrão do ambiente do shell.
Uma explicação mais detalhada de cada uma das opções incluídas no comando:
- "set -e": Encerra o script imediatamente caso um comando falhe ou retorne um status diferente de zero. Isso ajuda a evitar que erros passem despercebidos e ajuda a garantir que o script pare em caso de falha.
- "set -u": Faz com que o shell gere um erro caso uma variável não definida seja referenciada. Isso pode ajudar a evitar erros que possam ocorrer quando uma variável é usada sem ter sido previamente inicializada.
- "set -f": Desativa a expansão de nomes de arquivos com caracteres curinga (como * e ?), o que pode ser útil em scripts que lidam com arquivos com nomes não convencionais ou que podem conter espaços ou outros caracteres especiais.
- "set -o pipefail": Faz com que um pipeline (comando composto por vários comandos conectados com o operador |) retorne o status de saída do último comando que falhou, em vez de retornar o status de saída do último comando executado com sucesso. Isso pode ser útil em pipelines complexos, onde é importante detectar falhas em qualquer ponto do pipeline.
O comando "set -eufo pipefail" ajuda a garantir que o script seja executado de forma confiável e consistente, evitando erros comuns que podem levar a falhas ou a comportamentos inesperados. Ele é especialmente útil em scripts que executam tarefas críticas ou lidam com dados sensíveis, onde a confiabilidade é essencial.
SOURCE_URL=https://repositorio_git_origem.git
TARGET_URL=https://repositorio_git_alvo.git
SOURCE_URL será a URL Git do repositório que queremos copiar
TARGET_URL será a URL Git do repositório alvo que queremos que fique igual ao repositório da SOURCE_URL
WORKDIR=./repos
Apenas para organização criei um diretório de trabalho local.
echo "Cloning from ${SOURCE_URL} into ${WORKDIR}..."
git init --bare "${WORKDIR}"
cd "${WORKDIR}"
O –bare cria um repositório vazio. Se GIT_DIRo ambiente não estiver definido, ele será definido no diretório de trabalho atual. Ao incializar um repositório como bare não será permitido editar arquivos (git add) e commitar mudanças (git commit), já que o mesmo não possui uma working tree.
Utilizo o –bare para garantir que não tenha nenhuma mudança no meio do processo de migração.
git config remote.origin.url "${SOURCE_URL}"
Esse comando é utilizado para definir a URL de um repositório Git remoto
git config --add remote.origin.fetch '+refs/heads/*:refs/heads/*'
O comando git config --add remote.origin.fetch adicionam uma nova configuração no git para o repositório atual.
O parâmetro --add diz ao git para adicionar essa configuração em vez de substituir configurações existentes.
remote.origin.fetch define o nome da configuração que está sendo adicionada. Essa configuração especifica como o Git deve buscar as alterações dos ramos do repositório remoto (chamado de "origin").
O valor '+refs/heads/:refs/heads/' é uma expressão que especifica que o git deve buscar todas as branches (ramificações) do repositório remoto. O primeiro * representa todas as branches no repositório remoto, e o segundo * representa todas as branches locais no repositório local. O sinal de + antes de refs/heads/* indica que, além de buscar os branches existentes, também deve-se adicionar novos branches que possam ser criados no repositório remoto.
Essa configuração diz ao git para buscar todas as branches do repositório remoto chamado "origin" e adicioná-las ao repositório local.
git config --add remote.origin.fetch '+refs/tags/*:refs/tags/*'
O sinal de + antes de refs/tags/* indica que, além de buscar as tags existentes, também deve-se adicionar novas tags que possam ser criadas no repositório remoto.
Essa configuração diz ao git para buscar todas as tags do repositório remoto chamado "origin" e adicioná-las ao repositório local.
git config --add remote.origin.fetch '+refs/notes/*:refs/notes/*'
O sinal de + antes de refs/notes/* indica que, além de buscar as notas existentes, também deve-se adicionar novas notas que possam ser criadas no repositório remoto.
Essa configuração diz ao git para buscar todas as notas do repositório remoto chamado "origin" e adicioná-las ao repositório local.
git config remote.origin.mirror true
A opção mirror é usada para especificar se o repositório local deve espelhar todos os dados do repositório remoto. Quando essa opção é definida como true, isso indica que todas as alterações feitas no repositório remoto devem ser automaticamente sincronizadas com o repositório local.
Quando essa opção está ativada, todas as operações de push, fetch e pull serão direcionadas ao repositório remoto origin, e o repositório local será atualizado automaticamente para refletir todas as alterações no repositório remoto, ou seja, define que o repositório remoto origin deve ser espelhado no repositório local e que todas as alterações no repositório remoto devem ser automaticamente sincronizadas com o repositório local.
git fetch --all
Este comando é usado para atualizar todas as referências de um repositório local com as alterações mais recentes do repositório remoto.
O parâmetro --all indica que o comando deve buscar atualizações para todas as branches (ramificações), tags e notas no repositório remoto.
Quando executado, o comando git fetch --all irá buscar todas as alterações no repositório remoto, mas não as mesclar automaticamente com a branch atual. Em vez disso, ele atualizará as referências locais para refletir as alterações mais recentes no repositório remoto.
Isso é útil quando você deseja verificar o estado atual do repositório remoto sem mesclar as alterações com seu repositório local.
echo ""
echo "Cloned to ${WORKDIR}; pushing to ${TARGET_URL}"
Apenas um print para deixar tudo mais visual
git push --mirror "${TARGET_URL}"
Ao executar o comando git push --mirror "${TARGET_URL}", o Git irá enviar todas as alterações do repositório local para o repositório remoto especificado, sobrescrevendo quaisquer alterações existentes e excluindo referências que não existem mais no repositório local.
echo ""
echo "Cleaning up temporary directory ${WORKDIR}..."
Mais anotações para deixar visível a conclusão da execução.
rm -rf "${WORKDIR}"
Remoção do diretorio de trabalho.
Com isso passamos por todos os comandos do script e seu repositório foi migrado na íntegra =D
Abaixo o script completo.
echo "Done."
bla bla bla
#!/bin/sh
set -eufo pipefail
SOURCE_URL=https://repositorio_git_origem.git
TARGET_URL=https://repositorio_git_alvo.git
WORKDIR=./repos
echo "Cloning from ${SOURCE_URL} into ${WORKDIR}..."
git init --bare "${WORKDIR}"
cd "${WORKDIR}"
git config remote.origin.url "${SOURCE_URL}"
git config --add remote.origin.fetch '+refs/heads/*:refs/heads/*'
git config --add remote.origin.fetch '+refs/tags/*:refs/tags/*'
git config --add remote.origin.fetch '+refs/notes/*:refs/notes/*'
git config remote.origin.mirror true
git fetch --all
echo ""
echo "Cloned to ${WORKDIR}; pushing to ${TARGET_URL}"
git push --mirror "${TARGET_URL}"
echo ""
echo "Cleaning up temporary directory ${WORKDIR}..."
rm -rf "${WORKDIR}"
echo "Done."
Posted on March 22, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.