web-dev-qa-db-fra.com

Déterminer si le répertoire de travail Git est propre à partir d'un script

J'ai un script qui exécute rsync avec un répertoire de travail Git comme destination. Je veux que le script ait un comportement différent selon que le répertoire de travail est propre (aucune modification à valider) ou non. Par exemple, si la sortie de git status est comme ci-dessous, je veux que le script se termine:

git status
Already up-to-date.
# On branch master
nothing to commit (working directory clean)
Everything up-to-date

Si le répertoire n'est pas propre, j'aimerais qu'il exécute quelques commandes supplémentaires.

Comment puis-je vérifier la sortie comme ci-dessus dans un script Shell?

102
brentwpeterson

Analyser la sortie de git status est une mauvaise idée car la sortie est destinée à être lisible par l'homme, pas lisible par la machine. Il n'y a aucune garantie que la sortie restera la même dans les futures versions de Git ou dans des environnements configurés différemment.

commentaire UVV est sur la bonne voie, mais malheureusement le code retour de git status ne change pas en cas de modifications non validées. Il fournit cependant les --porcelain , qui provoque la sortie de git status --porcelain à formater dans un format facile à analyser pour les scripts, et resteront stables dans toutes les versions de Git et quelle que soit la configuration de l'utilisateur.

Nous pouvons utiliser une sortie vide de git status --porcelain comme indicateur qu'aucune modification ne doit être validée:

if [ -z "$(git status --porcelain)" ]; then 
  # Working directory clean
else 
  # Uncommitted changes
fi

Si nous ne nous soucions pas des fichiers non suivis dans le répertoire de travail, nous pouvons utiliser le --untracked-files=no option pour ignorer ceux-ci:

if [ -z "$(git status --untracked-files=no --porcelain)" ]; then 
  # Working directory clean excluding untracked files
else 
  # Uncommitted changes in tracked files
fi

Pour rendre cela plus robuste contre des conditions qui réellement provoquent git status pour échouer sans sortie vers stdout, nous pouvons affiner la vérification pour:

if output=$(git status --porcelain) && [ -z "$output" ]; then
  # Working directory clean
else 
  # Uncommitted changes
fi

Il convient également de noter que, bien que git status ne donne pas de code de sortie significatif lorsque le répertoire de travail est impur, git diff fournit le --exit-code , ce qui le rend similaire à l'utilitaire diff , c'est-à-dire qu'il quitte avec le statut 1 quand il y avait des différences et 0 quand aucun n'a été trouvé.

À l'aide de cela, nous pouvons vérifier les modifications non planifiées avec:

git diff --exit-code

et des changements échelonnés mais non validés avec:

git diff --cached --exit-code

Bien que git diff peut signaler des fichiers non suivis dans des sous-modules via des arguments appropriés pour --ignore-submodules , malheureusement, il semble qu'il n'y ait aucun moyen de le signaler sur les fichiers non suivis dans le répertoire de travail réel. Si les fichiers non suivis du répertoire de travail sont pertinents, git status --porcelain est probablement le meilleur choix.

160
Thomas Nyman

Utilisation:

git diff-index --quiet HEAD

Le code retour reflète l'état du répertoire de travail (0 = propre, 1 = sale). Les fichiers non suivis sont ignorés.

25
André van Herk

Extension mineure à celle d'André excellente réponse .

C'est une façon d'évaluer les résultats et d'éviter également un piège si vous êtes dans un script qui a précédemment publié set -e .

Les fichiers non suivis sont ignorés.

set +e
git diff-index --quiet HEAD

if [ $? == 1 ] ; then
  set -e
  GIT_MODS="dirty"
else
  set -e
  GIT_MODS="clean"
fi
1
orion elenzil

J'ai fait ce genre de test

TEST=$(git status --porcelain|wc -l)
if [ 0 -eq $TEST ]; then
   echo "No changes"
else
   echo "Changes"
fi 
1
PHZ.fi-Pharazon
#!/bin/bash
echo "First arg: $1"

cd $1

bob="Already up-to-date."
echo $bob

echo $(git pull) > s.txt
cat s.txt
if [ "$(cat s.txt)" == "$bob" ]
then
echo "up"
else
echo "not up"
fi
rm -rf s.txt
0
Robert A