La chiave per un "scripting" affidabile di Git è usare i comandi "idraulici".
Gli sviluppatori si preoccupano quando cambiano i comandi idraulici per assicurarsi che forniscano interfacce molto stabili (cioè una data combinazione di stato del repository, stdin, opzioni della riga di comando, argomenti, ecc. Produrrà lo stesso output in tutte le versioni di Git dove il comando / opzione esiste). Nuove variazioni di output nei comandi idraulici possono essere introdotte tramite nuove opzioni, ma ciò non può comportare problemi per i programmi che sono già stati scritti su versioni precedenti (non utilizzerebbero le nuove opzioni, poiché non esistevano (o almeno lo erano non utilizzato) al momento della stesura dello script).
Sfortunatamente i comandi Git "di tutti i giorni" sono i comandi "porcellana", quindi la maggior parte degli utenti Git potrebbe non avere familiarità con i comandi idraulici. La distinzione tra comando di porcellana e comando idraulico viene fatta nella manpage git principale (vedere le sottosezioni intitolate Comandi di alto livello (porcellana) e Comandi di basso livello (impianto idraulico) .
Per scoprire modifiche senza compromessi, sarà probabilmente necessario git diff-index
(confrontare l'indice (e forse i bit tracciati dell'albero di lavoro) con qualche altro albero (ad es. HEAD
)), Forse git diff-files
(confrontare l'albero di lavoro con l'indice) e possibilmente git ls-files
(elencare i file; ad es. Elenco non monitorato , file non firmati).
(Si noti che nei comandi seguenti HEAD --
viene utilizzato anziché HEAD
perché altrimenti il comando non riesce se esiste un file denominato HEAD
.)
Per verificare se un repository ha messo in scena modifiche (non ancora impegnate) utilizzare questo:
git diff-index --quiet --cached HEAD --
- Se esce con
0
allora non c'erano differenze ( 1
significa che c'erano differenze).
Per verificare se un albero di lavoro ha delle modifiche che potrebbero essere messe in scena:
git diff-files --quiet
- Il codice di uscita è lo stesso di
git diff-index
( 0
== nessuna differenza; 1
== differenze).
Per verificare se la combinazione dell'indice e dei file tracciati nell'albero di lavoro presenta delle modifiche rispetto a HEAD
:
git diff-index --quiet HEAD --
- Questo è come una combinazione dei due precedenti. Una differenza principale è che riporterà comunque "nessuna differenza" se si dispone di una modifica graduale che si è "annullata" nella struttura di lavoro (tornando ai contenuti presenti
HEAD
). In questa stessa situazione, i due comandi separati restituirebbero entrambi rapporti di "differenze presenti".
Hai anche citato file non tracciati. Potresti significare "non tracciato e non firmato", oppure potresti semplicemente indicare "non tracciato" (compresi i file ignorati). In entrambi i casi, git ls-files
è lo strumento per il lavoro:
Per "non tracciato" (includerà i file ignorati, se presenti):
git ls-files --others
Per "non tracciato e non firmato":
git ls-files --exclude-standard --others
Il mio primo pensiero è quello di verificare se questi comandi hanno un output:
test -z "$(git ls-files --others)"
- Se esce con
0
allora non ci sono file non tracciati. Se esce con 1
allora ci sono file non tracciati.
Vi è una piccola possibilità che ciò traduca le uscite anomale da git ls-files
in report "nessun file non tracciato" (entrambi comportano uscite diverse da zero del comando sopra). Una versione un po 'più robusta potrebbe apparire così:
u="$(git ls-files --others)" && test -z "$u"
- L'idea è la stessa del comando precedente, ma consente la
git ls-files
propagazione di errori imprevisti . In questo caso un'uscita diversa da zero potrebbe significare "ci sono file non tracciati" oppure potrebbe essersi verificato un errore. Se si desidera invece i risultati di "errore" in combinazione con il risultato "nessun file non monitorato", utilizzare test -n "$u"
(dove exit 0
indica "alcuni file non monitorati" e un valore diverso da zero significa errore o "nessun file non monitorato").
Un'altra idea è quella di utilizzare --error-unmatch
per causare un'uscita diversa da zero quando non ci sono file non tracciati. Ciò comporta anche il rischio di confondere "nessun file non monitorato" (uscita 1
) con "si è verificato un errore" (uscita diversa da zero, ma probabilmente 128
). Ma verificare i codici di uscita 0
vs. 1
vs. diversi da zero è probabilmente abbastanza robusto:
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
Uno qualsiasi degli git ls-files
esempi sopra può prendere --exclude-standard
se si desidera prendere in considerazione solo file non tracciati e non firmati.