Contexto
Durante uma migração de SVN para Git, enfrentei a seguinte situação:
No SVN, quando um branch é criado, ele contém um único commit sendo a base de código inteira.
No Git, um branch é apenas um link simbólico (tipo de) para um commit. Portanto, quando um branch é criado a partir do master, o histórico do branch é igual ao do master.
Depois de migrar os branches SVN no repositório Git, cada branch tinha um ponto de partida diferente, o que complicou as coisas quando o branch teve que ser mesclado de volta no master (muitos conflitos de arquivos existentes em ambos os branches).
Então eu escrevi um script para recriar o branch com base no commit a partir do qual foram criados.
Explicações
Obtenha o primeiro commit da filial
Primeiro, eu tive que encontrar o primeiro commit do branch:
BRANCH_FIRST_COMMIT=`git rev-list $BRANCH | tail -n 1`
Encontre o commit de onde BRANCH_FIRST_COMMIT vem
Então, eu tive que encontrar no pai, quando o ramo foi criado. Para isso, fiz um loop na lista de rev do alvo a partir do último:
COMMIT=$TARGET
DIFF='1'
while [ ! -z "$DIFF" ]
do
COMMIT=`git rev-list $COMMIT^ | head -n 1`
DIFF=`git diff $BRANCH_FIRST_COMMIT $COMMIT | head -n 1`
done
Recrie a filial
Uma vez que o commit foi encontrado, eu recriei o branch deste commit. Eu fiz isso criando um novo branch e selecionando todos os commits do branch original (exceto o primeiro, que é a criação do branch) no recém-criado:
git branch tmp-$BRANCH $COMMIT
git checkout tmp-$BRANCH
git rev-list $BRANCH_FIRST_COMMIT..$BRANCH | tac | awk 'NR > 0 { print }' | xargs -I [] sh -c "git cherry-pick []"
Substitua os ramos
Por fim, substituí o branch original pelo recém-criado:
git checkout $BRANCH
git branch -m $BRANCH-old
git checkout tmp-$BRANCH
git branch -m $BRANCH
Versão global
O script completo pode ser encontrado em https://gist.github.com/padawin/9899f82913d237c1fd5c