Recebi a seguinte dúvida:
Preciso levar um repositório de um team project para outro, então clonei na minha máquina e apontei para um outro remote, e fiz o push… porém as branch’s do repositório de origem não foram para o destino, o que fazer?
Quando você faz um clone de um repositório, o Git não está fazendo o tracking de todas as branch’s remotas, é preciso baixar elas para poder fazer o push de tudo. Mas se o meu repositório tem dezenas delas, como executar de uma maneira rápida? Usando o poder do Powershell.
Para pegar todas as branch’s é fácil:
git branch -a
Onde o -a lista tanto branch’s locais como remotas.
Dai se poderia interar na coleção de strings:
git branch -a | % {$_ (...)
E então era trabalhar com elas para chegar aos nomes das branch’s e poder executar um checkout.
Porém, consultando o Giovanni Bassi, ele me chamou a atenção para o comando: git ls-remote.
git ls-remote
Este comando lista as referências do repositório remoto, se executarmos no repositório do code-cracker teremos uma longa lista de branch’s (1), pull request’s (2) e tag’s (3):
O objetivo é levar as branch’s para o outro repositório, então vamos usar:
git ls-remote --heads origin
-match e $matches
Agora que temos uma coleção de referências, vamos buscar filtrar somente o nome das branch’s.
Para isso faremos uso do operador de comparação do Powershell -match. Passando o pattern, baseado em RegEx, ‘refs/heads/(.*)’, iremos testar, se a referência na coleção é qualquer coisa que tenha no início da string refs-barra-heads-barra.
git ls-remote --heads origin | % { $_ -match 'refs/heads/(.*)' }
Executando a linha acima, teremos a confirmação de que todas batem com o padrão. Mas… o objetivo não é esse ao usar o -match. O legal é que o Powershell irá criar uma coleção dos matches, com nome de variável $matches, sempre! Essa variável é um hashtable key-value, ou chave-valor, é possível chamá-la na sessão digitando o seu nome:
$matches
Portanto se quisermos só o nome da branch, basta pegar o conteúdo no índice 1!
O que é preciso fazer agora é passar essa coleção para a próxima execução de comando, mas ignorando a resposta da iteração, ou seja os True. Para isso usamos out-null, porém, repassamos os matches para serem processados no próximo pipe, o comando fica assim:
git ls-remote --heads origin | % { $_ -match 'refs/heads/(.*)' | out-null; $matches[1] }
git checkout
Agora só é preciso iterar na coleção de nomes, fazendo o checkout das branch’s.
git ls-remote --heads origin | % { $_ -match 'refs/heads/(.*)' | out-null; $matches[1] } | % { git checkout $_ }
Só mandar o push para o outro remote!
Emmanuel Brandão