Como posso iterar por todos os branches locais em meu repositório usando o script bash. Preciso iterar e verificar se há alguma diferença entre o branch e alguns branches remotos. Ex
for branch in $(git branch);
do
git log --oneline $branch ^remotes/origin/master;
done
Eu preciso fazer algo como o fornecido acima, mas o problema que estou enfrentando é $ (git branch) me dá as pastas dentro da pasta do repositório junto com os branches presentes no repositório.
Esta é a maneira correta de resolver o problema? Ou existe outra maneira de fazer isso?
Obrigado
for b in "$(git branch)"; do git branch -D $b; done
Respostas:
Você não deve usar o branch git ao escrever scripts. Git fornece uma interface de "encanamento" que é explicitamente projetada para uso em scripts (muitas implementações atuais e históricas de comandos normais do Git (adicionar, verificar, mesclar, etc.) usam essa mesma interface).
O comando de encanamento que você deseja é git for-each-ref :
Nota: Você não precisa do
remotes/
prefixo no ref remoto, a menos que você tenha outros refs que causemorigin/master
a correspondência de vários lugares no caminho de pesquisa de nome de ref (consulte “Um nome de ref simbólico.…” Na seção Especificando revisões de git-rev-parse (1) ). Se você está tentando evitar explictly ambigüidade, em seguida, ir com o nome ref completa:refs/remotes/origin/master
.Você obterá uma saída como esta:
Você pode canalizar essa saída para sh .
Se você não gosta da ideia de gerar o código do shell, pode abrir mão de um pouco de robustez * e fazer o seguinte:
* Nomes de ref devem ser protegidos da divisão de palavras do shell (consulte git-check-ref-format (1) ). Pessoalmente, eu ficaria com a versão anterior (código de shell gerado); Estou mais confiante de que nada de impróprio pode acontecer com isso.
Como você especificou o bash e ele oferece suporte a matrizes, você pode manter a segurança e ainda evitar a geração do seu loop:
Você poderia fazer algo semelhante
$@
se não estiver usando um shell que suporte matrizes (set --
para inicializar eset -- "$@" %(refname)
adicionar elementos).fonte
--merged
, eu teria que duplicar a lógica no git branch? Tem que haver uma maneira melhor de fazer isso.git for-each-ref refs/heads | cut -d/ -f3-
git for-each-ref refs/heads --format='%(refname)'
for-each-ref
agora suporta todos os seletores de branch como--merged
egit branch
egit tag
agora estão realmente implementados em termos degit for-each-ref
si mesmos , pelo menos para os casos existentes na lista. (Criar novos branches e tags não é, e não deveria ser, partefor-each-ref
.)Isso ocorre porque
git branch
marca a ramificação atual com um asterisco, por exemplo:então se
$(git branch)
expande para* master mybranch
, por exemplo , e então se*
expande para a lista de arquivos no diretório atual.Não vejo uma opção óbvia para não imprimir o asterisco em primeiro lugar; mas você pode cortá-lo:
fonte
$(git branch | sed -e s/\\*//g)
.3-
solução.$(git branch | sed 's/^..//')
$(git branch | tr -d " *")
O bash embutido
mapfile
, é construído para issotodos os branches do git:
git branch --all --format='%(refname:short)'
todos os branches locais do git:
git branch --format='%(refname:short)'
todos os branches remotos do git:
git branch --remotes --format='%(refname:short)'
iterar por meio de todos os branches do git:
mapfile -t -C my_callback -c 1 < <( get_branches )
exemplo:
para a situação específica do OP:
source: lista todos os branches locais do git sem um asterisco
fonte
Eu itero, por exemplo:
fonte
Eu sugeriria
$(git branch|grep -o "[0-9A-Za-z]\+")
se suas filiais locais fossem nomeadas apenas por dígitos, az e / ou letras AZfonte
A resposta aceita está correta e realmente deve ser a abordagem usada, mas resolver o problema no bash é um ótimo exercício para entender como os shells funcionam. O truque para fazer isso usando o bash sem realizar manipulação de texto adicional é garantir que a saída do git branch nunca seja expandida como parte de um comando a ser executado pelo shell. Isso evita que o asterisco se expanda na expansão do nome do arquivo (etapa 8) da expansão do shell (consulte http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html )
Use a construção bash while com um comando read para dividir a saída do git branch em linhas. O '*' será lido como um caractere literal. Use uma instrução case para fazer a correspondência, prestando atenção especial aos padrões de correspondência.
Os asteriscos na construção do caso bash e na substituição do parâmetro precisam ser escapados com barras invertidas para evitar que o shell os interprete como caracteres de correspondência de padrão. Os espaços também são escapados (para evitar a tokenização) porque você está literalmente combinando '*'.
fonte
A opção mais fácil de lembrar na minha opinião:
git branch | grep "[^* ]+" -Eo
Resultado:
A opção -o do Grep (--only-matching) restringe a saída para apenas as partes correspondentes da entrada.
Visto que nem espaço nem * são válidos em nomes de ramificação Git, isso retorna a lista de ramificações sem os caracteres extras.
Editar: Se você estiver no estado de 'cabeça separada' , você precisará filtrar a entrada atual:
git branch --list | grep -v "HEAD detached" | grep "[^* ]+" -oE
fonte
O que acabei fazendo, aplica-se à sua pergunta (& inspirado pela menção de ccpizza
tr
):git branch | tr -d ' *' | while IFS='' read -r line; do git log --oneline "$line" ^remotes/origin/master; done
(Eu uso muito loops while. Embora para coisas específicas você definitivamente queira usar um nome de variável pontiagudo ["branch", por exemplo], na maioria das vezes estou apenas preocupado em fazer algo com cada linha de entrada. 'linha' aqui em vez de 'ramificação' é um aceno para a capacidade de reutilização / memória / eficiência muscular.)
fonte
Prosseguindo com a resposta de @finn (obrigado!), O seguinte permitirá que você itere nas ramificações sem criar um script de shell intermediário. É robusto o suficiente, desde que não haja novas linhas no nome do branch :)
O loop while é executado em um subshell, o que normalmente é bom, a menos que você esteja definindo variáveis de shell que deseja acessar no shell atual. Nesse caso, você usa a substituição do processo para inverter o tubo:
fonte
Se você estiver neste estado:
E você executa este código:
Você obterá este resultado:
fonte
for b in "$(git branch)"; do git branch -D $b; done
Mantenha simples
A maneira simples de obter o nome do branch em loop usando o script bash.
Resultado:
fonte
Resposta do Googlian, mas sem usar para
fonte
Isso usa os comandos do git plumbing , que são projetados para scripts. Também é simples e padrão.
Referência: conclusão do Bash do Git
fonte