Как я могу увидеть, какие ветви Git отслеживают, какая ветка удаленной / восходящей?

825

Я знаю, что могу сделать git branch --all, и это показывает мне как локальные, так и удаленные ветви, но это не так полезно, чтобы показать мне отношения между ними.

Как мне перечислить ветви таким образом, чтобы показать, какая локальная ветвь отслеживает, какая удаленная?

Иоахим
источник

Ответы:

1146

Очень фарфоровая команда, не очень хорошая, если вы хотите это для сценариев:

git branch -vv   # doubly verbose!

Обратите внимание, что в git 1.8.3 эта ветвь вверх по течению отображается синим цветом (см. « Что это за отслеживание веток (если есть) в git? »)


Если вы хотите получить чистый вывод, посмотрите ответ arcresu - он использует фарфоровую команду, которая, как мне кажется, не существовала в то время, когда я изначально писал этот ответ, поэтому он немного более лаконичен и работает с ветвями, настроенными для rebase, а не просто для слияния.

Cascabel
источник
3
Первый способ, описанный выше, не дает мне желаемой информации. Второй ... кажется излишним, особенно после ответа Куби. Я что-то пропустил?
garyp
3
@garyp Ты не тот, кто задал вопрос. Первый предоставил то, что нужно ОП, а второй предоставил именно то , что ему нужно, на тот случай, если он хочет в чистом виде для сценариев или хочет просто сохранить его как псевдоним. («Overkill» - это хорошо, если он дает вам то, что вы хотите, и вам не нужно его повторять.) С точки зрения этого вопроса, ответ Куби дает некоторую постороннюю информацию, а если есть более одного пульта, он не не показывает все, но если оно отвечает вашим потребностям, обязательно используйте его.
Каскабель
2
Я должен извиниться. Когда я впервые запустил первый метод, я не получил никакой информации о том, что отслеживает, и я должен был это четко указать. Но теперь я вижу информацию об отслеживании, поэтому, должно быть, у меня что-то не так с настройкой. Так что я был что - то не хватает.
garyp
2
Я был сбит с толку, потому что -v и -vv показывают такой похожий вывод. Отслеживаемая ветка отображается в квадратных скобках после хеша и перед самой последней фиксацией (при моей домашней установке OSX по умолчанию).
Джеркларк
3
Для меня все это - распечатать последний хеш коммита и комментарий для каждой ветки.
Капибаралет
263

git remote show origin

Замените «origin» на имя вашего пульта.

куби
источник
11
Несмотря на то, что эта команда фарфора работает для человека (не столько для сценария, сколько для анализа выходных данных фарфора), мне не нравится в этом подходе то, что git remote showкоманда фактически подключается к удаленному репо ... и, следовательно, он потерпит неудачу, если вы оказались вне сети или по какой-либо причине не можете подключиться к репо ...
pvandenberk
17
@pvandenberk Вы можете использовать, git remote show -n originчтобы получить некоторую информацию даже в автономном режиме. Из документации по git remote : «С опцией -n удаленные заголовки сначала не запрашиваются с помощью git ls-remote <name>; вместо этого используется кэшированная информация».
Серран
5
Одна странная вещь в этой команде: она перечисляет удаленные ветви как «отслеженные», даже если нет локальной ветви, настроенной для pull / push. Я всегда нахожу это запутанным. Я на самом деле не ясно, что "отслеживается" должен означать в этом выводе. Git docs на предмет заставляет это звучать так, как будто удаленная ветка «отслеживается», только когда она связана / привязана к локальной ветке для push / pull ...
Hawkeye Parker
Проблема в том, что мне нужно вызывать это для всех удаленных имен, пока я не увижу то, что на самом деле ищу.
jolvi
2
@jolvi Вы можете запустить, git remote show | xargs git remote show -nчтобы просмотреть объединенную информацию отслеживания для всех пультов.
Синоли
107

Если вы посмотрите на справочную страницу git-rev-parse, вы увидите следующий синтаксис:

<branchname>@{upstream}например master@{upstream},@{u}

Суффикс @{upstream}к branchname (краткая форма <branchname>@{u}) относится к ветви, над которой ветвь, указанная в branchname, установлена. Отсутствующее фирменное имя по умолчанию соответствует текущему.

Следовательно, чтобы найти восходящую ветку master, вы должны сделать:

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

