如何以编程方式确定当前签出的Git分支

在Unix或GNU脚本环境(例如Linux发行版,Cygwin,OSX)中,确定当前在工作目录中检出哪个Git分支的最佳方法是什么?

这种技术的一个用途就是自动标记一个发行版(就像svnversion会用Subversion一样)。

请参阅我的相关问题: 如何以编程方式确定Git签出是否是标记,如果是,则标记名称是什么?

正确的解决scheme是在contrib / completions / git-completion.bash中查看__git_ps1 bash提示符。 删除所有额外的东西,如select如何描述分离的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,这是目前检出分支。

备用解决scheme可以是:

 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 maintainer)博客文章,从2013年6月10日起以编程方式检查当前分支 ,更详细地解释了whys (和hows)。

有没有人看到有什么不对,只是要求Git描述你所在的分支?

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

这可以在$()中使用,并在Bash,Powershell,Perl等中轻松传递。如果您在提交时有多个分支,并且如果您当前不在分支上,用“HEAD”回复。

或者,您可以使用

 git symbolic-ref --short -q HEAD 

哪个会给你相同的输出,但是如果你被分离,它将不会返回任何东西。 如果你想在分离的时候想要一个错误,那么这个是有用的,只需要删除-q。

你可以使用git name-rev --name-only HEAD

从这个答案: https : //stackoverflow.com/a/1418022/605356 :

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

显然可以使用Git 1.6.3或更新的版本。

试试:

  git symbolic-ref --short -q HEAD 

或者你用git branch--no-color强制简单的纯string输出:

  git branch --no-color 

使用正则expression式模式( -E )grep你可以检查是否存在字符'*':

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

其结果类似于:

 * currentBranch 

您可以使用下一个选项:

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

例如:

  git branch --no-color | grep -E '^\*' | sed 's/\*[^az]*//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; 

使接受的答案适应Windows PowerShell的:

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

这个在bash文件中为我工作。

 git branch | grep '^*' | sed 's/* //' ################bash file################### #!/bin/bash BRANCH=$(git branch | grep '^*' | sed 's/* //' ) echo $BRANCH 

这个为我工作。 如果你想要一个简单的string, --no-color部分是,或者可以是重要的。

 git branch --no-color | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/' 

这是我做的:

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

输出结果如下所示:

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

我正在尝试这里最简单,最明显的方法:

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

我发现了两个非常简单的方法来做到这一点:

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

 $ git branch | grep "*" | cut -d ' ' -f 2 

有人提到用bashless于三个任务做…这样一些混乱的控制stream如何:

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

如果您使用的是旧的NT命令行,则可以使用以下命令:

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

要在batch file中使用,你必须加倍%:

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

这是我的解决scheme,适合在PS1中使用,或自动标记发布

如果您在分支机构签出,则会获得分行名称。

如果你在一个刚刚开始的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你可以删除if we_are_in_git_work_tree位。 我只是在PS1中的另一个函数中使用它,您可以在这里完整地查看: PS1行与git当前分支和颜色

使用–porcelain可以轻松parsing向后兼容的输出:

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

从文档:

瓷器格式类似于短格式,但保证不会在Git版本之间或基于用户configuration的后向不兼容的方式改变。 这使得它非常适合通过脚本parsing。

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

我发现调用git相当慢(任何子命令),尤其是对于更新提示。 时间在回购的根目录内的.1和.2秒之间,以及回购之外,在顶尖的机器上(raid 1,8GB内存,8个硬件线程)超过0.2秒。 它确实运行Cygwin。

所以我为速度写了这个脚本:

 #!/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@/[^/]*$@@; } 

可能需要一些调整。

这是一个解决scheme。 如果你把它添加到你的.bashrc中,它会在控制台中显示当前分支。

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

但是它非常有限。 但是有一个叫做git sh的伟大项目,正是这样做(还有更多)。

如果你正在使用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 } 

“`

如果你是一个独立的头(即你已经签出一个版本),并从git状态输出,如

 HEAD detached at v1.7.3.1 

而你想发行的版本,我们使用下面的命令…

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

这返回1.7.3.1,我们用parameters.yml(Symfony)replace

 # 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命令的参数。