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

这种技术的一个用途是自动标记版本(就像svnversion对Subversion所做的那样)。

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


当前回答

正确的解决方案是查看contrib/completions/git-completion。Bash在__git_ps1中为Bash提示符执行此操作。删除所有额外的内容,比如选择如何描述分离的HEAD情况,即当我们在未命名的分支上时,它是:

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

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

Git symbol -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维护者)2013年6月10日的博客文章,以编程方式检查当前分支,更详细地解释了为什么(以及如何)。

其他回答

这个适合我。如果您希望返回纯字符串,那么——no-color部分非常重要。

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

这是一个解。如果您将它添加到.bashrc中,它将在控制台中显示当前分支。

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

然而,这是相当有限的。但是有一个叫做git sh的伟大项目,它正在做这些事情(甚至更多)。

有人提到在bash中做不到三个任务…像这样混乱的控制流怎么样:

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

结果与单行变量赋值中接受的答案相同:

branch_name=$((git symbolic-ref HEAD 2>/dev/null || echo "(unnamed branch)")|cut -d/ -f3-)

有人觉得让Git描述你所在的分支有什么不对吗?

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

它可以在$()中使用,并且可以在Bash、Powershell、Perl等中轻松传递。如果你在提交过程中有几个分支,它不会被愚弄,如果你目前不在一个分支上,它会简单地返回“HEAD”。

或者,您可以使用

git symbolic-ref --short -q HEAD

它会给你相同的输出,但如果你是分离的,它根本不会返回任何东西。如果你想在分离时出现错误,这个选项很有用,只需要删除-q。