Linux 如何将当前git分支的名称放入shell脚本中的变量中?

Linux 如何将当前git分支的名称放入shell脚本中的变量中?,linux,git,bash,shell,ubuntu,Linux,Git,Bash,Shell,Ubuntu,我不熟悉shell脚本,无法理解这一点。如果您不熟悉,那么命令git branch将返回如下内容 * develop master ,其中星号标记当前签出的分支。在终端中运行以下命令时: git branch | grep "*" 我得到: * develop 正如所料 然而,当我跑的时候 test=$(git branch | grep "*") 或 然后 echo $test ,结果只是目录中的文件列表。我们如何使test=“*开发”的价值 然后下一步(一旦我们将“*devel

我不熟悉shell脚本,无法理解这一点。如果您不熟悉,那么命令git branch将返回如下内容

* develop
  master
,其中星号标记当前签出的分支。在终端中运行以下命令时:

git branch | grep "*"
我得到:

* develop
正如所料

然而,当我跑的时候

test=$(git branch | grep "*")

然后

echo $test
,结果只是目录中的文件列表。我们如何使test=“*开发”的价值

然后下一步(一旦我们将“*develope”变成一个名为test的变量),就是获取子字符串。那会是以下情况吗

currentBranch=${test:2} 

我在玩那个子字符串函数,我经常遇到“坏替换”错误,不知道为什么。

扩展了*后,您可以使用sed而不是grep,并立即获得分支的名称:

branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
以及一个使用git符号ref的版本,正如努法尔·易卜拉欣所建议的那样

branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
为了详细说明扩展,(正如marco所做的那样,)扩展发生在echo中,当您使用包含
*master
$test
执行
$test
时,
*
将根据正常扩展规则进行扩展。要抑制此项,必须引用变量,如marco所示:
echo“$test”
。或者,如果在回显之前去掉星号,一切都会好的,例如,
echo${test:2}
只回显
master
。或者,您可以按照您的建议重新分配:

branch=${test:2}
echo $branch

这将根据您的需要回显
master

我将在git内核中使用
git symbolic ref
命令。如果您说
git symbolic ref HEAD
,您将得到当前分支的名称。

禁用子shell全局扩展

test=$(set -f; git branch)
问题在于:

echo $test
事实上,变量test包含一个通配符,该通配符由shell展开。要避免这种情况,请使用双引号保护$test:

echo "$test"
继续展开,将
--short
标志与
git symbolic ref
一起使用,无需对
sed
大惊小怪

我一直在hooks中使用类似的东西,效果很好:

#!/bin/bash

branch=$(git symbolic-ref --short HEAD)

echo
echo "**** Running post-commit hook from branch $branch"
echo
输出“****从分支主节点运行提交后钩子”

请注意,
git symbolic ref
仅在存储库中工作。幸运的是,
.git/HEAD
,作为git早期的一个遗留版本,包含了相同的符号ref。如果您想获得多个git存储库的活动分支,而不需要遍历目录,您可以使用如下bash one行文:

for repo in */.git; do branch=$(cat $repo/HEAD); echo ${repo%/.git} :  ${branch##*/}; done
其输出类似于:

repo1 : master  
repo2 : dev  
repo3 : issue12
如果您想更进一步,则
.git/HEAD
中包含的完整ref也是包含分支上次提交的SHA-1散列的文件的相对路径

我用这个
git descripe--contains--all HEAD
在我的git助手脚本中

例如:

#!/bin/bash
branchname=$(git describe --contains --all HEAD)
git pull --rebase origin $branchname
我在
~/scripts

编辑: 对于许多CI环境,他们会以“分离头”状态签出您的代码,因此我将使用:

BRANCH=$(\
  git for-each-ref \
  --format='%(objectname) %(refname:short)' refs/heads \
  | awk "/^$(git rev-parse HEAD)/ {print \$2}"\
)

如果您使用其中的元素更新您的答案,请您提及我的答案,这将是非常礼貌的。当然,我很抱歉,我在离开之前更新得很快,错过了属性。好的,所以我尝试了这两种方法,我必须说,
symbolic ref
并不总是有效。例如:如果您签出一些旧的提交,它会抛出错误,而
sed
命令会给出类似于
(头在1qw23er处分离)
的内容。注意:第一种技术即使分支名称中有正向斜杠(例如,因为它是一个问题URL),也会起作用,为什么在这种情况下第二个只取最后一段。这不是扩展发生的地方,而是在回音中,正如marco已经详细阐述的那样。在git的更高版本中,您将不得不使用git symbolic ref HEAD。您希望使用--short标志只获取分支名称。例如:在主分支上,
git symbolic ref HEAD
outputs
refs/heads/master
但是`git symbolic ref--short HEAD`只输出
master
试试。如果在星号周围使用单引号:
“*”
而不是
“*”
@glenn这不是扩展发生的地方,正如marco已经详细阐述的那样,它在echo中。
git descripe--contains--all HEAD
并没有给我当前的分支,正如用
git branch
突出显示的那样。这在jenkins构建脚本中很有用,谢谢注意:用git descripe,如果头部有一个标记,它将为您提供标记名,而不是分支名。
alias currentgitbranch='git symbolic ref--short HEAD'
这是最好的答案,使用
--short
可以得到您正在寻找的字符串。谢谢
BRANCH=$(\
  git for-each-ref \
  --format='%(objectname) %(refname:short)' refs/heads \
  | awk "/^$(git rev-parse HEAD)/ {print \$2}"\
)