How to get the name of the current git branch into a variable in a shell script?
Solution 1
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.
Solution 2
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.
Solution 3
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.
Solution 4
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}"\
)
Solution 5
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"
Related videos on Youtube
Ben
Updated on February 02, 2021Comments
-
Ben over 3 years
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 the 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.
-
Dominik Sandjaja over 14 yearsTry this blog post.
-
glenn jackman over 14 yearsWhat if you use single quotes around the asterisk:
'*'
instead of"*"
-
wich over 14 years@glenn that's not where the expansion happens, it's in the echo, as marco already elaborated upon.
-
-
Noufal Ibrahim over 14 yearsIt would be courteous of you to mention my answer if you used elements from it to update yours.
-
wich over 14 yearsOf course, my apologies, I updated quickly before leaving, missed the attribution.
-
wich over 14 yearsthat's not where the expansion happens, it's in the echo, as marco already elaborated upon.
-
Jamey Hicks over 14 yearsIn later version of git, you will have to use git symbolic-ref HEAD instead.
-
hakre about 10 years
git describe --contains --all HEAD
does not give me the current branch as highlighted by a star withgit branch
. -
nemesisdesign over 9 yearsthis was useful in a jenkins build script, thanks
-
Pat almost 9 years
alias currentgitbranch='git symbolic-ref --short HEAD'
-
zhirzh over 8 yearsok, so I tried both the methods, and I must say that
symbolic-ref
won't always work. eg: if you checkout some old commit, it throws error, whereas thesed
command gives something like(HEAD detached at 1qw23er)
-
Aral Balkan about 8 yearsNote: the first technique works even if there are forward slashes in the branch name (e.g., because it is an issue URL), why the second one only takes the last segment in that case.
-
0atman almost 8 yearsThis is the best answer, using
--short
gets you just the string you are looking for. Thanks! -
UTF_or_Death about 5 yearsYou'd want to use the --short flag to only get the branch name. For an example: While on the master branch
git-symbolic-ref HEAD
outputsrefs/heads/master
but ` git-symbolic-ref --short HEAD` only outputsmaster
-
João Portela about 3 yearsAttention: With git describe, if you have a tag on HEAD it will give you the tag name instead of branch name.
-
wilbur4321 about 2 years
sed
makes this even easier, actually!branch=$(git branch | sed '/^ /d;s/^\* //')