git - как получить ветку по умолчанию?

Моя команда чередует использование dev и master в качестве ветки по умолчанию для нескольких репозиториев, и я хотел бы написать скрипт, который проверяет ветку по умолчанию при входе в каталог.

Когда запросы на вытягивание открываются в некоторых из этих репозиториев, они по умолчанию имеют значение «dev» или «master» в качестве цели слияния.

Я понимаю, как установить эту информацию, но не получить ее: https://help.github.com/articles/setting-the-default-branch/

Доступна ли команда git для определения ветки по умолчанию для удаленного репозитория?


person lfender6445    schedule 23.02.2015    source источник
comment
Ветка по умолчанию — это github, а не git.   -  person Ismail Badawi    schedule 23.02.2015
comment
Вы можете использовать API GitHub, как в этом вопросе: stackoverflow.com/questions/16500461/   -  person Ismail Badawi    schedule 23.02.2015
comment
@IsmailBadawi Правда? При создании локального голого репо и выполнении его клонирования должна быть какая-то логика, определяющая, какая ветка извлечена по умолчанию, верно?   -  person bluenote10    schedule 16.07.2019
comment
Ни одно из приведенных ниже решений не работает надежно для меня: если я нахожусь в ветке feature, разветвленной из develop, она вернет мне develop, а не master (или main, из которой develop является вилкой)... Любая помощь?   -  person user3341592    schedule 12.01.2021
comment
Вопрос задан в stackoverflow.com/questions/65703168/   -  person user3341592    schedule 13.01.2021


Ответы (13)


Протестировано с git 2.9.4 (но, возможно, работает и в других версиях) в репозитории, клонированном с Github:

$ git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
master
person danielkza    schedule 25.06.2017
comment
если я изменю ветку по умолчанию на стороне сервера (github), это все равно получит старое значение по умолчанию в старом, но в остальном текущем клоне (но свежие клоны в порядке). Как здесь принудительно обновить? - person nhed; 05.04.2018
comment
Это отлично работает для источника, но когда я попытался получить ветку по умолчанию для другого удаленного сервера, например восходящего потока в разветвленной настройке github, я не получил символическую ссылку. Я недостаточно разбираюсь в git, чтобы понять, почему, но, видимо, ref/remotes/upstream вообще не будет существовать. Однако решение Radon8472, основанное на git remote, сработало для меня. - person JHH; 09.10.2018
comment
Возможно, я делаю что-то не так, но когда я запускаю это, я получаю: fatal: ref refs/remotes/origin/HEAD is not a symbolic ref с Git 2.19.1. - person christianbundy; 02.11.2018
comment
Этот метод может дать сбой или вернуть неверные результаты. Ссылка может быть хешем, который не может быть преобразован в ветвь, а не в символическую ссылку. Это также можно решить, взглянув на HEAD. Тем не менее, в 6528 репозиториях я проверил, что два метода git symbolic-ref возвращают неправильные результаты (например, master, а не develop для Alfresco/chef-alfresco) в 172 случаях. Метод git remote show, предложенный @Radon8472, более надежен и, кажется, возвращает правильный результат в нескольких из 172 расходящихся случаев, которые я проверил вручную. - person Diomidis Spinellis; 25.01.2019
comment
Вы также можете использовать базовое имя вместо sed basename $(git symbolic-ref refs/remotes/origin/HEAD) - person OzzyCzech; 26.03.2019
comment
@lfender6445 команда из этого ответа возвращает неверные результаты для моих репозиториев. Другой с git remote show... возвращает правильную ветку. - person Side S. Fresh; 20.09.2019
comment
Чтобы синхронизировать эту символическую ссылку из восходящего потока, git remote set-head origin --auto. Это обновляет как то, что видно в git remote show, так и символическую ссылку, на которую ссылается здесь. - person Edward Anderson; 14.01.2020

Я нашел способ определить ветку по умолчанию, если она не является главной.

git remote show [your_remote] | sed -n '/HEAD branch/s/.*: //p'

Я протестировал его с несколькими репозиториями из gitlab, и он работал нормально. (в большинстве случаев [your_remote] будет origin, запустите git remote, чтобы проверить имя вашего пульта)

