Git
Chapters ▾ 2nd Edition

8.3 Εξατομίκευση του Git - Τα άγκιστρα του Git

Τα άγκιστρα του Git

Όπως πολλά άλλα συστήματα ελέγχου εκδόσεων, το Git έχει έναν τρόπο να τρέξει εξατομικευμένα script όταν συμβαίνουν ορισμένες σημαντικές ενέργειες. Υπάρχουν δύο κατηγορίες αγκίστρων: από την πλευρά του πελάτη και από την πλευρά του διακομιστή. Τα άγκιστρα από την πλευρά του πελάτη ενεργοποιούνται από λειτουργίες όπως η υποβολή και η συγχώνευση, ενώ τα άγκιστρα από την πλευρά του διακομιστή εκτελούνται σε λειτουργίες δικτύου όπως λήψη ωθημένων υποβολών. Μπορούμε να χρησιμοποιήσουμε αυτά τα άγκιστρα για διάφορους λόγους.

Εγκατάσταση ενός αγκίστρου

Όλα τα άγκιστρα αποθηκεύονται όλα στον υποκατάλογο hooks του καταλόγου Git. Στα περισσότερα έργα, αυτός είναι ο .git/hooks. Όταν αρχικοποιούμε ένα νέο αποθετήριο με την git init, το Git επικοίζει τον κατάλογο των άγκιστρων με ένα σωρό script, πολλά από τα οποία είναι χρήσιμα από μόνα τους· αλλά επίσης καταγράφουν τις τιμές εισόδου για κάθε script. Όλα τα παραδείγματα είναι γραμμένα ως script κελύφους, πασπαλισμένα με λίγη Perl, αλλά οποιοδήποτε κατάλληλα ονομάσμένο εκτελέσιμο script θα λειτουργήσει μια χαρά —μπορούμε να τα γράψουμε σε Ruby ή Python ή τι θέλουμε. Εάν θέλουμε να χρησιμοποιήσουμε πακέτα script αγκίστρων, θα πρέπει να τα μετονομάσουμε· τα ονόματα όλων των αρχείων πρέπει να τελειώνουν σε το .sample.

Για να ενεργοποιήσουμε μια script αγκίστρου, τοποθετούμε ένα αρχείο στον υποκατάλογο hooks του καταλόγου Git που έχει κατάλληλο όνομα και είναι εκτελέσιμος. Από εκείνο το σημείο και μετά, θα πρέπει να καλείται. Θα καλύψουμε τα περισσότερα από τα κύρια ονόματα αρχείων script εδώ.

Άγκιστρα από την πλευρά του πελάτη

Υπάρχουν πολλά άγκιστρα από την πλευρά του πελάτη. Αυτή η ενότητα τους διαχωρίζει σε άγκιστρα ροής εργασιών υποβολής, script ροής εργασίας e-mail και τα υπόλοιπα.

Note

Είναι σημαντικό να σημειώσουμε ότι τα άγκιστρα από την πλευρά του πελάτη δεν αντιγράφονται όταν κλωνοποιούμε ένα αποθετήριο. Εάν η πρόθεσή μας με αυτά τα script είναι να επιβάλλουμε μια πολιτική, τότε αυτό πρέπει να το κάνουμς από την πλευρά του διακομιστή· βλ. παράδειγμα στην ενότητα Ένα παράδειγμα επιβολής πολιτικής από το Git.

Άγκιστρα που σχετίζονται με την υποβολή

Τα πρώτα τέσσερα άγκιστρα έχουν να κάνουν με τη διαδικασία υποβολής.

Το άγκιστρο pre-commit τρέχει πρώτο, προτού ακόμα πληκτρολογήσουμε ένα μήνυμα υποβολής. Χρησιμοποιείται για την επιθεώρηση του στιγμιότυπου που πρόκειται να υποβληθεί, για να δούμε εάν έχουμε ξεχάσει κάτι, για να βεβαιωθούμε ότι τρέχουν τα οι δοκιμές ή για να εξετάσουμε ό,τι χρειάζεται ώστε να επιθεωρήσουμε τον κώδικα. Η μη-μηδενική έξοδος από αυτό το άγκιστρο ακυρώνει την υποβολή, αν και μπορούμε να το παρακάμψουμε αυτήν τη συμπεριφορά με git commit --no-verify. Μπορούμε να κάνουμε διάφορα πράγματα όπως να ελέγξουμε το στυλ κώδικα (τρέξτε το lint ή κάτι αντίστοιχο), να ελέγξουμε για τελικά λευκά κενά (το προεπιλεγμένο άγκιστρο κάνει ακριβώς αυτό) ή να ελέγξουμε αν υπάρχει κατάλληλη τεκμηρίωση για νέες μεθόδους.

