Como posso ver quais ramificações do Git estão rastreando qual ramificação remota / upstream?

825

Eu sei que posso fazer git branch --all , e isso me mostra ramificações locais e remotas, mas não é tão útil para me mostrar o relacionamento entre elas.

Como listar ramificações de uma maneira que mostre qual ramificação local está rastreando qual remoto?

joachim
fonte

Respostas:

1146

Um comando de porcelana, não é bom se você deseja isso para scripts:

git branch -vv   # doubly verbose!

Observe que, com o git 1.8.3, esse ramo upstream é exibido em azul (consulte " O que esse ramo está rastreando (se houver) no git? ")


Se você deseja uma saída limpa, consulte a resposta do arcresu - ele usa um comando de porcelana que não acredito que existia no momento em que escrevi essa resposta originalmente, por isso é um pouco mais conciso e funciona com ramificações configuradas para rebase, não apenas para mesclagem.

Cascabel
fonte
3
O primeiro método acima não fornece as informações desejadas para mim. O segundo ... parece exagero, especialmente porque a resposta de Kubi funciona. Estou esquecendo de algo?
precisa saber é
3
@garyp Você não foi quem fez a pergunta. O primeiro forneceu o que o OP precisava, e o segundo forneceu exatamente o que ele precisava, caso ele o desejasse de forma limpa para scripts ou apenas o salvasse como um alias. ("Overkill" é bom se você conseguir o que deseja e não precisar repeti-lo.) Do ponto de vista desta pergunta, a resposta do kubi fornece algumas informações estranhas e, se houver mais de um controle remoto, ele não mostre tudo, mas se ele atender às suas necessidades, use-o.
Cascabel
2
Eu devo desculpas. Quando eu originalmente correu o primeiro método, eu tenho nenhuma informação sobre o que controla o quê, e eu deveria ter declarado que explicitamente. Mas agora vejo as informações de rastreamento, por isso devo ter algo errado com minha configuração. Então estava faltando alguma coisa.
precisa saber é
2
FWIW Fiquei confuso porque -v e -vv mostram uma saída semelhante. A ramificação rastreada é mostrada entre colchetes após o hash e antes da confirmação mais recente (na minha instalação padrão do OSX homebrew).
jerclarke
3
Tudo isso para mim é imprimir o último hash de confirmação e comentar para cada ramificação.
capybaralet
263

git remote show origin

Substitua 'origem' por qualquer que seja o nome do seu controle remoto.

kubi
fonte
11
Mesmo que esse comando de porcelana funcione para um humano (não tanto para um script, como teria que analisar a saída de porcelana), o que eu não gosto nessa abordagem é que o git remote showcomando realmente se conecta ao repositório remoto ... e, portanto, não se acontecer de você estar off-line ou incapaz de se conectar à repo por qualquer motivo ...
pvandenberk
17
@pvandenberk Você pode usar git remote show -n originpara obter algumas informações, mesmo quando estiver offline. Na documentação do git remote : "Com a opção -n, os cabeçotes remotos não são consultados primeiro com git ls-remote <name>; as informações em cache são usadas."
Cerran
5
Uma coisa estranha sobre esse comando: lista as ramificações remotas como "rastreadas", mesmo se não houver ramificações locais configuradas para pull / push. Eu sempre acho isso confuso. Na verdade, não sei ao certo o que "rastreado" deve significar nesta saída. Os docs git sobre o assunto fazê-lo soar como uma filial remota é "monitorado" apenas quando é ligada / vinculada a uma filial local para empurrar / puxar ...
Hawkeye Parker
O problema é que eu preciso chamar isso para todos os nomes remotos até ver o que estou realmente procurando.
jolvi
2
@jolvi Você pode correr git remote show | xargs git remote show -npara visualizar as informações de rastreamento combinadas de todos os controles remotos.
Synoli 20/05
107

Se você olhar para a página de manual git-rev-parse, verá a seguinte sintaxe descrita:

<branchname>@{upstream}por exemplo master@{upstream},@{u}

O sufixo @{upstream}para um nome da ramificação (formato abreviado <branchname>@{u}) refere-se à ramificação que a ramificação especificada por nome da ramificação está configurada para construir. Um nome de filial ausente é padronizado como o atual.

Portanto, para encontrar a montante do ramo master, você faria:

git rev-parse --abbrev-ref master@{upstream}
# => origin/master

Para imprimir as informações de cada filial, você pode fazer algo como:

while read branch; do
  upstream=$(git rev-parse --abbrev-ref $branch@{upstream} 2>/dev/null)
  if [[ $? == 0 ]]; then
    echo $branch tracks $upstream
  else
    echo $branch has no upstream configured
  fi
