La clé d'un "scripting" fiable de Git est d'utiliser les commandes de "plomberie".
Les développeurs prennent soin, lorsqu'ils modifient les commandes de plomberie, de s'assurer qu'elles fournissent des interfaces très stables (c'est-à-dire qu'une combinaison donnée d'état du dépôt, de stdin, d'options de ligne de commande, d'arguments, etc. produira la même sortie dans toutes les versions de Git où la commande/option existe). De nouvelles variations de sortie dans les commandes de plomberie peuvent être introduites via de nouvelles options, mais cela ne peut pas introduire de problèmes pour les programmes qui ont déjà été écrits contre des versions plus anciennes (ils n'utiliseraient pas les nouvelles options, puisqu'elles n'existaient pas (ou du moins n'étaient pas utilisées) au moment où le script a été écrit).
Malheureusement, les commandes Git "de tous les jours" sont les commandes "en porcelaine", de sorte que la plupart des utilisateurs de Git ne sont pas familiers avec les commandes de plomberie. La distinction entre les commandes "porcelaine" et les commandes "plomberie" est faite dans les principaux éléments suivants page de manuel git (voir les sous-sections intitulées Commandes de haut niveau (porcelaine) y Commandes de bas niveau (plomberie) .
Pour vous renseigner sur les modifications non admises, vous aurez probablement besoin de git diff-index
(comparer l'index (et peut-être les éléments suivis de l'arbre de travail) avec d'autres arbres (par ex. HEAD
)), peut-être git diff-files
(comparer l'arbre de travail à l'index), et éventuellement git ls-files
(liste des fichiers ; par exemple, liste des fichiers non suivis, non ignorés).
(Notez que dans les commandes ci-dessous, HEAD --
est utilisé à la place de HEAD
car sinon la commande échoue s'il existe un fichier nommé HEAD
.)
Pour vérifier si un dépôt a des changements indexés (pas encore livrés), utilisez ceci :
git diff-index --quiet --cached HEAD --
- S'il sort avec
0
puis il n'y a pas eu de différences ( 1
signifie qu'il y avait des différences).
Pour vérifier si un arbre de travail a des changements qui pourraient être mis en scène :
git diff-files --quiet
- Le code de sortie est le même que pour
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'arborescence de travail a changé par rapport à HEAD
:
git diff-index --quiet HEAD --
- C'est comme une combinaison des deux précédentes. La principale différence est qu'il ne signalera toujours "aucune différence" si vous avez une modification échelonnée que vous avez "annulée" dans l'arbre de travail (retour au contenu qui se trouve dans l'arbre de travail).
HEAD
). Dans cette même situation, les deux commandes distinctes renverraient toutes deux le rapport "différences présentes".
Vous avez également mentionné les fichiers non tracés. Vous pouvez vouloir dire "non suivis et non ignorés", ou vous pouvez vouloir dire simplement "non suivis" (y compris les fichiers ignorés). Dans tous les cas, git ls-files
est l'outil idéal pour ce travail :
Pour "untracked" (inclura les fichiers ignorés, s'ils sont présents) :
git ls-files --others
Pour "sans trace et sans signe" :
git ls-files --exclude-standard --others
Ma première idée est de vérifier si ces commandes ont un résultat :
test -z "$(git ls-files --others)"
- S'il sort avec
0
alors il n'y a pas de fichiers non tracés. S'il sort avec 1
alors il y a des fichiers non tracés.
Il y a une petite chance que cela se traduise par des sorties anormales de git ls-files
en rapports "no untracked files" (les deux résultent en 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"
- L'idée est la même que la commande précédente, mais elle permet aux erreurs inattendues de
git ls-files
pour se propager à l'extérieur. Dans ce cas, une sortie non nulle pourrait signifier "il y a des fichiers non suivis" ou cela pourrait signifier qu'une erreur s'est produite. Si vous voulez que le résultat "erreur" soit combiné avec le résultat "pas de fichiers non suivis" à la place, utilisez test -n "$u"
(où la sortie de 0
signifie "quelques fichiers non suivis", et un chiffre différent de zéro signifie une erreur ou "aucun fichier non suivi").
Une autre idée est d'utiliser --error-unmatch
pour provoquer une sortie non nulle lorsqu'il n'y a pas de fichiers non suivis. Cela présente également le risque de confondre "aucun fichier non suivi" (exit 1
) avec "une erreur s'est produite" (sortie non nulle, mais probablement 128
). Mais la vérification de 0
vs. 1
par rapport aux codes de sortie non nuls est probablement assez robuste :
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
les exemples peuvent prendre --exclude-standard
si vous voulez considérer uniquement les fichiers non suivis et non ignorés.
3 votes
Git status retournera 1 s'il y a des fichiers modifiés non paginés. Mais en général, je trouve que les outils git ne sont pas particulièrement minutieux avec le retour du statut. EG git diff renvoie 0, qu'il y ait ou non des différences.
11 votes
@intuited : Si vous avez besoin
diff
pour indiquer la présence ou l'absence de différences plutôt que l'exécution réussie de la commande, alors vous devez utiliser--exit-code
o--quiet
. les commandes git sont généralement très cohérentes avec le retour d'un code de sortie zéro ou non zéro pour indiquer le succès de la commande.1 votes
Charles Bailey : Super, j'ai manqué cette option. Merci ! Je suppose que je n'ai jamais vraiment eu besoin de le faire, sinon j'aurais probablement parcouru la page de manuel pour cela. Content que vous m'ayez corrigé :)
1 votes
Robert - c'est un sujet très confus pour la communauté (le fait que le mot "porcelaine" soit utilisé différemment dans différents contextes n'aide pas). La réponse que vous avez choisie ignore une réponse 2,5 fois plus votée qui est plus robuste et qui suit la conception de git. Avez-vous vu la réponse de @ChrisJ ?
1 votes
@Robert - J'espère que vous pourriez envisager de modifier votre réponse acceptée. Celle que vous avez choisie s'appuie sur des commandes git 'porcelaine' plus fragiles ; la réponse correcte (également avec 2x les votes positifs) repose sur les commandes correctes de git "plomberie". Cette réponse correcte a été donnée à l'origine par Chris Johnsen. Je soulève ce point car c'est la troisième fois aujourd'hui que je dois renvoyer quelqu'un à cette page, mais je ne peux pas simplement indiquer la réponse, je dois expliquer pourquoi la réponse acceptée est sous-optimale / limite fausse. Merci !