Το άγκιστρο prepare-commit-msg εκτελείται πριν την εκκίνηση του επεξεργαστή μηνυμάτων υποβολών, αλλά αφού δημιουργηθεί το προεπιλεγμένο μήνυμα. Μας επιτρέπει να επεξεργαστούμε το προεπιλεγμένο μήνυμα πριν το δει ο συγγραφέας του. Αυτό το άκγιστρο παίρνει κάποιες παραμέτρους: τη διαδρομή προς το αρχείο που περιέχει το μήνυμα υποβολής μέχρι στιγμής, τον τύπο της υποβολής και το SHA-1 της υποβολής εφόσον πρόκειται για τροποποιημένη (amended) υποβολή. Αυτό το άγκιστρο γενικά δεν είναι χρήσιμο για κανονικές υποβολές. Αντίθετα, είναι καλό για υποβολές όπου το προεπιλεγμένο μήνυμα παράγεται αυτόματα, όπως μηνύματα με προτυποποιημένα μηνύματα υποβολών, υποβολές συγχώνευσης, συνθλιμμένες υποβολές και τροποποιημένες υποβολές. Μπορούμε να το χρησιμοποιήσουμε σε συνδυασμό με ένα πρότυπο υποβολής ώστε να εισαγάγουμε πληροφορίες προγραμματιστικά.

Το άγκιστρο commit-msg παίρνει μία παράμετρο, η οποία και πάλι είναι η διαδρομή προς ένα προσωρινό αρχείο που περιέχει το μήνυμα υποβολής που έχει γράψει ο προγραμματιστής. Εάν αυτό το script τερματίσει με μη-μηδενική κατάσταση, το Git απορρίπτει τη διαδικασία υποβολής. Επομένως μπορούμε να χρησιμοποιήσουμε αυτό το άγκιστρο για να επικυρώσουμε το μήνυμα του έργου μας ή το μήνυμα υποβολής πριν αφήσουμε την υποβολή να περάσει. Στην τελευταία ενότητα αυτού του κεφαλαίου, θα δείξουμε τη χρήση αυτού του αγκίστρου για να ελέγξουμε ότι το μήνυμά υποβολής μας είναι συμβατό με ένα απαιτούμενο υπόδειγμα.

Το άγκιστρο post-commit τρέχει αφού ολοκληρωθεί η διαδικασία υποβολής. Δεν παίρνει καμία παράμετρο, αλλά μπορούμε να πάρουμε εύκολα την τελευταία υποβολή τρέχοντας git log -1 HEAD. Γενικά, αυτό το script χρησιμοποιείται για ειδοποίηση ή κάτι παρόμοιο.

Άγκιστρα ροής εργασίας e-mail

Μπορούμε να ορίσουμε τρία άγκιστρα από την πλευρά του πελάτη για μια ροή εργασίας που βασίζεται στο ηλεκτρονικό ταχυδρομείο. Όλα καλούνται από την εντολή git am, οπότε αν δεν χρησιμοποιούμε αυτήν την εντολή στη ροή εργασίας μας, μπορούμε να μεταβούμε με ασφάλεια στην επόμενη ενότητα. Αν παίρνουμε επιθέματα μέσω e-mail που προετοιμάζονται από την git format-patch, τότε μερικά από αυτά μπορεί να μας βοηθήσουν.

Το πρώτο άγκιστρο που τρέχει είναι το applypatch-msg. Χρειάζεται μόνο μία παράμετρο εισόδου: το όνομα του προσωρινού αρχείου που περιέχει το προτεινόμενο μήνυμα υποβολής. Το Git ακυρώνει το επίθεμα εάν το script αυτό τερματίζει με μη-μηδένική κατάσταση. Αυτό μπορούμε να το χρησιμοποιήσουμε για να βεβαιωθούμε ότι ένα μήνυμα υποβολής είναι μορφοποιημένο σωστά ή για να κανονικόποιήσουμε το μήνυμα θέτοντας το script να το επεξεργαστεί επί τόπου.

