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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2111042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:42:27  来源:igfitidea点击:

How to get the name of the current git branch into a variable in a shell script?

linuxgitbashshellubuntu

提问by Ben

I am new to shell scripting and can't figure this out. If you are unfamiliar, the command git branch returns something like

我是 shell 脚本的新手,无法弄清楚这一点。如果您不熟悉,命令 git branch 会返回类似

* develop
  master

, where the asterisk marks the currently checked out branch. When I run the following in the terminal:

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

git branch | grep "*"

I get:

我得到:

* develop

as expected.

正如预期的那样。

However, when I run

然而,当我跑

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

or

或者

test=`git branch | grep "*"`

And then

进而

echo $test

, the result is just a list of files in the directory. How do we make the value of test="* develop"?

,结果只是目录中的文件列表。我们如何使 test="* develop" 的值?

Then the next step (once we get "* develop" into a variable called test), is to get the substring. Would that just be the following?

然后下一步(一旦我们将“* develop”放入名为 test 的变量中),就是获取子字符串。那只会是以下吗?

currentBranch=${test:2} 

I was playing around with that substring function and I got "bad substitution" errors a lot and don't know why.

我在玩那个子字符串函数,我得到了很多“坏替换”错误,不知道为什么。

采纳答案by wich

The * is expanded, what you can do is use sed instead of grep and get the name of the branch immediately:

* 被扩展,你可以做的是使用 sed 而不是 grep 并立即获取分支的名称:

branch=$(git branch | sed -n -e 's/^\* \(.*\)//p')

And a version using git symbolic-ref, as suggested by Noufal Ibrahim

以及使用 git 符号引用的版本,如 Noufal Ibrahim 所建议的

branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),,')

To elaborate on the expansion, (as marco already did,) the expansion happens in the echo, when you do echo $testwith $test containing "* master" then the * is expanded according to the normal expansion rules. To suppress this one would have to quote the variable, as shown by marco: echo "$test". Alternatively, if you get rid of the asterisk before you echo it, all will be fine, e.g. echo ${test:2}will just echo "master". Alternatively you could assign it anew as you already proposed:

为了详细说明扩展,(正如 marco 已经做过的那样)扩展发生在 echo 中,当您echo $test使用包含“* master”的 $test 时,* 将根据正常扩展规则进行扩展。要抑制这一点,必须引用变量,如 marco: 所示echo "$test"。或者,如果您在回显之前去掉星号,一切都会好起来的,例如echo ${test:2}只回显“master”。或者,您可以按照您已经提议的方式重新分配它:

branch=${test:2}
echo $branch

This will echo "master", like you wanted.

这将呼应“主人”,就像您想要的那样。

回答by Noufal Ibrahim

I would use the git-symbolic-refcommand in the git core. If you say git-symbolic-ref HEAD, you will get the name of the current branch.

我会git-symbolic-ref在 git 核心中使用该命令。如果你说git-symbolic-ref HEAD,你会得到当前分支的名称。

回答by Dyno Fu

disable subshell glob expansion,

禁用子shell glob扩展,

test=$(set -f; git branch)

回答by marco

The problem relies on:

问题依赖于:

echo $test

In fact the variable test contains a wildcard which is expanded by the shell. To avoid that just protect $test with double quotes:

事实上,变量 test 包含一个由 shell 扩展的通配符。为了避免这种情况,只需用双引号保护 $test :

echo "$test"

回答by joemaller

Expanding on Noufal Ibrahim's answer, use the --shortflag with git-symbolic-ref, no need to fuss with sed.

扩展Noufal Ibrahim 的答案,使用--short带有的标志git-symbolic-ref,无需大惊小怪sed

I've been using something like this in hooks and it works well:

我一直在钩子中使用这样的东西,它运行良好:

#!/bin/bash

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

echo
echo "**** Running post-commit hook from branch $branch"
echo

That outputs "**** Running post-commit hook from branch master"

输出“**** 从分支主运行后提交钩子”

Note that git-symbolic-refonly works if you're in a repository. Luckily .git/HEAD, as a leftover from Git's early days, contains the same symbolic ref. If you want to get the active branch of several git repositories, without traversing directories, you could use a bash one-liner like this:

请注意,git-symbolic-ref仅当您在存储库中时才有效。幸运的是.git/HEAD,作为 Git 早期的遗留物,包含相同的符号引用。如果您想获取多个 git 存储库的活动分支,而无需遍历目录,您可以像这样使用 bash one-liner:

for repo in */.git; do branch=$(cat $repo/HEAD); echo ${repo%/.git} :  ${branch##*/}; done

Which outputs something like:

输出类似于:

repo1 : master  
repo2 : dev  
repo3 : issue12

If you want to go further, the full ref contained in .git/HEADis also a relative path to a file containing the SHA-1 hash of the branch's last commit.

如果您想更进一步,包含的完整 ref.git/HEAD也是包含分支上次提交的 SHA-1 哈希的文件的相对路径。

回答by NullVoxPopuli

I use this git describe --contains --all HEADin my git helper scripts

git describe --contains --all HEAD在我的 git helper 脚本中使用它

example:

例子:

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

I have that in a file called gpullin ~/scripts

我在一个叫做gpullin的文件中有它~/scripts

Edit:

编辑:

for a lot of CI environments, they'll check your code out in a "detached head" state, so then I'll use:

对于许多 CI 环境,他们会在“分离头”状态下检查您的代码,因此我将使用:

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