Как прочитать текущий апстрим для ветки git
Я ищу команду git, чтобы узнать восходящий поток, связанный с существующей веткой (если есть).
(какая-то команда "read", связанная с командой "write" git branch --set-upstream-to=...
)
Причина в том, что я использую ветку, связанную с несколькими удаленными репозиториями, и я хотел бы проверить, не связана ли ветка с правым восходящим потоком, прежде чем менять ее.
4 ответа
TL;DR: использовать git rev-parse
$ git rev-parse --abbrev-ref master@{u}
weird/master
Если восходящий поток не установлен, вы получите:
fatal: no upstream configured for branch 'master'
(и ненулевой код выхода). Перенаправить stderr на /dev/null
чтобы отменить сообщение об ошибке, если оно вам не нужно:
if master_upstream=$(git rev-parse --abbrev-ref master@{u} 2>/dev/null); then
master_has_upstream=true
else
master_has_upstream=false
fi
например.
объяснение
Ответ Энтони Соттиля обычно дает вам правильное имя, но не всегда. В частности, смотрите, что происходит, когда remote.origin.fetch
установка для origin
это не норма
$ git init
Initialized empty Git repository in .../tmp/tt/.git/
$ git remote add origin git://github.com/git/git
$ git config remote.origin.fetch '+refs/heads/*:refs/remotes/weird/*'
$ git fetch
remote: Counting objects: 231294, done.
remote: Compressing objects: 100% (663/663), done.
remote: Total 231294 (delta 0), reused 662 (delta 0), pack-reused 230631
Receiving objects: 100% (231294/231294), 93.03 MiB | 3.54 MiB/s, done.
Resolving deltas: 100% (170261/170261), done.
From git://github.com/git/git
* [new branch] maint -> weird/maint
* [new branch] master -> weird/master
* [new branch] next -> weird/next
* [new branch] pu -> weird/pu
* [new branch] todo -> weird/todo
* [new tag] v2.14.2 -> v2.14.2
[lots more tags snipped]
Обратите внимание, что хотя пульт называется origin
, ветви удаленного отслеживания названы weird/master
, weird/next
, и так далее. И это на самом деле работает:
$ git checkout master
Branch master set up to track remote branch master from origin.
Already on 'master'
$ git status
On branch master
Your branch is up-to-date with 'weird/master'.
nothing to commit, working tree clean
Но что в .git/config
все еще выглядит так, как вы ожидаете, если origin/master
:
[branch "master"]
remote = origin
merge = refs/heads/master
С помощью:
branch="$(git branch | grep '\*' | cut -d' ' -f2-)"
работает достаточно хорошо (хотя часто следует использовать git symbolic-ref --short HEAD
чтобы получить текущее название ветви: см. ниже).
remote="$(git config "branch.${branch}.remote")"
Эта часть работает отлично - она получает имя пульта.
remote_branch="$(git config "branch.${branch}.merge" | cut -d/ -f3-)"
Это где мы идем не так. Что нам нужно, это использовать git rev-parse
плюс синтаксис gitrevisions для "восходящего потока указанной ветки", который должен добавить @{u}
или же @{upstream}
на имя филиала. Обычно git rev-parse
превращает это в хэш-идентификатор, но с --abbrev-ref
, он печатает краткую версию названия или с --symbolic-full-name
, он печатает длинную версию:
$ git rev-parse --symbolic-full-name master@{u}
refs/remotes/weird/master
(Я понятия не имею, почему это пишется --abbrev-ref
в одном случае и --symbolic-full-name
в другой.)
Обратите внимание, что при использовании git rev-parse
на HEAD
, если HEAD
отсоединен, ответ является символом HEAD
, То есть в любом репозитории Git, git rev-parse HEAD
всегда удается, даже при печати символических имен. Это не верно для git symbolic-ref
хоть:
$ git checkout --detach
HEAD is now at ea220ee40... The eleventh batch for 2.15
$ git rev-parse --abbrev-ref HEAD
HEAD
$ git rev-parse --symbolic-full-name HEAD
HEAD
$ git symbolic-ref HEAD
fatal: ref HEAD is not a symbolic ref
Так что для разрешения HEAD
(чтобы найти текущую ветвь), выберите, какую команду использовать, основываясь на желаемом поведении в случае "нет текущей ветки".
Вот как я нашел тот же ответ, что и git status
но дружественным к сценарию образом:
$ branch="$(git branch | grep '\*' | cut -d' ' -f2-)"
$ remote="$(git config "branch.${branch}.remote")"
$ remote_branch="$(git config "branch.${branch}.merge" | cut -d/ -f3-)"
$ echo "${branch} is tracking ${remote}/${remote_branch}"
print_locking_less is tracking origin/master
Информация для удаленного отслеживания ветки хранится в .git/config
это выглядит так:
[branch "print_locking_less"]
remote = origin
merge = refs/heads/master
Просто используйте
git branch -vv
:
foo 03b325f Commit on untracked branch
master b7da42b [origin/master] Initial commit
Восходящий поток (если есть) красиво отображается в квадратных скобках.
Выдержка из руководства с добавлением акцента:
-v
-vv
--verbose
В режиме списка показывать sha1 и строку темы фиксации для каждой главы, а также отношение к вышестоящей ветке (если есть). Если указано дважды, напечатайте путь к связанному рабочему дереву (если есть), а также имя вышестоящей ветки (см. также git remote show). Обратите внимание, что путь к HEAD текущего рабочего дерева не будет напечатан (это всегда будет ваш текущий каталог).
Обратите внимание, что
-vv
более подробный, чем
--verbose
что то же самое, что
-v
.
На самом деле, я нашел первый трюк, используя git status
команда:
Я ветвь является текущей ветвью и есть восходящий, я получаю строку, как Your branch is up-to-date with 'the_repo/the branch'
Но у меня есть более прямой способ узнать это.