Как программно определить текущую извлеченную ветку Git [duplicate]

200

В среде сценариев Unix или GNU (например, дистрибутив Linux, Cygwin, OSX), каков наилучший способ определить, какая ветвь Git в настоящее время проверена в рабочем каталоге?

Одно использование этого метода будет автоматически помечать выпуск (например, svnversion будет делать с Subversion).

Также см. мой родственный вопрос: Как программно определить, является ли проверка Git тегом, и если да, то что такое имя тега?

Теги:

19 ответов

216
Лучший ответ

Правильное решение - заглянуть в contrib/completions/git-completion.bash делает это для приглашения bash в __git_ps1. Удаление всех дополнительных функций, например, выбор способа описания ситуации с отсоединенным HEAD, т.е. Когда мы находимся в неназванной ветки, это:

branch_name="$(git symbolic-ref HEAD 2>/dev/null)" ||
branch_name="(unnamed branch)"     # detached HEAD

branch_name=${branch_name##refs/heads/}

git symbolic-ref используется для полного извлечения имя квалифицированной ветки с символической ссылкой; мы используем его для HEAD, который в настоящее время проверяется.

Альтернативное решение может быть:

branch_name=$(git symbolic-ref -q HEAD)
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD}

где в последней строке мы имеем дело с ситуацией отдельно стоящего HEAD, используя просто "HEAD" для обозначения такой ситуации.


Добавлено 11-06-2013

Junio ​​C. Hamano (git supporter), Проверяя текущую ветвь программно, с 10 июня 2013 года объясняет whys (и hows) более подробно.

  • 0
    + для $ (git symbolic-ref -q HEAD), я использую это для скрипта автоматизации # head_sha1 = $ (cat .git / $ (git symbolic-ref HEAD)); # echo $ head_sha1 9ed68f221e158ce90f8a36832d981befa6e75179 отлично работает, большое спасибо
  • 9
    Не используйте cat .git/refs/heads/branch ; используйте git rev-parse --verify refs/heads/branch . Ссылки могут быть упакованы , и решение с cat получится.
Показать ещё 14 комментариев
148

Кто-нибудь видит что-то не так, просто спрашивая Git описать ветку, в которой вы находитесь?

git rev-parse --symbolic-full-name --abbrev-ref HEAD

Это может быть использовано в $() и легко передается в Bash, Powershell, Perl и т.д. Это не обмануто, если у вас есть несколько веток в фиксации, на котором вы находитесь, и если вы в данный момент не находитесь ветвь, она просто отвечает "HEAD".

В качестве альтернативы вы можете использовать

git symbolic-ref --short -q HEAD

Что даст вам тот же результат, но он не вернет ничего вообще, если вы отсоединились. Это полезно, если вы хотите, чтобы ошибка была отсоединена, просто удалите -q.

  • 2
    Извините, я думаю, опция --short для synbolic-ref доступна только в Git 1.7.10 (MSYS). Второй вариант не работает так же хорошо для 1.7.9 (CygWin).
  • 1
    Как бы вы тогда взяли команду git rev-parse --symbolic-full-name --abbrev-ref HEAD и поместили ее в переменную PS1 для bash или приглашение для csh?
Показать ещё 2 комментария
33

вы можете использовать git name-rev --name-only HEAD

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

Из этого ответа: https://stackoverflow.com/questions/1417957/show-just-the-current-branch-in-git:

$ git rev-parse --abbrev-ref HEAD
master

Очевидно, работает с Git 1.6.3 или новее.

  • 2
    это не сработает, если вы находитесь в отдельном состоянии головы.
  • 1
    @Eimantas - он просто печатает 'HEAD' в отдельном состоянии головы на моей системе: gist.github.com/johnnyutahh/2f4db5c755bc032b106b . Вы используете Git> = 1.6.3?
Показать ещё 1 комментарий
12

Попробуйте:

 git symbolic-ref --short -q HEAD

Или вы пытаетесь с помощью git branch с --no-color принудительно простую строку вывести:

 git branch  --no-color

С grep в режиме регулярного выражения (-E) вы можете проверить, существует ли символ '*':

 git branch  --no-color  | grep -E '^\*' 

Результаты аналогичны:

* currentBranch

Вы можете использовать следующие параметры:

