I am new to shell scripting and can't figure this out. If you are unfamiliar, the command git branch returns something like
* 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"?
Then th开发者_Python百科e next step (once we get "* develop" into a variable called test), is to get the substring. Would that just be the following?
currentBranch=${test:2}
I was playing around with that substring function and I got "bad substitution" errors a lot and don't know why.
The * is expanded, what you can do is use sed instead of grep and get the name of the branch immediately:
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
And a version using git symbolic-ref, as suggested by Noufal Ibrahim
branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
To elaborate on the expansion, (as marco already did,) the expansion happens in the echo, when you do echo $test
with $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:
branch=${test:2}
echo $branch
This will echo master
, like you wanted.
Expanding on Noufal Ibrahim's answer, use the --short
flag with git-symbolic-ref
, no need to fuss with 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-ref
only 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:
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/HEAD
is also a relative path to a file containing the SHA-1 hash of the branch's last commit.
I would use the git-symbolic-ref
command in the git core. If you say git-symbolic-ref HEAD
, you will get the name of the current branch.
I use this
git describe --contains --all HEAD
in my git helper scripts
example:
#!/bin/bash
branchname=$(git describe --contains --all HEAD)
git pull --rebase origin $branchname
I have that in a file called gpull
in ~/scripts
Edit:
for a lot of CI environments, they'll check your code out in a "detached head" state, so then I'll use:
BRANCH=$(\
git for-each-ref \
--format='%(objectname) %(refname:short)' refs/heads \
| awk "/^$(git rev-parse HEAD)/ {print \$2}"\
)
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:
echo "$test"
disable subshell glob expansion,
test=$(set -f; git branch)
精彩评论