在Unix或GNU脚本环境(例如Linux发行版,Cygwin,OSX)中,确定当前在工作目录中检出哪个Git分支的最佳方法是什么?
这种技术的一个用途是自动标记一个版本(就像svnversion
会对Subversion做的那样)。
另请参阅我的相关问题:How to programmatically determine whether a Git checkout is a tag, and if so what is the tag name?
答案 0 :(得分:274)
正确的解决方案是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 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 maintainer)博客文章Checking the current branch programatically,自2013年6月10日起,更详细地解释了 为什么 (和hows)。< / p>
答案 1 :(得分:189)
有人看到Git描述你所在的分支有什么问题吗?
git rev-parse --symbolic-full-name --abbrev-ref HEAD
可以在$()中使用,并在Bash,Powershell,Perl等中轻松传递。如果您在提交中有多个分支,并且如果您当前不在分支上,则不会被欺骗,它只是回答“HEAD”。
或者,您可以使用
git symbolic-ref --short -q HEAD
这将为您提供相同的输出,但如果您已分离,它将不会返回任何内容。如果你想在分离时发生错误,这个很有用,只需删除-q。
答案 2 :(得分:43)
git name-rev --name-only HEAD
答案 3 :(得分:34)
从这个回答:https://stackoverflow.com/a/1418022/605356:
$ git rev-parse --abbrev-ref HEAD
master
显然适用于Git 1.6.3或更新版本。
答案 4 :(得分:18)
尝试:
git symbolic-ref --short -q HEAD
或者您尝试git branch
使用--no-color
强制简单的字符串输出:
git branch --no-color
使用正则表达式模式下的grep(-E
),您可以检查字符是否存在&#39; *&#39;:
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;
答案 5 :(得分:9)
使接受的答案适应windows powershell:
Split-Path -Leaf (git symbolic-ref HEAD)
答案 6 :(得分:8)
这个在bash文件中为我工作。
git branch | grep '^*' | sed 's/* //'
################bash file###################
#!/bin/bash
BRANCH=$(git branch | grep '^*' | sed 's/* //' )
echo $BRANCH
答案 7 :(得分:6)
这个对我有用。如果你想要一个普通的字符串,--no-color
部分是或者可能是重要的。
git branch --no-color | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
答案 8 :(得分:5)
我正在尝试这里最简单,最不言自明的方法:
git status | grep "On branch" | cut -c 11-
答案 9 :(得分:4)
以下是我的工作:
git branch | sed --quiet 's/* \(.*\)/\1/p'
输出如下:
$ git branch | sed --quiet 's/* \(.*\)/\1/p'
master
$
答案 10 :(得分:4)
我找到了两种非常简单的方法:
$ git status | head -1 | cut -d ' ' -f 4
和
$ git branch | grep "*" | cut -d ' ' -f 2
答案 11 :(得分:2)
这是我的解决方案,适用于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
位;我只是在PS1中的另一个函数中使用它,你可以在这里完整地查看:PS1 line with git current branch and colors
答案 12 :(得分:2)
如果您使用的是旧的NT命令行,则可以使用以下命令:
@for /f "usebackq" %i in (`git symbolic-ref -q HEAD`) do @echo %~ni
要在批处理文件中使用,您必须加倍%s:
@for /f "usebackq" %%i in (`git symbolic-ref -q HEAD`) do @echo %%~ni
答案 13 :(得分:2)
使用--porcelain可以轻松解析向后兼容的输出:
git status --branch --porcelain | grep '##' | cut -c 4-
来自文档:
瓷器格式类似于短格式,但保证不会在Git版本之间以向后兼容的方式更改或基于用户配置。这使其成为脚本解析的理想选择。
答案 14 :(得分:2)
有人提到在bash中用少于三个作业来做这件事......这样一些凌乱的控制流怎么样:
branch_name="$(b=$(git symbolic-ref -q HEAD); { [ -n "$b" ] && echo ${b##refs/heads/}; } || echo HEAD)"
答案 15 :(得分:1)
如果您使用的是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
}
```
答案 16 :(得分:1)
与单行变量赋值中的已接受答案相同的结果:
branch_name=$((git symbolic-ref HEAD 2>/dev/null || echo "(unnamed branch)")|cut -d/ -f3-)
答案 17 :(得分:0)
我发现调用git相当慢(任何子命令), 特别是用于更新提示。时间在回购的根目录内在.1和.2秒之间变化,在回购之前超过0.2秒,在顶级机器上突袭(突袭1,8 gb ram,8个硬件线程)。但它确实运行了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@/[^/]*$@@;
}
可能需要一些调整。
答案 18 :(得分:0)
如果你处于一个独立的头上(即你已经检查过一个版本)并且从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)中用
替换它# 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命令的参数。
答案 19 :(得分: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的伟大项目,正是这样做的(以及更多)。