person Radon8472    schedule 27.04.2018
comment
Это сработало для меня хорошо, за исключением того, что команда cut оставляет пробел перед фактическим именем ветки, что может вызвать проблемы при использовании этого из скриптов. В итоге я использовал git remote show upstream | grep "HEAD branch" | sed 's/.*: //' - person JHH; 09.10.2018
comment
Пока лучший метод. У меня даже нет refs/remotes/origin/HEAD по некоторым причинам. - person Loïc Faure-Lacroix; 11.10.2018
comment
Это зависит от того, как вы называете свой пульт или добавили ли вы его. Попробуйте запустить git remote и посмотрите, что он покажет - person Radon8472; 15.10.2018
comment
@JHH Вы также можете выполнить «xargs», чтобы избавиться от пробелов. То есть: git remote show [your_remote] | grep "HEAD branch" | cut -d ":" -f 2 | xargs - person balaganAtomi; 27.08.2019
comment
Я обновил его, чтобы он был таким, чтобы удалить пробел git remote show origin | grep 'HEAD branch' | cut -d' ' -f5 - person Andrew; 20.09.2019
comment
Имейте в виду, что это может не работать для некоторых (более старых) версий git, если у вас неоднозначный HEAD. См., например. этот пост - person David Střelák; 27.09.2019
comment
Он также не работает с локализованным (переведенным) Git. Например, у меня на выходе git remote show upstream есть branch HEAD:. - person flod; 10.10.2020
comment
У меня не работает надежно: если я нахожусь в ветке feature, разветвленной из develop, она вернет мне develop, а не master (чей develop является вилкой)... Любая помощь? - person user3341592; 11.01.2021
comment
Другие варианты зачистки пространства; * на основе sed: git remote show origin | sed -e '/HEAD branch: /!d' -e '/HEAD branch: /s/.*: //' * на основе perl: git remote show origin | perl -ne 'if (/HEAD branch:\s*(.*)/) { print "$1"} ' - person bernard paulus; 11.06.2021
comment
@JHH: отправил вашу версию как правку - person bernard paulus; 11.06.2021
comment
Используя регулярное выражение (в моем случае js), можно использовать этот шаблон: result.match(/(?<=HEAD branch:).+/)?.[0].trim() - person Henrique Bruno; 25.07.2021

Кажется, пока нет ответа, который не требует клонирования.

Для этого требуется git 2.8.0 или новее

$ git ls-remote --symref [email protected]:pre-commit/pre-commit.github.io HEAD
ref: refs/heads/real_master HEAD
e100a6a3c72b4e54f0d176f791dfd2dbd7eb5fa7    HEAD
person Anthony Sottile    schedule 15.01.2019
comment
Спасибо за хороший ответ. Я добавил awk, чтобы взять имя ветки: git ls-remote --symref https://github.com/hnakamur/ltsvlog HEAD | awk '/^ref:/ {sub(/refs\/heads\//, "", $2); print $2}' - person hnakamur; 27.07.2020

Этот вопрос немного устарел, но на случай, если кто-то столкнется с этим совсем недавно...

git remote show <remote_name> | awk '/HEAD branch/ {print $NF}'

Это также будет отображать только имя ветки, не включая пробелы или другую чепуху.

Мне нравится сохранять это, используя пару псевдонимов git (у меня есть куча таких полезных псевдонимов):

upstream-name = !git remote | egrep -o '(upstream|origin)' | tail -1
head-branch = !git remote show $(git upstream-name) | awk '/HEAD branch/ {print $NF}'

Я использую «upstream» и «origin» в качестве пультов почти в 100% случаев («upstream», когда я использую Fork & Pull... что часто бывает). Ваш вариант использования может не нуждаться в псевдониме upstream-name, я просто считаю его полезным.

person JoeLinux    schedule 22.04.2020
comment
Возможное решение PowerShell: (git remote show origin | Select-String "HEAD branch: " -Raw).Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[2] - person kapsiR; 05.05.2021
comment
git remote show работает медленно, потому что запрашивает сервер. Использование опции -n работает быстрее, но возвращает только список уже известных ветвей. Возможно, это не лучшее решение, но можно написать следующее: git remote show origin -n | grep -c main &> /dev/null && echo main || echo master - person fredericrous; 08.07.2021

git rev-parse --abbrev-ref origin/HEAD напечатает origin/<default-branch-name>. Ответы git symbolic-ref делают то же самое, но требуют более длинного аргумента.

Если репозиторий origin изменит имя ветки по умолчанию, то git remote set-head origin -a получит новое имя ветки по умолчанию.

person Jeffrey Yasskin    schedule 15.06.2020
comment
Это работает намного быстрее, чем git remote show, потому что использует локальную информацию без опроса удаленного. Вы можете обрезать первые 7 символов (например, origin/) и получить только имя ветки с помощью git rev-parse --abbrev-ref origin/HEAD | cut -c8-. - person scottclowe; 15.06.2021
comment
Разве это не канонический ответ, поскольку он использует сантехнику и не требует никаких утилит, кроме самого git? - person Andrew Spencer; 18.06.2021
comment
Отвечаю сам себе - это НЕ канонический ответ, поскольку он работает только в репо, созданном путем клонирования с удаленного устройства, а не с репозитория, который вы создали, а затем добавили удаленный git remote add и нажали на него. - person Andrew Spencer; 18.06.2021
comment
(по-прежнему голосую, так как это лучший ответ в вероятном случае использования скрипта, когда вы знаете, что клонировали репо с удаленного компьютера) - person Andrew Spencer; 18.06.2021