Το επόμενο άγκιστρο που θα τρέξει κατά την εφαρμογή των επιθεμάτων μέσω της git am είναι το pre-applypatch. Το όνομά του προκαλεί κάποια σύγχυση, αφού εκτελείται πριν γίνει οποιαδήποτε υποβολή, αλλά μετά την εφαρμογή του επιθέματος, έτσι μπορούμε να το χρησιμοποιούμε για να επιθεωρούμε κάποιο στιγμιότυπο πριν τη διεξαγωγή της υποβολής. Με αυτό το script μπορούμε να εκτελέσουμε τεστ ή να ελέγξουμε με κάποιον άλλον τρόπο το δέντρο εργασίας. Εάν κάτι λείπει ή τα τεστ αποτύχουν, το script τερματίζει με μη-μηδενική έξοδο και η git am τερματίζει χωρίς να υποβάλει το επίθεμα.

Το τελευταίο άγκιστρο που τρέχει κατά τη διάρκεια μιας λειτουργίας git am είναι το post-applypatch, το οποίο τρέχει μετά την πραγματοποίηση της υποβολής. Μπορούμε να το χρησιμοποιήσουμε για να ειδοποιήσουμε μια ομάδα ή τον συντάκτη του επιθέματος που έλξαμε ότι πράγματι τον έλξαμε. Δεν μπορούμε να σταματήσουμε τη διαδικασία εφαρμογής του επιθέματος με αυτό το script.

Άλλα άγκιστρα πελατών

Το άγκιστρο pre-rebase εκτελείται πριν γίνει οποιαδήποτε αλλαγή βάσης και μπορεί να σταματήσει τη διαδικασία αν τερματίσει με μη-μηδενική κατάσταση. Μπορούμε να χρησιμοποιήσουμε αυτό το άγκιστρο για να απαγορεύσουμε την αλλαγή βάσης υποβολών που έχουν ήδη ωθηθεί. Το παράδειγμα του αγκίστρου pre-rebase που εγκαθιστά το Git επιτελεί ακριβώς αυτό, αν και κάνει κάποιες υποθέσεις που μπορεί να μην ταιριάζουν με τη ροή εργασίας μας.

Το άγκιστρο post-rewrite εκτελείται από εντολές που αντικαθιστούν υποβολές, όπως οι git commit -amend και git rebase (αλλά όχι η git filter-branch). Η μόνη παράμετρος εισόδου του είναι ποια εντολή ξεκίνησε την επανεγγραφή και λαμβάνει μια λίστα επανεγγραφών στο stdin. Αυτό το άγκιστρο έχει πολλές κοινές χρήσεις με τα άγκιστρα post-checkout και post-merge.

Αφού μία git checkout τερματίσει με επιτυχία, το άγκιστρο τρέχει post-checkout· μπορούμε να το χρησιμοποιήσουμε για να καθορίσουμε σωστά τον κατάλογο εργασίας μας για το περιβάλλον του έργου μας. Αυτό μπορεί να σημαίνει τη μετακίνηση μεγάλων δυαδικών αρχείων τα οποία δεν θέλουμε να υπόκεινται σε έλεγχο εκδόσεων, την αυτόματη δημιουργία τεκμηρίωσης ή κάτι παρόμοιο.

Το άγκιστρο post-merge τρέχει μετά από μια επιτυχημένη εντολή merge. Μπορούμε να το χρησιμοποιήσουμε για να επαναφέρουμε στο δέντρο εργασίας δεδομένα που δεν μπορεί να παρακολουθήσει το Git, όπως τα δεδομένα δικαιωμάτων (permissions). Αυτό το άγκιστρο μπορεί επίσης να επικυρώσει την παρουσία αρχείων που δεν υπόκεινται στον έλεγχο του Git, τα οποία ενδεχομένως θέλουμε να αντιγραφούν όταν αλλάζει το δέντρο εργασίας.

Το άγκιστρο pre-push εκτελείται κατά τη διάρκεια της git push, αφού έχουν ενημερωθεί τα απομακρυσμένα refs, αλλά πριν μεταφερθεί ο,τιδήποτε. Λαμβάνει το όνομα και τη θέση του απομακρυσμένου αποθετηρίου ως ορίσματα καθώς και μια λίστα με refs που θα ενημερωθούν μέσω της stdin. Μπορούμε να το χρησιμοποιήσουμε για να επικυρώσουμε ένα σύνολο ενημερώσεων refs πριν συμβεί μια ώθηση (ένας μη-μηδενικός κωδικός τερματισμού θα ακυρώσει την ώθηση).

