问题描述
我是shell脚本的新手,无法解决这个问题。如果您不熟悉,命令git branch会返回类似的内容
* develop
master
,星号标记当前签出的分支。当我在终端中运行以下内容时:
git branch | grep "*"
我明白了:
* develop
正如所料。
但是,当我跑
test=$(git branch | grep "*")
要么
test=`git branch | grep "*"`
然后
echo $test
,结果只是目录中的文件列表。我们如何使test =“* develop”的价值?
然后下一步(一旦我们将“* develop”变成一个名为test的变量),就是得到子串。这只是以下几点吗?
currentBranch=${test:2}
我正在玩那个子串函数,我得到了很多”bad substitution”错误,不知道为什么。
最佳解决方案
*被扩展,你可以做的是使用sed而不是grep并立即得到分支的名称:
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
和Noufal Ibrahim建议的使用git symbolic-ref的版本
branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
为了详细说明扩展(如marco已经做的那样),扩展发生在echo中,当你使用$ test包含“* master”进行echo $test
时,*会根据正常的扩展规则进行扩展。为了抑制这个,必须引用变量,如marco所示:echo "$test"
。或者,如果你在回音之前摆脱了星号,一切都会好的,例如: echo ${test:2}
将回复”master”。或者,您可以按照您的建议重新分配:
branch=${test:2}
echo $branch
这将回复”master”,就像你想要的那样。
次佳解决方案
在Noufal Ibrahim’s answer上扩展,使用带有git-symbolic-ref
的--short
标志,无需对sed
大惊小怪。
我一直在钩子中使用这样的东西,它运作良好:
#!/bin/bash
branch=$(git symbolic-ref --short HEAD)
echo
echo "**** Running post-commit hook from branch $branch"
echo
输出“****从分支主机运行post-commit钩子”
请注意,git-symbolic-ref
仅在您位于存储库中时才有效。幸运的是,.git/HEAD
作为Git早期的遗留物,含有相同的符号引用。如果你想获得几个git存储库的活动分支,而不遍历目录,你可以像这样使用bash one-liner:
for repo in */.git; do branch=$(cat $repo/HEAD); echo ${repo%/.git} : ${branch##*/}; done
哪个输出如下:
repo1 : master
repo2 : dev
repo3 : issue12
如果你想更进一步,.git/HEAD
中包含的完整引用也是包含分支最后一次提交的SHA-1哈希的文件的相对路径。
第三种解决方案
我会在git核心中使用git-symbolic-ref
命令。如果您说git-symbolic-ref HEAD
,您将获得当前分支的名称。
第四种方案
我在我的git helper脚本中使用了这个git describe --contains --all HEAD
例:
#!/bin/bash
branchname=$(git describe --contains --all HEAD)
git pull --rebase origin $branchname
我在~/scripts
中名为gpull
的文件中有这个
编辑:
对于很多CI环境,他们会在”detached head”状态下检查你的代码,然后我将使用:
BRANCH=$(\
git for-each-ref \
--format='%(objectname) %(refname:short)' refs/heads \
| awk "/^$(git rev-parse HEAD)/ {print \$2}"\
)
第五种方案
问题依赖于:
echo $test
事实上,变量测试包含一个由shell扩展的通配符。为了避免这种情况,只需使用双引号保护$ test:
echo "$test"