Это работает для меня с Git 2.1.10, используя репозиторий, клонированный из GitHub:

git branch -r --points-at refs/remotes/origin/HEAD

Основная проблема с этим подходом заключается в том, что он перечисляет каждую удаленную ветвь, указывающую на HEAD; однако вывод включает подсказку:

  origin/HEAD -> origin/master
  origin/master
  origin/test123

Таким образом, вы можете обработать вывод с помощью grep или аналогичного, чтобы найти тот, у которого есть стрелка:

git branch -r --points-at refs/remotes/origin/HEAD | grep '\->' | cut -d' ' -f5 | cut -d/ -f2
person Tony Spataro    schedule 03.03.2017
comment
Стоит отметить, что .git/refs/remotes/origin/HEAD не будет существовать только в том случае, если вы клонировали репо, а не в том случае, если вы его создали/авторили. git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master можно использовать для ссылки на ссылки (но это противоречит сути этого вопроса :)) - person shalomb; 10.04.2019

Существует опция --short для git symbolic-ref. Итак, моя предпочтительная команда:

$ git symbolic-ref --short HEAD
master
person Christian Hesse    schedule 20.03.2018
comment
Для удаленного доступа все равно будет git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@' - person maxm; 05.10.2018
comment
Это путь, поэтому в большинстве оболочек POSIX вы также можете просто использовать базовое имя для получения последнего компонента. :D basename $(git symbolic-ref --short refs/remotes/origin/HEAD) - person dannysauer; 30.07.2020
comment
Это текущая ветка при фиксации текущей ветки. - person ncaq; 05.10.2020
comment
Это не будет работать для того, что задает вопрос. Он дает правильный ответ, только если вы оказались на ветке по умолчанию. Если что-то другое проверено, оно даст это вместо этого. - person Caleb; 15.10.2020

Я просто хотел, чтобы сценарий оболочки знал, является ли ветка главной или основной.

Для этой цели это кажется достаточно хорошим:

[ -f "$(git rev-parse --show-toplevel)/.git/refs/heads/master" ] && echo master || echo main

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

[ -f .git/refs/heads/master ] && echo master || echo main

Я использую это в своих псевдонимах Git, например: dotfiles/commit/6815bd95770afab2936fb6202b1ee5e82cb9662b

person Henrik N    schedule 14.03.2021

Если вам нравится этот вопрос, вы пытаетесь получить ветку GitHub по умолчанию, а не какой-либо другой сервер git:

Вы можете получить ветку по умолчанию с помощью /repos GitHub API. Это поле default_branch ответа:

$ curl -s https://api.github.com/repos/darthwalsh/bootstrappingCIL | \
      jq --raw-output .default_branch
master
person Carl Walsh    schedule 21.01.2021

Похоже на обходное решение, но это, похоже, работает:

$ cat .git/refs/remotes/origin/HEAD 
ref: refs/remotes/origin/master
person anorm    schedule 16.06.2017

Следующая команда отобразит ветку HEAD, независимо от того, как вы назвали свои пульты:

git branch --remotes --list '*/HEAD'

Из этого вы можете извлечь ветку по умолчанию следующим образом:

git branch -rl '*/HEAD' | rev | cut -d/ -f1 | rev

(используя короткие варианты аргументов git branch).

person Henry    schedule 20.04.2021
comment
Я работаю где-то, что stage используется как ствол для разработки, а master используется для развертывания. Это дает мне stage, что я и хотел — спасибо! - person rattray; 27.05.2021

Доступна ли команда git для определения ветки по умолчанию для удаленного репозитория?

Нет, вроде нет:

git ls-remote -h https://github.com/<user>/<repo>

Это будет список всех ветвей, но не HEAD (это symref, который обозначает ветвь по умолчанию)

Точно так же GitHub Reference API может отображать заголовки, но также не будет включать HEAD.

person VonC    schedule 23.02.2015

Все остальные ответы сделали слишком много предположений, это единственный способ, который сработал для меня. Это работает независимо от того, в какой ветке вы сейчас находитесь, не предполагает, что ссылка origin/HEAD существует локально, и всегда будет отражать текущую ветку по умолчанию, даже если она была изменена.

Единственным недостатком является то, что он изменяет локальную ссылку origin/HEAD, но обычно это не должно быть проблемой.

Разрешите git установить ваш origin/HEAD, определяя, какую ветку использовать автоматически:

$ git remote set-head origin --auto
origin/HEAD set to main

Затем получите строку, содержащую имя ветки по умолчанию:

$ git rev-parse --abbrev-ref origin/HEAD
origin/main

Альтернативно, для однострочного решения:

$ git remote set-head origin --auto >/dev/null 2>&1 && git rev-parse --abbrev-ref origin/HEAD
origin/main
person Makusu2    schedule 31.03.2021