Το Git περιστασιακά συλλέγει τα σκουπίδια ως μέρος της κανονικής λειτουργίας του, τρέχοντας το git gc --auto. Το άγκιστρο pre-auto-gc χρησιμοποιείται ακριβώς πριν γίνει η συλλογή των απορριμμάτων και μπορεί να χρησιμοποιηθεί για να μας ειδοποιήσει ότι συμβαίνει ή για να ακυρώσει τη συλλογή αν τώρα δεν είναι η κατάλληλη στιγμή.

Άγκιστρα από την πλευρά του διακομιστή

Εκτός από τα άγκιστρα από την πλευράς του πελάτη, μπορούμε να χρησιμοποιήσουμε μερικά σημαντικά άγκιστρα από την πλευρά του διακομιστή ως διαχειριστές συστημάτων για την εφαρμογή σχεδόν κάθε είδους πολιτικής για το έργο μας. Αυτά τα script τρέχουν πριν και μετά τις ωθήσεις στον διακομιστή. Τα άγκιστρα που τρέχουν πριν τις ωθήσεις είναι δυνατό να τερματίζουν με μη-μηδενικό κωδικό τερματισμού ανά πάσα στιγμή ώστε να απορρίψουν την ώθηση και εκτυπώνουν ένα μήνυμα σφάλματος στον πελάτη· μπορούμε να στήσουμε μια πολιτική ώθησης όσο περίπλοκη επιθυμούμε.

pre-receive

Το πρώτο script που τρέχει κατά τον χειρισμό μίας ώθησης από έναν πελάτη είναι το `pre-receive '. Παίρνει μια λίστα αναφορών που ωθούνται από το stdin· αν τερματίζει με μη-μηδενικό κωδικό, καμία από αυτές δεν γίνεται αποδεκτή. Μπορούμε να χρησιμοποιήσουμε αυτό το άγκιστρο για να κάνουμε διάφορα πράγματα όπως να βεβαιωθούμε ότι καμία από τις ενημερωμένες αναφορές δεν είναι ταχυπροώθηση ή να κάνουμε έλεγχο πρόσβασης για όλα τα refs και τα αρχεία που τροποποιούνται με την ώθηση.

update

Το script update είναι πολύ παρόμοιο με το script pre-receive', εκτός από το ότι εκτελείται μία φορά για κάθε κλάδο που προσπαθεί να ενημερώσει όποιος ωθεί. Εάν αυτός που ωθεί προσπαθεί να ωθήσει σε πολλαπλούς κλάδους, το `pre-receive τρέχει μόνο μία φορά ενώ το update εκτελείται μία φορά ανά κλάδο στον οποίο γίνεται ώθηση. Αντί της ανάγνωσης από το stdin, αυτό το script παίρνει τρεις παραμέτρους εισόδου: το όνομα της αναφοράς (κλάδου), το SHA-1 στο οποίο έδειχνε η αναφορά πριν από την ώθηση και το SHA-1 που προσπαθεί να ωθήσει ο χρήστης. Εάν το script update τερματίσει με μη-μηδένικό κωδικό, μόνο αυτή η συγκεκριμένη αναφορά απορρίπτεται· οι άλλες αναφορές θα ενημερωθούν (εφόσον δεν τερματίσει με μη-μηδενική έξοδο το αντίστοιχο script).

post-receive

Το άγκιστρο post-receive εκτελείται αφού ολοκληρωθεί η διαδικασία και μπορεί να χρησιμοποιηθεί για την ενημέρωση άλλων υπηρεσιών ή την ενημέρωση των χρηστών. Παίρνει τα ίδια δεδομένα στο stdin με το άγκιστρο pre-receive. Παραδείγματα είναι η αποστολή e-mail σε μια ηλεκτρονική λίστα αλληλογραφίας, η πληροφόρηση διακομιστή συνεχούς ενσωμάτωσης ή η ενημέρωση ενός συστήματος παρακολούθησης εισιτηρίων —μπορούμε ακόμη να αναλύσουμε τα μηνύματα υποβολής για να δούμε εάν κάποια εισιτήρια πρέπει να ανοίξουν, να τροποποιηθούν ή να κλείσουν. Αυτό το script δεν μπορεί να σταματήσει τη διαδικασία ώθησης, αλλά ο πελάτης δεν αποσυνδέεται μέχρι να ολοκληρωθεί, οπότε πρέπει να προσέχουμε αν προσπαθούμε να κάνουμε ο,τιδήποτε μπορεί να χρειαστεί πολύ χρόνο.