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

LinuxGitBashShellUbuntu

Linux Problem Overview


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.

Linux Solutions


Solution 1 - Linux

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 - Linux

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 - Linux

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 - Linux

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 - Linux

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"

Solution 6 - Linux

disable subshell glob expansion,

test=$(set -f; git branch)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBenView Question on Stackoverflow
Solution 1 - LinuxwichView Answer on Stackoverflow
Solution 2 - LinuxjoemallerView Answer on Stackoverflow
Solution 3 - LinuxNoufal IbrahimView Answer on Stackoverflow
Solution 4 - LinuxNullVoxPopuliView Answer on Stackoverflow
Solution 5 - LinuxmarcoView Answer on Stackoverflow
Solution 6 - LinuxDyno FuView Answer on Stackoverflow