web-dev-qa-db-fra.com

Comment obtenir le nom de la branche git actuelle dans une variable dans un script Shell?

Je suis nouveau dans les scripts Shell et je ne peux pas comprendre cela. Si vous n'êtes pas familier, la commande git branch retourne quelque chose comme

* develop
  master

, où l'astérisque marque la branche actuellement extraite. Lorsque j'exécute ce qui suit dans le terminal:

git branch | grep "*"

Je reçois:

* develop

comme prévu.

Cependant, quand je cours

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

ou

test=`git branch | grep "*"`

Puis

echo $test

, le résultat est juste une liste de fichiers dans le répertoire. Comment faire pour que la valeur de test = "* se développe"?

Ensuite, l'étape suivante (une fois que nous obtenons "* develop" en une variable appelée test), est d'obtenir la sous-chaîne. Serait-ce simplement le suivant?

currentBranch=${test:2} 

Je jouais avec cette fonction de sous-chaîne et j'ai souvent eu des erreurs de "mauvaise substitution" et je ne sais pas pourquoi.

63
Ben

Le * est développé, ce que vous pouvez faire est d'utiliser sed au lieu de grep et d'obtenir immédiatement le nom de la branche:

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

Et une version utilisant git symbolic-ref, comme suggéré par Noufal Ibrahim

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

Pour élaborer sur l'expansion, (comme marco l'a déjà fait), l'expansion se produit dans l'écho, lorsque vous faites echo $test avec $ test contenant "* master" puis le * est développé selon les règles d'expansion normales. Pour supprimer cela, il faudrait citer la variable, comme le montre marco: echo "$test". Alternativement, si vous vous débarrassez de l'astérisque avant de l'écho, tout ira bien, par exemple echo ${test:2} fera simplement écho à "master". Vous pouvez également l'attribuer à nouveau comme vous l'avez déjà proposé:

branch=${test:2}
echo $branch

Cela fera écho à "master", comme vous le vouliez.

81
wich

Développer sur réponse de Noufal Ibrahim , utilisez le --short drapeau avec git-symbolic-ref, pas besoin de s'occuper de sed.

J'ai utilisé quelque chose comme ça dans les crochets et cela fonctionne bien:

#!/bin/bash

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

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

Cela génère "**** Exécution du hook post-commit du maître de branche"

Notez que git-symbolic-ref ne fonctionne que si vous êtes dans un référentiel. Heureusement .git/HEAD, comme un reste des premiers jours de Git, contient la même référence symbolique. Si vous voulez obtenir la branche active de plusieurs référentiels git, sans parcourir les répertoires, vous pouvez utiliser un bash one-liner comme ceci:

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

Qui produit quelque chose comme:

repo1 : master  
repo2 : dev  
repo3 : issue12

Si vous voulez aller plus loin, la référence complète contenue dans .git/HEAD est également un chemin relatif vers un fichier contenant le hachage SHA-1 du dernier commit de la branche.

80
joemaller

J'utiliserais le git-symbolic-ref commande dans le noyau git. Si tu le dis git-symbolic-ref HEAD, vous obtiendrez le nom de la branche actuelle.

30
Noufal Ibrahim

J'utilise ce git describe --contains --all HEAD dans mes scripts d'aide git

exemple:

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

Je l'ai dans un fichier appelé gpull dans ~/scripts

Éditer:

pour de nombreux environnements CI, ils vérifieront votre code dans un état "tête détachée", alors j'utiliserai:

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

Le problème repose sur:

echo $test

En fait, le test de variable contient un caractère générique qui est développé par le Shell. Pour éviter cela, protégez simplement $ test avec des guillemets doubles:

echo "$test"
7
marco

désactiver l'expansion de glob de subshell,

test=$(set -f; git branch)
1
Dyno Fu