Software-Entwicklung mit Git: Lokale Git-Hooks (Teil 3)

Git-Hooks sind Skripte, mit denen sich vielerlei Funktionen von Git beeinflussen lassen. Dabei gibt es serverseitige und lokale, Repository-gebundene Skripte. Letzteren widmet sich diese Artikelreihe (Teil 1, Teil 2). In diesem dritten Beitrag diskutieren wir nun die Hooks post-checkout und pre-rebase.

Nach dem Checkout

Der post-checkout-Hook gleicht dem post-commit-Hook in vielen Belangen, doch er wird aufgerufen, wann immer wir eine Referenz mit git checkout auschecken. Das ist hilfreich, um unser Arbeitsverzeichnis von generierten Dateien zu bereinigen, die sonst Verwirrung stiften würden.

Dieser Hook akzeptiert drei Parameter, und sein Exit-Status hat keine Auswirkungen auf den Befehl git checkout:

  1. Die Referenz des vorangehenden HEAD.
  2. Die Referenz des neuen HEAD.
  3. Ein Hinweis, der uns sagt, ob ein Branch oder eine Datei ausgecheckt wurde (1 oder 0).

Python-Entwickler haben regelmäßig das Problem, dass generierte .pyc-Dateien dableiben, nachdem sie zwischen Branches gewechselt sind. Manchmal nutzt der Interpreter diese .pyc statt der .py-Quelldatei. Um Verwirrung zu vermeiden, können wir mithilfe des folgenden post-checkout-Skripts alle .pyc-Dateien löschen, wann immer wir einen neuen Branch auschecken.

#!/usr/bin/env python

import sys, os, re
from subprocess import check_output

# Collect the parameters
previous_head = sys.argv[1]
new_head = sys.argv[2]
is_branch_checkout = sys.argv[3]

if is_branch_checkout == "0":
    print "post-checkout: This is a file checkout. Nothing to do."
    sys.exit(0)

print "post-checkout: Deleting all '.pyc' files in working directory"
for root, dirs, files in os.walk('.'):
    for filename in files:
        ext = os.path.splitext(filename)[1]
        if ext == '.pyc':
            os.unlink(os.path.join(root, filename))

Das aktuelle Arbeitsverzeichnis für Hook-Skripte ist immer auf das Root des Repositorys gesetzt. Der Aufruf os.walk('.') iteriert somit durch jede Datei im Repository. Dann prüfen wir ihre Erweiterung und löschen sie, wenn es sich um eine .pyc-Datei handelt.

Wir können den post-checkout-Hook auch nutzen, um unser Arbeitsverzeichnis darauf basierend anzupassen, welchen Branch wir ausgecheckt haben. Beispielsweise könnten wir einen Branch namens plugins nutzen, um alle unsere Plugins außerhalb der Kern-Codebasis zu speichern. Wenn diese Plugins viele Binaries erfordern, die andere Branches nicht benötigen, können wir sie selektiv immer nur dann bauen, wenn wir im plugins-Branch arbeiten.

Vor dem Rebasing

Der pre-repase-Hook wird aufgerufen, bevor git rebase irgendetwas ändert. Damit ist er eine gute Möglichkeit sicherzustellen, dass nichts Verheerendes geschieht.

Dieser Hook nimmt zwei Parameter: den Upstream-Branch, von dem geforkt wurde, und den Branch fürs Rebasing. Der zweite Parameter ist leer, wenn wir den aktuellen Branch rebasen. Ein Exit mit Nicht-Null-Status bricht das Rebasing ab.

Wir wir für unser Repository das Rebasing beispielsweise komplett unterbinden möchten, könnten wir das folgende pre-rebase-Skript nutzen:

#!/bin/sh

# Disallow all rebasing
echo "pre-rebase: Rebasing is dangerous. Don't do it."
exit 1

Nun sehen wir bei jeder Ausführung von git rebase diese Meldung:

pre-rebase: Rebasing is dangerous. Don't do it.
The pre-rebase hook refused to rebase.

Für ein Beispiel, das mehr in die Tiefe geht, sollten wir mal einen Blick in das native Skript pre-rebase.sample werfen. Dieses geht mit dem Unterbinden von Rebasing etwas intelligenter um. Es prüft, ob der Topic-Branch, den wir rebasen wollen, bereits in den next-Branch gemergt wurde (in diesem Fall der Branch der Haupt-Codelinie). Falls dem so ist, würden wir wahrscheinlich in Schwierigkeiten kommen, wenn wir trotzdem ein Rebasing durchführen, und das Skript verwirft den Rebase.

Damit haben wir die sechs hilfreichsten lokalen Git-Hooks besprochen. In einer kommenden Artikelreihe sehen wir uns dann serverseitige Skripte an.

Git und Bitbucket Server effektiv nutzen? Wir sind Ihr Partner!

Kennen Sie Bitbucket Server (vormals Stash), Atlassians Git-Repository-Managementsystem? Bitbucket Server bietet eine zentrale Lösung zum Management des gesamten distributierten Codes: Hier kommen alle Git-Repositories im Unternehmen zusammen, hier finden Entwickler immer die letzte offizielle Version eines Projekts, hier können Projektverantwortliche Berechtigungen kontrollieren, um sicherzustellen, dass die richtigen Nutzer Zugriff auf den richtigen Code haben. Möchten Sie mehr erfahren? Wir sind offizieller Vertriebspartner von Atlassian und einer der größten Atlassian Experts Partner weltweit. Gerne unterstützen wir Sie bei der Evaluierung, Lizenzierung und Adaption von Bitbucket Server.

Übrigens: //SEIBERT/MEDIA bietet auch professionelle Grundlagen- und Aufbau-Workshops zu Git und Bitbucket Server an. Sie möchten, dass wir Ihren gesamten Software-Entwicklungsprozess mit Ihnen neu aufsetzen oder modernisieren? Dann testen Sie kostenfrei und unverbindlich unseren CoderStack.

Weiterführende Infos

99 Argumente für Bitbucket Server (Stash) als Git-Repository-Manager
Branch-basierte Git-Workflows adaptieren
Echte Integration: Das Zusammenspiel von JIRA, Stash und Bamboo
Interview: Die Vorteile von Git in der Software-Entwicklung und die Möglichkeiten von Bitbucket Server (Stash)
So funktioniert die Lizenzierung von Atlassian-Produkten