2012-12-05 11 views
11

Sto cercando scrivere uno script di shell che fa la seguente:Script di shell per controllare git per le modifiche e quindi eseguire il loop dei file modificati?

  1. Controlli repository git a distanza per eventuali modifiche per tirare.
  2. Se sono presenti modifiche nel repository git remoto, effettuare tali modifiche.
  3. Loop attraverso i file nuovi o modificati.

Attraverso la mia ricerca ho trovato alcuni dei comandi necessari per fare queste cose, ma non sono stato in grado di farli lavorare insieme in uno script di shell.

Ecco uno script con alcuni dei comandi che ho:

#!/bin/sh 

#Check if there are any changed files 
git --git-dir="/dir/.git" fetch origin 

if git --git-dir="/dir/.git" log HEAD..origin/master --oneline 
then 

#Output the modified files from the last pull 
     git --git-dir="/dir/.git" diff --name-status ORIG_HEAD.. 

fi 

Le cose che non sono stato in grado di ottenere a lavorare con i comandi di questo script sono:

  1. Il se la dichiarazione per verificare se ci sono cambiamenti o non sempre è vera. Ho provato se le istruzioni con altri comandi git e sono anche sempre vere. Sembra che git non funzioni come i normali comandi di shell in cui ottieni una risposta 0 o 1. Come posso ottenere un comando git come questo o altri comandi git per restituire le risposte corrette in un'istruzione if?
  2. Come posso assegnare le variabili in uscita dal comando per vedere i file modificati in una matrice in modo che possa scorrere attraverso di essi utilizzando un for?

Se i comandi del mio script non funzionano davvero in questo caso, qual è il modo migliore per farlo?

Modifica: Scusa dovrei essere più chiaro quando eseguo il loop dei file modificati Ho bisogno di estrarre le modifiche dal repository remoto prima di scorrere i file in modo tale che quando lavoro con questi file ho le ultime modifiche.

risposta

9

Per la vostra prima domanda, è possibile utilizzare git diff --quiet (o git diff --exit-code, ma in genere quando lo si usa per il suo codice di uscita che si desidera non stampare l'uscita in ogni caso, e git diff --quiet implica --exit-code) per determinare se sono state apportate modifiche. Questo ti darà un valore 1 se ci sono cambiamenti e uno 0 se non ci sono.Quindi, se si vuole avere il codice che verrà eseguito solo se ci sono cambiamenti:

if ! git --git-dir="/dir/.git" diff --quiet 
then 
    # do stuff... 
fi 

Per la seconda domanda, mi consiglia un ciclo while read ... di leggere le linee da git diff-tree:

git --git-dir="/dir/.git" diff-tree ORIG_HEAD.. | \ 
    while read srcmode dstmode srcsha dstsha status srcfile dstfile 
    do 
     # do something with $srcfile and $dstfile 
    done 

Si noti che $srcmode avrà un ulteriore : all'inizio e $dstfile avrà un valore solo se il file è stato rinominato. Se non vuoi preoccuparti della rinomina, passa a --no-renames e invece di vedere i nomi dei nomi vedrai solo le aggiunte e le eliminazioni.

3

Hai ragione, git normalmente non esce con stato diverso da zero se non si verifica un errore. Il modo più semplice che ho trovato per rilevare modifiche non è qualcosa di simile:

let changes=0 
while read status filename; do 
    let changes=1 
    # do something with this filename/status 
done < <(git status --porcelain) 
if ((! changes)); then 
    echo "No changes." 
fi 

In generale, se avete intenzione di provare a guidare git dal codice, si dovrebbe usare --porcelain su quelle subcommands che la sostengono, per farlo agire in un modo più favorevole all'automazione. Potresti anche voler indagare sulle librerie di altre lingue per interagire con git senza costruire i tuoi comandi di shell; per esempio, in Ruby c'è grit.

Ora, nel tuo caso, vuoi rilevare cosa è cambiato a monte. Per questo, probabilmente si desidera utilizzare git diff-tree. logica simile al precedente:

git fetch # not pull 
while read filename; do 
    # do something with filename 
done < <(git diff-tree --name-only origin/master master) # or whatever branch you're using 
+0

Ciao Mark. Grazie per la tua risposta. Ho provato a eseguire il tuo script ma sto ricevendo il seguente errore: errore di sintassi vicino a un token imprevisto '<'' done <<(git status --porcelain)'. Qualche idea su quale dovrebbe essere la sintassi corretta? – startupsmith

+0

Sei sicuro di stare usando bash? –

+0

Ciao Mark. Hai ragione, non stavo usando bash ... funziona ora. Devo approfondire ulteriormente questo aspetto, ma da quello che posso vedere questo script eseguirà il ciclo dei file modificati prima che siano stati estratti dal repository remoto? – startupsmith

1

È possibile utilizzare semplicemente git diff --name-only per elencare tutti i nomi file dei file modificati.

Ad esempio, ecco un semplice script per elencare tutti i file PHP modificati e testare la sintassi.

#!/bin/bash 
files=`git diff --name-only | grep -E '.php$' ` 
for file in $files; do 
    php -l $file 
done 
Problemi correlati