Git Pre-Commit Hook: geänderte / hinzugefügte Dateien

Ich schreibe einen Pre-Commit-Haken. Ich möchte php -l gegen alle Dateien mit .php-Erweiterung ausführen. Aber ich stecke fest.

Ich muss eine Liste der neuen / geänderten Dateien abrufen, die bereitgestellt werden. Gelöschte Dateien sollten ausgeschlossen werden.

Ich habe versucht, git diff und git ls-files , aber ich denke, ich brauche hier eine Hand.

git diff --cached --name-status zeigt eine Zusammenfassung dessen an, was inszeniert ist, so dass entfernte Dateien einfach ausgeschlossen werden können, zB:

 M wt-status.c D wt-status.h 

Dies zeigt an, dass wt-status.c modifiziert wurde und wt-status.h im Staging-Bereich (Index) entfernt wurde. Um nur Dateien zu überprüfen, die nicht entfernt wurden:

 steve@arise:~/src/git $ git diff --cached --name-status | awk '$1 != "D" { print $2 }' wt-status.c wt-status.h 

Sie müssen durch zusätzliche Ringe springen, um sich mit Dateinamen mit Leerzeichen in though zu befassen (-z Option zu git diff und ein paar interessanteres Parsing)

Eine etwas bessere Art, die gleiche Liste zu erhalten, ist:

 git diff --cached --name-only --diff-filter=ACM 

Dies gibt die Liste der Dateien zurück, die überprüft werden müssen.

Aber das Ausführen von php -l auf Ihrer Arbeitskopie ist möglicherweise nicht das Richtige. Wenn Sie eine partielle Festschreibung durchführen, dh nur eine Teilmenge der Unterschiede zwischen Ihrem aktuellen Arbeitssatz und dem HEAD für das Festschreiben auswählen, wird der Test auf Ihrem Arbeitssatz ausgeführt, aber er bestätigt ein Festschreiben, das auf Ihrem nie existiert hat Scheibe.

Um es richtig zu machen, sollten Sie das gesamte gestufte Bild in einen temporären Bereich extrahieren und dort den Test durchführen.

 rm -rf $TEMPDIR mkdir -p $TEMPDIR git checkout-index --prefix=$TEMPDIR/ -af git diff --cached --name-only --diff-filter=ACM | xargs -n 1 -I '{}' \bin\echo TEMPDIR/'{}' | grep \\.php | xargs -n 1 php -l 

Siehe Erstellen eines besseren Vorab-Hooks für Git für eine andere Implementierung.

Hier ist, was ich für meine Perl-Checks verwende:

 git diff --cached --name-status | while read st file; do # skip deleted files if [ "$st" == 'D' ]; then continue; fi # do a check only on the perl files if [[ "$file" =~ "(.pm|.pl)$" ]] && ! perl -c "$file"; then echo "Perl syntax check failed for file: $file" exit 1 fi done 

Für PHP sieht es so aus:

 git diff --cached --name-status | while read st file; do # skip deleted files if [ "$st" == 'D' ]; then continue; fi # do a check only on the php files if [[ "$file" =~ ".php$" ]] && ! php -l "$file"; then echo "PHP syntax check failed for file: $file" exit 1 fi done 

Keine der Antworten hier unterstützt Dateinamen mit Leerzeichen. Der beste Weg dazu ist, das Flag -z in Kombination mit xargs -0 hinzuzufügen

 git diff --cached --name-only --diff-filter=ACM -z | xargs -0 ... 

Dies ist, was git in eingebauten Samples angibt (siehe .git / hooks / pre-commit.sample )

git diff –cached reicht nicht aus, wenn der Commit-Aufruf mit dem Flag -a angegeben wurde, und es gibt keine Möglichkeit festzustellen, ob dieses Flag in den Hook geworfen wurde. Es wäre hilfreich, wenn die Argumente für das Commit zur Verfügung stehen sollten.