done < <(git for-each-ref --format='%(refname:short)' refs/heads/*)

# Output:
# master tracks origin/master
# ...

Isso é mais limpo do que analisar refs e config manualmente.

Carl Suster
fonte
Eu não conseguia entender esse trecho em revisão, apesar de encontrá-lo, então obrigado pela explicação clara!
Alice Purcell #
3
Para aqueles que usam git-flow, com ramificações denominadas "feature / blahblah", a instrução de fechamento do loop while deve ser: done < <(git for-each-ref --format='%(refname:short)' refs/heads/**)Observe os dois asteriscos no final do padrão glob.
Markeissler
2
git rev-parse --abbrev-ref HEAD@{upstream}parece funcionar bem para o ramo atual. Também cria um bom alias para o git.
22717 Digikata
A whilesintaxe do loop parece um pouco estranha para mim. Você pode usar apenas o git for-each-ref ... | while read branch; do ...que não precisa de um FIFO e é executado na mesma ordem que os comandos escritos.
Daniel Böhmer
Pelo menos desde git 2.5.1, você tem um one-liner comgit for-each-ref --format='%(refname:short) tracks %(upstream:short)' refs/heads/*
Mat M
81

Uma alternativa à resposta do kubi é dar uma olhada no .git/configarquivo que mostra a configuração do repositório local:

cat .git/config

Abizern
fonte
6
Também git config --get-regex branch
Tamir Daniely
6
Ou, mais especificamente, 'git config --get-regexp branch. * Merge'
yoyo
41
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

mostrará uma linha para cada filial local. Um ramo de rastreamento será semelhante a:

master <- origin/master

Um sem rastreamento será parecido com:

test <- 
Aurelien
fonte
Bom, para adicionar alguma saída de ordenação e TAB-bed: git for-each-ref --sort upstream --format = '% (refname: short)% 09 <-% (upstream: short)' refs / heads
dimir
Lindamente conciso e a saída é realmente muito mais legível do que a aceita git branch -vv. J
joki
O único problema é que eu não consigo me lembrar isso, então eu useigit config --global alias.track 'for-each-ref --format='\''%(refname:short) <- %(upstream:short)'\'' refs/heads'
joki
38

Para a ramificação atual , aqui estão duas boas opções:

% git rev-parse --abbrev-ref --symbolic-full-name @{u}
origin/mainline

ou

% git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
origin/mainline

Essa resposta também está aqui , para uma pergunta um pouco diferente que foi (erroneamente) marcada como duplicada.

cdunn2001
fonte
5
Com base nisso, todos os ramos podem ser listados de uma forma amigável script: git for-each-ref --shell --format='%(refname:short) %(upstream:short)' refs/heads.
Daniel James
15

Para a ramificação atual, você também pode dizer git checkout(sem ramificação). Este é um no-op com efeitos colaterais para mostrar as informações de rastreamento, se existir, do ramo atual.

$ git checkout 
Your branch is up-to-date with 'origin/master'.
Eugene Yarmash
fonte
É justo, mas você pode digitar acidentalmente git checkout ., o que não é um não-op.
Tomasz Gandor
6

Eu uso esse apelido

git config --global alias.track '!f() { ([ $# -eq 2 ] && ( echo "Setting tracking for branch " $1 " -> " $2;git branch --set-upstream $1 $2; ) || ( git for-each-ref --format="local: %(refname:short) <--sync--> remote: %(upstream:short)" refs/heads && echo --Remotes && git remote -v)); }; f'

então

git track
Olivier Refalo
fonte
5
Eu acho que vale a pena notar que, com dois parâmetros, seu comando configura um branch branch.
albfan
3

Com base na resposta de Olivier Refalo

if [ $# -eq 2 ] 
then
    echo "Setting tracking for branch " $1 " -> " $2
    git branch --set-upstream $1 $2
else
    echo "-- Local --" 
    git for-each-ref --shell --format="[ %(upstream:short) != '' ] && echo -e '\t%(refname:short) <--> %(upstream:short)'" refs/heads | sh
    echo "-- Remote --" 
    REMOTES=$(git remote -v) 
    if [ "$REMOTES" != '' ]
    then
        echo $REMOTES
    fi  
fi

Mostra apenas local com a faixa configurada.

Escreva em um script chamado git-track no seu caminho e você receberá um comando git track

Uma versão mais elaborada em https://github.com/albfan/git-showupstream

albfan
fonte
1

git config --get-regexp "branch\.$current_branch\.remote"

lhe dará o nome do controle remoto que está sendo rastreado

git config --get-regexp "branch\.$current_branch\.merge"

fornecerá o nome da ramificação remota que está sendo rastreada.

Você precisará substituir $ current_branch pelo nome da sua filial atual. Você pode conseguir isso dinamicamente comgit rev-parse --abbrev-ref HEAD

O mini-script a seguir combina essas coisas. Cole-o em um arquivo chamadogit-tracking , torne-o executável e verifique se ele está no seu caminho.

então você pode dizer

$ git  tracking
<current_branch_name>-><remote_repo_name>/<remote_branch_name>

observe que o nome da filial remota pode ser diferente do nome da filial local (embora geralmente não seja). Por exemplo:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

como você pode ver no código, a chave para isso é extrair os dados da configuração do git. Eu apenas uso sed para limpar os dados estranhos.

#!/bin/sh

current_branch=$(git rev-parse --abbrev-ref HEAD)
remote=$(git config --get-regexp "branch\.$current_branch\.remote" | sed -e "s/^.* //")
remote_branch=$(git config --get-regexp "branch\.$current_branch\.merge" | \
  sed -e "s/^.* //" -e "s/refs\/.*\///")

echo "$current_branch -> $remote/$remote_branch"
masukomi
fonte
1

Aqui está um puro e simples. Pode verificar git remote -v, que mostra toda a origem e a montante da ramificação atual.

MJeremy
fonte