Чтобы распечатать информацию для каждой ветви, вы можете сделать что-то вроде:

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
# ...

Это чище, чем разбор ссылок и настроек вручную.

Карл Сустер
источник
Я не мог понять этот бит в rev-parse, несмотря на то, что нашел его, так что спасибо за ясное объяснение!
Алиса Перселл,
3
Для тех из нас, кто использует git-flow с ветвями с именем «feature / blahblah», закрывающий оператор цикла while должен иметь следующий вид: done < <(git for-each-ref --format='%(refname:short)' refs/heads/**)обратите внимание на две звездочки в конце шаблона glob.
Markeissler
2
git rev-parse --abbrev-ref HEAD@{upstream}кажется, хорошо работает для текущей ветви. Это также делает для хорошего псевдонима мерзавца.
Digikata
whileСинтаксис цикла выглядит немного странно для меня. Вы можете просто использовать тот, git for-each-ref ... | while read branch; do ...который не нуждается в FIFO и работает в том же порядке, что и написанные команды.
Даниэль Бёмер
По крайней мере, с git 2.5.1 у вас есть однострочник сgit for-each-ref --format='%(refname:short) tracks %(upstream:short)' refs/heads/*
Mat M
81

Альтернатива ответу kubi - взглянуть на .git/configфайл, который показывает конфигурацию локального репозитория:

cat .git/config

Abizern
источник
6
Также git config --get-regex branch
Тамир Даниели
6
Или, более конкретно, 'git config --get-regexp branch. * Merge'
yoyo
41
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

покажет линию для каждого местного филиала. Отслеживающая ветка будет выглядеть так:

master <- origin/master

Не отслеживающий будет выглядеть так:

test <- 
Орельен
источник
Хорошо, добавить немного порядка и вывода в TAB-слое: git for-each-ref --sort upstream --format = '% (refname: short)% 09 <-% (upstream: short)' refs / heads
dimir
Красиво сжатый и вывод на самом деле гораздо более читабельным, чем принято git branch -vv. 🙏
Joki
Единственная проблема заключается в том , что я не могу вспомнить это, так что я использовалgit config --global alias.track 'for-each-ref --format='\''%(refname:short) <- %(upstream:short)'\'' refs/heads'
Joki
38

Для текущей ветки есть два хороших варианта:

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

или

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

Этот ответ также здесь , на немного другой вопрос, который был (ошибочно) отмечен как дубликат.

cdunn2001
источник
5
Исходя из этого, все ветви могут быть перечислены в сценарий безвредным: git for-each-ref --shell --format='%(refname:short) %(upstream:short)' refs/heads.
Даниэль Джеймс
15

Для текущей ветви вы также можете сказать git checkout(без любой ветви). Это неоперация с побочными эффектами для отображения информации об отслеживании, если она существует, для текущей ветви.

$ git checkout 
Your branch is up-to-date with 'origin/master'.
Евгений Ярмаш
источник
Справедливо, но вы можете случайно набрать git checkout ., что не является запретом.
Томаш Гандор
6

Я использую этот псевдоним

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'

тогда

git track
Оливье Рефало
источник
5
Думаю, стоит отметить, что с двумя параметрами ваша команда настраивает ветку трека.
Альбфан
3

На основании ответа Оливье Рефало

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

Он показывает только локально с настроенной дорожкой.

Напишите его в сценарии git-track на вашем пути, и вы получите команду git track

Более подробная версия на https://github.com/albfan/git-showupstream

albfan
источник
1

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

даст вам имя удаленного, который отслеживается

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

даст вам имя удаленной ветви, которая отслеживается.

Вам нужно заменить $ current_branch на имя вашей текущей ветки. Вы можете получить это динамически сgit rev-parse --abbrev-ref HEAD

Следующий мини-скрипт объединяет эти вещи. Вставьте его в файл с именем git-tracking, сделайте его исполняемым и убедитесь, что он находится на вашем пути.

тогда вы можете сказать

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

обратите внимание, что имя удаленной ветви может отличаться от имени вашей локальной ветви (хотя обычно это не так). Например:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

как вы можете видеть в коде, ключом к этому является извлечение данных из git config. Я просто использую sed для очистки посторонних данных.

#!/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
источник
1

Вот аккуратный и простой. Можно проверить git remote -v, который показывает вам все происхождение и восходящий поток текущей ветви.

MJeremy
источник