Comment puis-je vérifier si des modifications non validées ont été apportées dans mon référentiel git:
à partir d'un script?
git-status
semble toujours renvoyer zéro avec la version 1.6.4.2 de Git.
Bon timing! J'ai écrit un article de blog à ce sujet il y a quelques jours à peine, quand j'ai découvert comment ajouter des informations sur le statut des git à mon invite.
Voici ce que je fais:
Pour le statut sale:
# Returns "*" if the current git branch is dirty.
function evil_git_dirty {
[[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "*"
}
Pour les fichiers non suivis (notez le --porcelain
flag à git status
qui vous donne une sortie analysable de Nice):
# Returns the number of untracked files
function evil_git_num_untracked_files {
expr `git status --porcelain 2>/dev/null| grep "^??" | wc -l`
}
Bien que git diff --shortstat
est plus pratique, vous pouvez aussi utiliser git status --porcelain
pour obtenir des fichiers corrompus:
# Get number of files added to the index (but uncommitted)
expr $(git status --porcelain 2>/dev/null| grep "^M" | wc -l)
# Get number of files that are uncommitted and not added
expr $(git status --porcelain 2>/dev/null| grep "^ M" | wc -l)
# Get number of total uncommited files
expr $(git status --porcelain 2>/dev/null| egrep "^(M| M)" | wc -l)
Noter la 2>/dev/null
filtre les messages d'erreur afin que vous puissiez utiliser ces commandes sur des répertoires non-git. (Ils vont simplement retourner 0
pour le nombre de fichiers.)
Modifier:
Voici les messages:
Ajout d'informations sur le statut Git à votre invite de terminal
La clé pour "scripter" de manière fiable Git consiste à utiliser les commandes de "plomberie".
Lors du changement des commandes de plomberie, les développeurs veillent à fournir des interfaces très stables (une combinaison donnée d’états de référentiel, stdin, options de ligne de commande, arguments, etc. produiront le même résultat dans toutes les versions de Git où la commande/l'option existe). De nouvelles variations de sortie dans les commandes de plomberie peuvent être introduites via de nouvelles options, mais cela ne pose aucun problème pour les programmes déjà écrits avec des versions plus anciennes (ils n'utiliseraient pas les nouvelles options, car elles n'existaient pas (ou du moins étaient pas utilisé) au moment de la rédaction du script).
Malheureusement, les commandes Git "quotidiennes" sont les commandes "porcelaine". Par conséquent, la plupart des utilisateurs de Git peuvent ne pas être familiarisés avec les commandes de plomberie. La distinction entre commande de porcelaine et commande de plomberie est faite dans la commande principale git manpage (voir les sous-sections intitulées Commandes de haut niveau (porcelaine) et Commandes de bas niveau (plomberie ) .
Pour en savoir plus sur les modifications non validées, vous aurez probablement besoin de git diff-index
(compare l’index (et peut-être des morceaux d’arbre de travail suivis) à un autre arbre (par exemple, HEAD
)), peut-être git diff-files
(compare l’arbre de travail à l’index), et éventuellement git ls-files
(liste de fichiers; par exemple, liste de fichiers non suivis, non ignorés).
(Notez que dans les commandes ci-dessous, HEAD --
est utilisé à la place de HEAD
, sinon la commande échec s’il existe un fichier nommé HEAD
.)
Pour vérifier si un référentiel a mis en place des modifications (non encore validées), utilisez ceci:
git diff-index --quiet --cached HEAD --
0
alors il n'y avait pas de différences (1
_ signifie qu'il y avait des différences).Pour vérifier si un arbre de travail contient des modifications pouvant être mises en place:
git diff-files --quiet
git diff-index
(0
== pas de différences; 1
_ == différences).Pour vérifier si la combinaison de l'index et des fichiers suivis dans l'arbre de travail présente des modifications par rapport à HEAD
:
git diff-index --quiet HEAD --
HEAD
). Dans cette même situation, les deux commandes distinctes renverraient toutes les deux des rapports de "différences présentes".Vous avez également mentionné les fichiers non suivis. Vous pourriez vouloir dire "non suivi et non marqué", ou simplement "non suivi" (y compris les fichiers ignorés). D'une manière ou d'une autre, git ls-files
est l'outil pour le travail:
Pour "non suivi" (inclura les fichiers ignorés, le cas échéant):
git ls-files --others
Pour “non suivi et non ignoré”:
git ls-files --exclude-standard --others
Ma première pensée est de vérifier si ces commandes ont une sortie:
test -z "$(git ls-files --others)"
0
alors il n'y a pas de fichiers non suivis. S'il existe avec 1
puis il y a des fichiers non suivis.Il y a un petit risque que cela traduise des sorties anormales de git ls-files
dans des rapports "Pas de fichiers non suivis" (les deux entraînent des sorties non nulles de la commande ci-dessus). Une version un peu plus robuste pourrait ressembler à ceci:
u="$(git ls-files --others)" && test -z "$u"
git ls-files
pour se propager. Dans ce cas, une sortie non nulle pourrait signifier "il y a des fichiers non suivis" ou une erreur. Si vous voulez plutôt que les résultats "erreur" soient combinés au résultat "pas de fichiers non suivis", utilisez test -n "$u"
(où sortie de 0
signifie “certains fichiers non suivis” et non nul signifie une erreur ou “pas de fichiers non suivis”).Une autre idée est d'utiliser --error-unmatch
pour provoquer une sortie non nulle en l'absence de fichiers non suivis. Cela risquerait également de confondre "pas de fichiers non suivis" (exit 1
) avec “une erreur est survenue” (sortie non nulle, mais probablement 128
). Mais vérifier pour 0
contre. 1
vs. les codes de sortie non nuls sont probablement assez robustes:
git ls-files --others --error-unmatch . >/dev/null 2>&1; ec=$?
if test "$ec" = 0; then
echo some untracked files
Elif test "$ec" = 1; then
echo no untracked files
else
echo error from ls-files
fi
Tout ce qui précède git ls-files
exemples peuvent prendre --exclude-standard
_ si vous ne souhaitez prendre en compte que les fichiers non suivis et non ignorés.
En supposant que vous soyez sur git 1.7.0 ou plus tard ...
Après avoir lu toutes les réponses sur cette page et quelques expériences, je pense que la méthode qui convient le mieux pour concilier exactitude et brièveté est la suivante:
test -n "$(git status --porcelain)"
Bien que git permette une grande nuance entre ce qui est suivi, ignorer, non suivi mais non-ignoré, etc., je pense que le cas d'utilisation typique est l'automatisation des scripts de construction, dans lesquels vous voulez tout arrêter si votre paiement n'est pas propre.
Dans ce cas, il est logique de simuler ce que ferait le programmeur: tapez git status
Et regardez le résultat. Mais nous ne voulons pas nous fier à des mots spécifiques, nous utilisons donc le mode --porcelain
Introduit dans 1.7.0; lorsqu'il est activé, un répertoire vide ne génère aucun résultat.
Ensuite, nous utilisons test -n
Pour voir s'il y a eu une sortie ou non.
Cette commande retournera 1 si le répertoire de travail est propre et 0 s'il y a des modifications à valider. Vous pouvez remplacer le -n
Par un -z
Si vous voulez le contraire. Ceci est utile pour chaîner cela à une commande dans un script. Par exemple:
test -z "$(git status --porcelain)" || red-alert "UNCLEAN UNCLEAN"
Cela dit effectivement "soit il n'y a aucune modification à apporter, soit une alarme"; Ce one-liner peut être préférable à une instruction if, selon le script que vous écrivez.
Une implémentation de la réponse de VonC :
if [[ -n $(git status --porcelain) ]]; then echo "repo is dirty"; fi
J'ai jeté un coup d'œil à quelques-unes de ces réponses ... (et j'ai eu divers problèmes sur * nix et windows, ce qui était une exigence que j'avais) ... ... a trouvé que ce qui suit fonctionnait bien ...
git diff --no-ext-diff --quiet --exit-code
Pour vérifier le code de sortie dans * nix
echo $?
#returns 1 if the repo has changes (0 if clean)
Pour vérifier le code de sortie dans la fenêtre $
echo %errorlevel%
#returns 1 if the repos has changes (0 if clean)
En provenance de https://github.com/sindresorhus/pure/issues/115 Merci à @paulirish pour ce partage
Pourquoi ne pas encapsuler 'git status
avec un script qui:
De cette façon, vous pouvez utiliser ce statut "amélioré" dans votre script.
Comme xfe mentionne dans son excellente réponse , git status --porcelain
est essentiel à toute solution basée sur un script
--porcelain
Donnez la sortie dans un format stable et facile à analyser pour les scripts.
Actuellement, cela est identique à--short output
, mais est garanti pour ne pas changer à l'avenir, le rendant sûr pour les scripts.
Une possibilité de bricolage, mise à jour pour suivre la suggestion de xfe
#!/bin/sh
exit $(git status --porcelain | wc -l)
Comme indiqué par Chris Johnsen , cela ne fonctionne que sur Git 1.7.0 ou plus récent.
J'avais souvent besoin d'un moyen simple pour échouer une construction si, à la fin de l'exécution, il existait des fichiers suivis modifiés ou des fichiers non suivis qui n'étaient pas ignorés.
Ceci est très important pour éviter les cas où les builds produisent des restes.
Jusqu'ici, la meilleure commande que j'ai finalement utilisée ressemble à ceci:
test -z "$(git status --porcelain | tee /dev/fd/2)" || \
{{ echo "ERROR: git unclean at the end, failing build." && return 1 }}
Cela peut paraître un peu complexe et j'apprécierais que quiconque trouve une variante raccourcie maintienne le comportement souhaité:
La réponse de @ eduard-wirch était assez complète, mais comme je voulais vérifier les deux en même temps, voici ma dernière variante.
set -eu
u="$(git ls-files --others)"
if ! git diff-index --name-only --quiet HEAD -- || [ -z "${u:-}" ]; then
dirty="-dirty"
fi
Lorsque vous n'exécutez pas avec set-e ou équivalent, nous pouvons à la place faire un u="$(git ls-files --others)" || exit 1
(ou le retourner si cela fonctionne pour une fonction utilisée)
Donc, untracked_files, n'est défini que si la commande réussit correctement.
après quoi, nous pouvons vérifier les deux propriétés et définir une variable (ou autre).
Vous pouvez aussi faire
git describe --dirty
. Il ajoutera le mot "-dirty" à la fin s'il détecte un arbre de travail sale. Selon git-describe(1)
:
--dirty[=<mark>]
Describe the working tree. It means describe HEAD and appends <mark> (-dirty by default) if
the working tree is dirty.
. Mise en garde: les fichiers non suivis ne sont pas considérés comme "sales", car, comme l'indique la page de manuel, elle ne s'intéresse qu'à l'arbre de travail.
Il s’agit d’une variante plus conviviale pour Shell permettant de déterminer si aucun fichiers non suivis existent dans le référentiel:
# Works in bash and zsh
if [[ "$(git status --porcelain 2>/dev/null)" = *\?\?* ]]; then
echo untracked files
fi
Cela ne crée pas un second processus, grep
, et il n'est pas nécessaire de vérifier si vous êtes dans un référentiel git ou non. Ce qui est pratique pour les invites de Shell, etc.
Il peut y avoir une meilleure combinaison de réponses de ce fil .. mais cela fonctionne pour moi ... pour votre .gitconfig
_ [alias]
section ...
# git untracked && echo "There are untracked files!"
untracked = ! git status --porcelain 2>/dev/null | grep -q "^??"
# git unclean && echo "There are uncommited changes!"
unclean = ! ! git diff --quiet --ignore-submodules HEAD > /dev/null 2>&1
# git dirty && echo "There are uncommitted changes OR untracked files!"
dirty = ! git untracked || git unclean
Le test automatique le plus simple que j'utilise pour détecter état sale = tout changement, y compris les fichiers non suivis :
git add --all
git diff-index --exit-code HEAD
REMARQUE:
add --all
diff-index
ne remarque pas les fichiers non suivis.git reset
après avoir testé le code d’erreur pour tout effacer.