Git: программно знать, насколько ветка впереди/за удаленной ветвью
Я хотел бы извлечь информацию, напечатанную после git status
, которая выглядит так:
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
Конечно, я могу разобрать вывод git status
, но это не рекомендуется, так как этот человекочитаемый вывод может измениться.
Есть две проблемы:
- Как узнать удаленную удаленную ветку? Это часто бывает
origin/branch
, но не обязательно.
- Как получить номера? Как узнать, впереди? На сколько коммит? А как насчет случая с расходящимся ветвлением?
Ответы
Ответ 1
Обновление
Как отмечалось в amalloy, последние версии git поддерживают поиск соответствующей ветки отслеживания для данной ветки, предоставляя "branchname @{upstream}" (или "branchname @{u}" или "@{u}" для ветки отслеживания HEAD). Это эффективно отменяет script ниже. Вы можете сделать:
git rev-list @{u}..
git rev-list --left-right --boundary @{u}...
gitk @{u}...
и т.д.. Например, у меня git q
с псевдонимом git log --pretty='...' @{u}..
, чтобы показать, что я "поставил в очередь", готов к нажатию.
оригинальный ответ
Кажется, нет простого способа найти ветку отслеживания вообще, без синтаксического анализа большего количества git config, чем это практично в нескольких командах оболочки. Но для многих случаев это будет иметь большое значение:
# work out the current branch name
currentbranch=$(expr $(git symbolic-ref HEAD) : 'refs/heads/\(.*\)')
[ -n "$currentbranch" ] || die "You don't seem to be on a branch"
# look up this branch in the configuration
remote=$(git config branch.$currentbranch.remote)
remote_ref=$(git config branch.$currentbranch.merge)
# convert the remote ref into the tracking ref... this is a hack
remote_branch=$(expr $remote_ref : 'refs/heads/\(.*\)')
tracking_branch=refs/remotes/$remote/$remote_branch
# now $tracking_branch should be the local ref tracking HEAD
git rev-list $tracking_branch..HEAD
Другой, более грубый, подход:
git rev-list HEAD --not --remotes
Ответ jamessan объясняет, как найти относительные различия между $tracking_branch и HEAD, используя git rev-list
. Одна забавная вещь, которую вы можете сделать:
git rev-list --left-right $tracking_branch...HEAD
(обратите внимание на три точки между $tracking_branch и HEAD). Это будет показывать фиксации на обоих "плечах" с отличительным знаком спереди: "<" для фиксации на $tracking_branch и " > " для фиксации на HEAD.
Ответ 2
git rev-list origin..HEAD
покажет коммиты, которые находятся в вашей текущей ветки, но не происхождение - то есть, превысите ли вы начало и по каким-то причинам.
git rev-list HEAD..origin
покажет обратное.
Если обе команды показывают фиксации, то у вас есть расходящиеся ветки.
Ответ 3
Вы можете попробовать git branch -v -v
. Если флаг -v
задан дважды, он выводит имена ветвей вверх по течению. Пример вывода:
* devel 7a5ff2c [origin/devel: ahead 1] smaller file status overlay icons
master 37ca389 [origin/master] initial project check-in.
Я думаю, что этот формат более стабилен, чем git status
.
Ответ 4
Edit:
Мой первоначальный ответ на самом деле был не очень хорошим, потому что он полагался на пользователя, чтобы иметь удаленный вызов "происхождение". Он также потерпел неудачу, если в текущей ветке была ветвь отслеживания, кроме начального. Эти недостатки по существу сделали это бесполезным. Однако ответ @araqnid не самый эффективный метод, и способ, которым он достигает $tracking_branch
, меньше, чем прорыв вперед. Самый эффективный (самый быстрый) метод, который я нашел, чтобы получить ту же функциональность, следующий:
# get the tracking-branch name
tracking_branch=$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))
# creates global variables $1 and $2 based on left vs. right tracking
# inspired by @adam_spiers
set -- $(git rev-list --left-right --count $tracking_branch...HEAD)
behind=$1
ahead=$2
оригинальный ответ: (нижний, но данный для ясности)
Возможно, самый простой способ, который я мог найти (вдохновленный @insidepower)
# count the number of logs
behind=$(git log --oneline HEAD..origin | wc -l)
ahead=$( git log --oneline origin..HEAD | wc -l)
Ранее я использовал метод @araqnid, но теперь я думаю, что я перенесу некоторые из своих сценариев в этот метод, поскольку он намного проще. Это должно работать в любой системе unix.
Ответ 5
git status
имеет параметр --porcelain
, предназначенный для синтаксического анализа по сценариям. Он основан на выходе --short
- они почти идентичны на момент написания (см. Раздел "Формат фарфора" на странице состояния git). Основное отличие состоит в том, что --short
имеет цветной выход.
По умолчанию не отображается информация о филиале, но если вы добавите опцию --branch
, вы получите вывод, например:
git status --short --branch
## master...origin/master [ahead 1]
?? untrackedfile.txt
...
Если вы устарели (после выборки), линия ветвления будет только:
## master
Если вы впереди:
## master...origin/master [ahead 1]
Если вы позади:
## master...origin/master [behind 58]
И для обоих:
## master...origin/master [ahead 1, behind 58]
Обратите внимание, что git status --porcelain --branch
доступен только в 1.7.10.3 или позже (хотя git status --short --branch
доступен с 1.7.2).
Ответ 6
В современных версиях git, @{u}
указывает на верхнюю часть текущей ветки, если она установлена.
Итак, чтобы подсчитать, сколько задержек вы находитесь за ветвью удаленного отслеживания:
git rev-list [email protected]{u} | wc -l
И чтобы увидеть, как далеко вы далеко от пульта, просто переключите порядок:
git rev-list @{u}..HEAD | wc -l
Для более удобного для чтения резюме вы можете запросить вместо него журнал:
git log --pretty=oneline @{u}..HEAD
В моих собственных целях я работаю над script, который заменит @{u}
на соответствующую догадку, если восходящий поток еще не установлен. К сожалению, в это время нет @{d}
для представления нисходящего потока (куда вы нажимаете).
Ответ 7
Верхняя часть кода в ответе araqnid не работает для меня, поэтому, возможно, что-то в git изменилось с тех пор, как было написано 18 месяцев назад. Он работает, если я меняю:
tracking_branch=refs/remotes/$remote/$remote_branch
к
tracking_branch=$remote/$remote_branch
Однако при отслеживании локальной ветки все еще есть проблема, и в этом случае вам нужно обрезать удаленную часть (которая становится "." ):
tracking_branch=${tracking_branch#./}
Затем вы можете программно получить количество ревизий позади и вперед следующим образом:
set -- `git rev-list --left-right --count $tracking_branch...HEAD`
behind="$1"
ahead="$2"
Я написал сценарии, чтобы сделать все это (и многое другое - например, они также могут попытаться обнаружить удаленные объекты на другой стороне моста git -svn) и опубликовать их в my git -config репозиторий в github. Например, здесь git-compare-upstream. См. README для инструкций по установке и других удобных скриптов.
Ответ 8
Почему бы не работать:
#!/bin/sh
git diff origin/master..HEAD --quiet --exit-code
RETVAL=$?
if [ $RETVAL -gt 0 ]; then
echo "You need to git push!"
else
echo "No git push necessary!"
fi
Ответ 9
Как узнать удаленную удаленную ветку? Это часто origin/branch
, но не обязательно.
Git 2.5+ вводит новый ярлык, который ссылается на ветку, на которую вы нажимаете. @{push}
: это будет ветвь удаленного отслеживания, которая здесь представляет интерес.
Это означает, что у вас есть еще один способ увидеть вперед/назад для всех ветвей, которые настроены на то, чтобы нажать на ветку.
git for-each-ref --format="%(push:track)" refs/heads
Подробнее в разделе Просмотр Unpushed Git Commits"