sed 's/\*[^a-z]*//g'
cut -d ' ' -f 2
awk '{print $2}'

например:

 git branch  --no-color  | grep -E '^\*' | sed 's/\*[^a-z]*//g'
 git branch  --no-color  | grep -E '^\*' | sed cut -d ' ' -f 2
 git branch  --no-color  | grep -E '^\*' | awk '{print $2}'

Если существует ошибка, которую вы не можете использовать по умолчанию:

  cmd || echo 'defualt value';

Все в функцию bash:

function get_branch() {
      git branch --no-color | grep -E '^\*' | awk '{print $2}' \
        || echo "default_value"
      # or
      # git symbolic-ref --short -q HEAD || echo "default_value";
}

Использование:

branch_name=`get_branch`;
echo $branch_name;
9

адаптация принятого ответа к окнам powershell:

Split-Path -Leaf (git symbolic-ref HEAD)
7

Этот файл работал у меня в файле bash.

git branch | grep '^*' | sed 's/* //'  


################bash file###################
#!/bin/bash
BRANCH=$(git branch | grep '^*' | sed 's/* //' )
echo $BRANCH
  • 1
    ^ * следует заключать в кавычки, чтобы избежать расширения, т.е. git branch | grep '^ *' | sed 's / * //'
  • 1
    @MingjiangShi спасибо за предложение. Я обновил ответ
6

Этот работает для меня. Часть --no-color является или может быть важной, если вы хотите, чтобы простая строка вернулась.

git branch --no-color | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
  • 7
    git-branch - это команда фарфора (пользовательский интерфейс), и ее вывод не должен использоваться в скриптах. Хотя вы получаете бонусные баллы за «--no-color».
  • 0
    Когда выход подключен к каналу, цвет не создается, попробуйте: git branch | cat
Показать ещё 1 комментарий
4

Я пытаюсь найти самый простой и понятный метод:

git status | grep "On branch" | cut -c 11-
4

Вот что я делаю:

git branch | sed --quiet 's/* \(.*\)/\1/p'

Результат будет выглядеть так:

$ git branch | sed --quiet 's/* \(.*\)/\1/p'
master
$
  • 4
    git-branch - это фарфоровая команда (пользовательский интерфейс), и ее вывод не должен использоваться в скриптах
  • 0
    Не работает в моей системе MacOS 10.6.8.
Показать ещё 1 комментарий
3

Я нашел два действительно простых способа сделать это:

$ git status | head -1 | cut -d ' ' -f 4

и

$ git branch | grep "*" | cut -d ' ' -f 2
  • 1
    Я не уверен насчет первого (например, кажется, не работает на Git 2.11.1 / MacOS), но вторая команда работает.
2

Использование --porcelain позволяет легко выводить обратно-совместимый вывод:

git status --branch --porcelain | grep '##' | cut -c 4-

Из документации:

Формат фарфора похож на короткий формат, но гарантированно не изменяется в обратном-несовместимом режиме между версиями Git или на основе пользовательской конфигурации. Это делает его идеальным для синтаксического анализа скриптов.

https://git-scm.com/docs/git-status

2

Здесь мое решение, подходящее для использования в PS1, или для автоматической маркировки выпуска

Если вы извлечены в ветке, вы получите название ветки.

Если вы находитесь только в проекте init'd git, вы просто получаете '@'

Если вы без головы, вы получите хорошее человеческое имя относительно какой-либо ветки или тега, с именем "@", предшествующим имени.

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

function we_are_in_git_work_tree {
    git rev-parse --is-inside-work-tree &> /dev/null
}

function parse_git_branch {
    if we_are_in_git_work_tree
    then
    local BR=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD 2> /dev/null)
    if [ "$BR" == HEAD ]
    then
        local NM=$(git name-rev --name-only HEAD 2> /dev/null)
        if [ "$NM" != undefined ]
        then echo -n "@$NM"
        else git rev-parse --short HEAD 2> /dev/null
        fi
    else
        echo -n $BR
    fi
    fi
}

Вы можете удалить бит if we_are_in_git_work_tree, если хотите; Я просто использую его в другой функции в своем PS1, которую вы можете полностью просмотреть здесь: PS1-строка с git текущей ветвью и цветами

2

