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

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

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

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

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

18 ответов

Решение

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

$ git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
master

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

git remote show [your_remote] | grep "HEAD branch" | cut -d ":" -f 2

Я протестировал его с несколькими репо из gitlab, и он работал нормально.

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

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

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

Это требует git 2.8.0 или новее

$ git ls-remote --symref git@github.com:pre-commit/pre-commit.github.io HEAD
ref: refs/heads/real_master HEAD
e100a6a3c72b4e54f0d176f791dfd2dbd7eb5fa7    HEAD

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

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}'

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

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

$ git symbolic-ref --short HEAD
master

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

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

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

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

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

Как отмечают другие ответчики, концепция ветки по умолчанию - это вещь GitHub, которая на самом деле не имеет смысла (в высоком смысле) Git (здесь есть достаточно хороший (хотя и недооцененный) комментарий: /questions/58769086/kak-poluchit-znachenie-po-umolchaniyu-dlya-osnovnoj-vetki-v-git/58777020#58777020), но на практике мы все знаем, что это значит.

Поскольку первоначальный вопрос был задан, Git 2.28 добавил init.defaultBranch, что позволяет использовать другую начальную ветвь, чем , и многие проекты теперь используют . Это хорошо. Большинство ответов здесь основаны на проверке удаленного устройства, но это зависит от того, что на самом деле это удаленное устройство, и что для этих удаленных устройств существует надежная и согласованная схема именования. Это, вероятно, (все чаще?) разумные предположения, но это не гарантия, и я не считаю, что какой-либо из основных ответов здесь терпит неудачу.

Более того, мой основной вариант использования — использование имени ветки по умолчанию для различных псевдонимов git (например, ). Я хотел бы использовать одни и те же псевдонимы, не задумываясь об этом слишком много, независимо от использования внешнего репо или локального использования без удаленного доступа. Git и его конфигурация не могут «хранить» информацию, поэтому нет возможности заранее установить основную ветку текущего репозитория. Таким образом, любой псевдоним, который хочет, скажем, показать коммиты между основной ветвью и HEAD, не может считаться git log master..HEADили же git log main..HEADзаработает.

Таким образом, я определяю default-branchпсевдоним в Git, который определяет ветку по умолчанию, а затем предоставляет ее другим псевдонимам. Это боль, так как простой lm = log main..HEADдолжен вместо этого стать lm = "!git log $(git default-branch)..HEAD"но вот мы:

default-branch = "!git branch --sort=-refname | grep -o -m1 '\\b\\(main\\|master\\|dev\\)\\b'"

Это просто получает имена ветвей, а затем находит первую в определенном списке. Если есть main, используйте это; если нет и есть master, используйте это. у меня тоже есть devтам в качестве третичного варианта некоторые люди используют.

Это похоже на то, что @henrik-n делает в /questions/25346831/git-kak-poluchit-vetku-po-umolchaniyu/56883953#56883953 , но я делаю это в самом Git, а не в оболочке, и я думаю, что у него есть дополнительные возможности.

Это можно сделать с помощью инструмента gh cli (проверено v2.0.0)

gh repo view --json defaultBranchRef --jq .defaultBranchRef.name

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

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

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

      $ 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

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

Для этой цели этого достаточно:

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

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

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

Я использую это в своих псевдонимах Git так: https://github.com/henrik/dotfiles/commit/6815bd95770afab2936fb6202b1ee5e82cb9662b

Вы можете получить ветку по умолчанию, используя <tcode id="4359109"></tcode>GitHub API . Это default_branch поле ответа:

      $ curl -s https://api.github.com/repos/darthwalsh/bootstrappingCIL | jq --raw-output .default_branch
master

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

Нет, похоже, нет:

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

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

Точно так же Справочный API GitHub может перечислять заголовки, но также не включает HEAD.

Из git 2.28.0 и выше:

      $ git config --get init.defaultBranch || echo master

Это работает для меня с 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

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

$ cat .git/refs/remotes/origin/HEAD 
ref: refs/remotes/origin/master

Я добавлю еще один ответ, основанный на других ответах. Мне не понравился ни один из других ответов, потому что запросы к удаленному устройству медленные, но я также не хотел решения «только для локального».

Я использую этот (длинный) псевдоним:

      head-branch = "!f() { gitHeadsDir=\"$(git rev-parse --show-toplevel)/.git/refs/heads\"; if [ -f \"$gitHeadsDir/main\" ]; then echo 'main'; elif [ -f \"$gitHeadsDir/master\" ]; then echo 'master'; else git remote show origin | grep 'HEAD branch' | cut -d' ' -f5; fi; }; f"

Вышеупомянутое в основном делает это:

  • если существует локальная ветвь с именем, используйте ее
  • если существует локальная ветвь с именем, используйте ее
  • в противном случае вернитесь к проверке пульта (что намного медленнее)

Это работает для 99% вариантов использования (и для всех моих вариантов использования), в том числе:

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

Вы все еще можете легко «сломать» это, создав локальную ветвь с именем или (или с обоими), даже если это на самом деле не ветвь по умолчанию. Это также потерпит неудачу, если у вас нет удаленного компьютера, а имя вашей ветки по умолчанию не будет ни , ни . Но в этих случаях вы, скорее всего, пытаетесь сломать его. ;-)

Сначала я проверяю, так как если у вас есть и то, и другое , вы, вероятно, находитесь в процессе перехода с к .

      > git var GIT_DEFAULT_BRANCH
master

Из документов для git var:

GIT_DEFAULT_BRANCH: имя первой ветки, созданной во вновь инициализированных репозиториях.

Эта переменная была добавлена ​​в git 2.35.

Другие вопросы по тегам