Если вы используете старую командную строку NT, вы можете использовать следующее:

@for /f "usebackq" %i in (`git symbolic-ref -q HEAD`) do @echo %~ni

Чтобы использовать в пакетном файле, вам нужно удвоить%:

@for /f "usebackq" %%i in (`git symbolic-ref -q HEAD`) do @echo %%~ni
2

Кто-то упомянул о том, чтобы сделать это в bash с менее чем тремя присваиваниями... как насчет какого-то беспорядочного потока управления следующим образом:

branch_name="$(b=$(git symbolic-ref -q HEAD); { [ -n "$b" ] && echo ${b##refs/heads/}; } || echo HEAD)"
1

Я обнаружил, что вызов git довольно медленный (любой из подкоманд), особенно для обновления подсказки. Время варьируется между 0,1 и 0,2 секунды в корневом каталоге репо и более чем на 2 секунды за пределами репо на верхней метке (рейд 1, 8 ГБ оперативной памяти, 8 аппаратных потоков). Однако он запускает Cygwin.

Поэтому я написал этот script для скорости:

#!/usr/bin/perl

$cwd=$ENV{PWD}; #`pwd`;
chomp $cwd;

while (length $cwd)
{
        -d "$cwd/.git" and do {
                -f "$cwd/.git/HEAD" and do {
                        open IN, "<", "$cwd/.git/HEAD";
                        $_=<IN>;
                        close IN;
                        s@ref: refs/heads/@@;
                        print $_;
                };
                exit;
        };

        $cwd=~s@/[^/]*$@@;
}

Может потребоваться настройка.

  • 1
    С момента публикации прошло 5 лет, Git стал намного быстрее. Я только что запустил цикл в bash, выполняя это 1000 раз против git rev-parse --abbrev-ref HEAD и команда git была в ~ git rev-parse --abbrev-ref HEAD раза быстрее (!) [Git 2.17 против perl 5.18, macOS]
0

Если вы находитесь на отдельной голове (то есть вы проверили выпуск) и имеете выход из состояния git, например

HEAD detached at v1.7.3.1

И вы хотите версию выпуска, мы используем следующую команду...

git status --branch | head -n1 | tr -d 'A-Za-z: '

Это возвращает 1.7.3.1, который мы заменяем в наших параметрах .yml(Symfony) с

# RevNum=`svn status -u | grep revision | tr -d 'A-Za-z: '`  # the old SVN version
RevNum=`git status --branch | head -n1 | tr -d 'A-Za-z: '` # Git (obvs)

sed -i "/^    app_version:/c\    app_version:$RevNum" app/config/parameters.yml

Надеюсь, что это поможет:) Очевидно, что если у вас есть нечисловые числа в имени вашей ветки, вам нужно будет изменить аргументы команды tr.

0

Если вы используете gradle,

`` `

def gitHash = new ByteArrayOutputStream()    
project.exec {
                commandLine 'git', 'rev-parse', '--short', 'HEAD'
                standardOutput = gitHash
            }

def gitBranch = new ByteArrayOutputStream()   
project.exec {
                def gitCmd = "git symbolic-ref --short -q HEAD || git branch -rq --contains "+getGitHash()+" | sed -e '2,\$d'  -e 's/\\(.*\\)\\/\\(.*\\)\$/\\2/' || echo 'master'"
                commandLine "bash", "-c", "${gitCmd}"
                standardOutput = gitBranch
            }

`` `

  • 0
    Это решает все ситуации, в том числе отдельный режим. Великий ~~~~!
0

Это одно решение. Если вы добавите его в свой .bashrc, он отобразит текущую ветку в консоли.

# git branch
parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1) /'
}
$PS1="\$(parse_git_branch)$PS1"

Однако он довольно ограничен. Но есть большой проект под названием git sh, который делает именно это (и многое другое).

  • 0
    Вау, это безумие. Это именно тот код, который у меня был в моем .bashrc. Я сократил его до использования опций GNU sed и продолжал думать, что это не похоже на мой код. Мне любопытно, был ли код, который вы опубликовали, из какого-то публичного примера?
  • 0
    Также +1, потому что, хотя я не проверял, я уверен, что ваш ответ не совместим с GNU, поэтому он может быть предпочтительным для Darwin, Solaris и т. Д.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню