Können Git-Hook-Skripte zusammen mit dem Repository verwaltet werden?

334

Wir möchten ein paar grundlegende Hook-Skripte erstellen, die wir alle gemeinsam nutzen können - zum Beispiel zum Vorformatieren von Commit-Nachrichten. Git hat Hook-Skripte dafür, die normalerweise unter gespeichert sind <project>/.git/hooks/. Diese Skripte werden jedoch nicht weitergegeben, wenn Benutzer einen Klon erstellen, und sie sind nicht versioniert.

Gibt es eine gute Möglichkeit, allen zu helfen, die richtigen Hook-Skripte zu erhalten? Kann ich diese Hook-Skripte einfach auf versionierte Skripte in meinem Repo verweisen lassen?

Pat Notz
quelle
5
Eine gute Frage. Ich wünschte nur, es gäbe eine bessere Antwort (ohne Beschwerden an @mipadi, ich wünschte nur, Git hätte eine Möglichkeit, dies automatischer zu tun - auch wenn nur eine Option zum Git-Klonen angegeben wurde.)
Lindes
Ich stimme zu, @lindes! Aber vielleicht diese gemeinsame Nutzung von Hooks absichtlich einschränken? Für Windows-Benutzer würde es wahrscheinlich chaotisch werden.
Kristianlm
@kristianlm: Es gibt viele Gründe, warum es manchmal chaotisch sein kann ... und auch manchmal, wenn es schön ist, es dort zu haben. Ich wünschte nur, es gäbe eine Option oder etwas, das die Haken kopieren würde. Ich denke, ich muss nur irgendwann den Git-Core-Code überprüfen und einen Patch erstellen. :) (Oder hoffe, dass jemand anderes es tut ... oder mit der Problemumgehung in Mipadis Antwort lebt , oder was auch immer.)
Lindes
pre-commitmacht dies für Pre-Commit-Hooks einfach. Beantwortet nicht die Frage des OP zur Verwaltung eines beliebigen Git-Hooks, aber Pre-Commit-Hooks werden wahrscheinlich am häufigsten für Zwecke der Codequalität verwendet.
Ericsoco

Antworten:

143

Theoretisch könnten hooksSie in Ihrem Projektverzeichnis ein Verzeichnis (oder einen beliebigen Namen) mit allen Skripten erstellen und diese dann mit einem Symlink verknüpfen .git/hooks. Natürlich müsste jede Person, die das Repo geklont hat, diese Symlinks einrichten (obwohl Sie wirklich ausgefallen sein und ein Bereitstellungsskript haben könnten, das der Kloner ausführen könnte, um sie halbautomatisch einzurichten).

Um den Symlink auf * nix zu erstellen, müssen Sie lediglich Folgendes tun:

root="$(pwd)"
ln -s "$root/hooks" "$root/.git/hooks"

Verwenden ln -sfSie diese Option, wenn Sie bereit sind, die Inhalte zu überschreiben.git/hooks

Mipadi
quelle
37
Dies war nicht trivial, daher füge
David T.
16
git Version 2.9 verfügt jetzt über eine Konfigurationsoption core.hooksPathzum Einrichten einer Datei außerhalb von .git, um eine Verknüpfung zum Hooks-Ordner herzustellen.
Aaron Rabinowitz
213

In Git 2.9 gibt die Konfigurationsoption core.hooksPathein benutzerdefiniertes Hooks-Verzeichnis an.

Verschieben Sie Ihre Hooks in ein hooksnachverfolgtes Verzeichnis in Ihrem Repository. Konfigurieren Sie dann jede Instanz des Repositorys so, dass hooksanstelle von $GIT_DIR/hooks:

git config core.hooksPath hooks

Im Allgemeinen kann der Pfad absolut oder relativ zu dem Verzeichnis sein, in dem die Hooks ausgeführt werden (normalerweise der Arbeitsbaumstamm; siehe Abschnitt BESCHREIBUNG von man githooks).

Max Shenfield
quelle
15
... und das Hooks-Verzeichnis, auf das verwiesen werden soll, kann ein separates Hooks-Repository sein;)
René Link
10
Wird dieser Konfigurationsparameter automatisch eingestellt, wenn Sie einen Git-Klon ausführen?
Ring
4
In der Regel können Git-Konfigurationsvariablen von dem zu klonenden Repository nicht festgelegt werden. Ich denke, dies soll die Ausführung von beliebigem Code verhindern. git config steuert die Ausführung von Code über Hooks, den Benutzernamen bei Festschreibungsnachrichten und andere wichtige Funktionen.
Max Shenfield
1
Was ist, wenn jemand im Team einen Git-Checkout in einer anderen Filiale durchführt? Sie müssen es in jeden Zweig aufnehmen ..
Jokerster
1
Das stimmt. Wenn Sie andererseits die Hooks in neueren Commits aktualisieren, erhalten geklonte Repos diese automatisch, wenn Sie an Zweigen arbeiten, die auf diesem Commit aufbauen. Beide Wege haben ihre Vor- und Nachteile.
fabb
15

Wenn Ihr Projekt ein JavaScript-Projekt ist und Sie npmals Paketmanager verwenden, können Sie Shared-Git-Hooks verwenden , um Githooks zu erzwingen npm install.

kilianc
quelle
5
Jetzt weiß ich, wem dieser Mist aufdringlich hinzugefügt wird .git/hooks.
Gavenkoa
Warnung - unterstützt Windows nicht (es sei denn, es wird als Administrator in Git Bash ausgeführt). Eine einfache Lösung besteht darin, "preinstall": "git config core.hooksPath hooks" als Skript in package.json hinzuzufügen. dh Wo Hooks ist ein Ordner, der Ihre Git-Skripte enthält.
Shane Gannon
8

Für Nodejs- Benutzer besteht eine einfache Lösung darin, package.json mit zu aktualisieren

{
  "name": "name",
  "version": "0.0.1",
  ......
  "scripts": {
    "preinstall": "git config core.hooksPath hooks", 

Die Vorinstallation wird vorher ausgeführt

npm installieren

und leitet git um, um nach Hooks im Verzeichnis. \ hooks (oder einem beliebigen Namen, den Sie wählen) zu suchen . Dieses Verzeichnis sollte . \. Git \ hooks in Bezug auf Dateinamen (abzüglich .sample) und Struktur imitieren.

Stellen Sie sich vor, Maven und andere Build-Tools entsprechen der Vorinstallation .

Es sollte auch plattformübergreifend funktionieren.

Wenn Sie weitere Informationen benötigen, besuchen Sie https://www.viget.com/articles/two-ways-to-share-git-hooks-with-your-team/

Shane Gannon
quelle
5

Wie wäre es mit Git-Hooks , die den .git/hooksAufruf in ein Skript im Projektverzeichnis weiterleiten githooks.

Es gibt auch viele Funktionen, mit denen Sie das Kopieren und den Symlink-Hook überall minimieren können.

Rohrkolben
quelle
5

Die meisten modernen Programmiersprachen oder besser gesagt ihre Build-Tools unterstützen Plugins zur Verwaltung von Git-Hooks. Das bedeutet, dass Sie nur Ihre package.json, pom.xml usw. konfigurieren müssen und jeder in Ihrem Team keine andere Wahl hat, als die Anforderungen zu erfüllen, es sei denn, er ändert die Build-Datei. Das Plugin fügt für Sie Inhalte zum .git-Verzeichnis hinzu.

Beispiele:

https://github.com/rudikershaw/git-build-hook

https://github.com/olukyrich/githook-maven-plugin

https://www.npmjs.com/package/git-hooks

Yuranos
quelle
Ich habe versucht, dies auf generische Weise zu erreichen, um es in meinen Projekten zu verwenden, also habe ich dieses Tool geschrieben: pypi.org/project/hooks4git
Lovato
3

Wir verwenden Visual Studio-Lösungen (und damit Projekte) mit Ereignissen vor und nach dem Build. Ich füge ein zusätzliches Projekt mit dem Namen 'GitHookDeployer' hinzu. Das Projekt ändert selbst eine Datei im Post-Build-Ereignis. Diese Datei soll in das Build-Verzeichnis kopiert werden. Daher wird das Projekt jedes Mal erstellt und nie übersprungen. Im Build-Ereignis wird außerdem sichergestellt, dass alle Git-Hooks vorhanden sind.

Beachten Sie, dass dies keine allgemeine Lösung ist, da einige Projekte natürlich nichts zu erstellen haben.

Mike de Klerk
quelle
1

Sie können Ihren Hooks-Ordner zu einem anderen Git-Repository machen und ihn als Submodul verknüpfen ... Ich denke, es lohnt sich nur, wenn Sie viele Mitglieder und Hooks haben, die regelmäßig geändert werden.

Neu machen
quelle
1

Sie können eine verwaltete Lösung für das Pre-Commit-Hook-Management wie Pre-Commit verwenden . Oder eine zentralisierte Lösung für serverseitige Git-Hooks wie Datree.io . Es hat eingebaute Richtlinien wie:

  1. Erkennen und verhindern Sie das Zusammenführen von Geheimnissen .
  2. Erzwingen Sie die richtige Git-Benutzerkonfiguration .
  3. Jira-Ticketintegration erzwingen - Geben Sie die Ticketnummer in der Pull-Anforderungsname / Commit-Nachricht an.

Es wird nicht alle Ihre Hooks ersetzen, aber es könnte Ihren Entwicklern bei den offensichtlichsten helfen, ohne dass die Konfiguration die Hooks auf jedem Entwicklercomputer / Repo installieren muss.

Haftungsausschluss: Ich bin einer der Gründer von Datrees

Shimon Tolts
quelle
1

Im Idealfall werden Hooks in Bash geschrieben, wenn Sie den Beispieldateien folgen. Sie können es jedoch in jeder verfügbaren Sprache schreiben und sicherstellen, dass es das Flag für ausführbare Dateien enthält.

Sie können also einen Python- oder Go-Code schreiben, um Ihre Ziele zu erreichen, und ihn unter dem Hooks-Ordner ablegen. Es wird funktionieren, aber es wird nicht zusammen mit dem Repository verwaltet.

Zwei Optionen

a) Multi-Skripte

Sie können Ihre Hooks in Ihrer Hilfe codieren und Hooks ein kleines Codefragment hinzufügen, um Ihr perfektes Skript wie folgt aufzurufen:

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/myprecommit.js

b) Einzelskript

Eine coolere Option besteht darin, nur ein Skript hinzuzufügen, um alle zu regieren, anstatt mehrere. Also erstellen Sie ein hooks / mysuperhook.go und richten jeden Haken, den Sie haben möchten, darauf.

$ cat .git/hooks/pre-commit
#!/bin/bash
../../hooks/mysuperhook.go $(basename $0)

Der Parameter gibt Ihrem Skript an, welcher Hook ausgelöst wurde, und Sie können ihn in Ihrem Code unterscheiden. Warum? Manchmal möchten Sie zum Beispiel die gleiche Prüfung für Commit und Push durchführen.

Und dann?

Dann möchten Sie vielleicht weitere Funktionen haben, wie zum Beispiel:

  • Lösen Sie den Hook manuell aus, um zu überprüfen, ob auch vor einem Commit oder Push alles in Ordnung ist. Wenn Sie nur Ihr Skript aufrufen (Option a oder b), reicht dies aus.
  • Lösen Sie die Hooks für CI aus, damit Sie nicht dieselben Überprüfungen für CI neu schreiben müssen. Sie rufen beispielsweise nur die Commit- und Push-Trigger auf. Das gleiche wie oben sollte es lösen.
  • Rufen Sie externe Tools wie einen Markdown-Validator oder einen YAML-Validator auf. Sie können Systemaufrufe tätigen und müssen STDOUT und STDERR verarbeiten.
  • Stellen Sie sicher, dass alle Entwickler eine einfache Möglichkeit haben, die Hooks zu installieren. Daher muss dem Repository ein nettes Skript hinzugefügt werden, um die Standard-Hooks durch die richtigen zu ersetzen
  • Lassen Sie einige globale Helfer, wie z. B. eine Überprüfung zum Blockieren von Commits zum Entwickeln und Beherrschen von Zweigen, diese nicht zu jedem Repository hinzufügen. Sie können es lösen, indem Sie ein anderes Repository mit globalen Skripten haben.

Kann das einfacher sein?

Ja, es gibt verschiedene Tools, mit denen Sie Git-Hooks verwalten können. Jeder von ihnen ist darauf zugeschnitten, das Problem aus einer anderen Perspektive anzugehen, und Sie müssen möglicherweise alle verstehen, um die für Sie oder Ihr Team am besten geeignete zu finden. GitHooks.com bietet viel über das Hooking und verschiedene Tools, die heute verfügbar sind.

Bis heute sind dort 21 Projekte mit unterschiedlichen Strategien zur Verwaltung von Git-Hooks aufgeführt. Einige tun dies nur für einen einzelnen Hook, andere für eine bestimmte Sprache und so weiter.

Eines dieser Tools, das von mir geschrieben und als OpenSource- Projekt kostenlos angeboten wird, heißt hooks4git . Es ist in Python geschrieben (weil es mir gefällt), aber die Idee ist, alle oben aufgeführten Elemente in einer einzigen Konfigurationsdatei namens .hooks4git.ini zu behandeln, die sich in Ihrem Repository befindet und jedes Skript aufrufen kann, das Sie aufrufen möchten, und zwar in jeder Sprache .

Die Verwendung von Git-Hooks ist absolut fantastisch, aber die Art und Weise, wie sie angeboten werden, bringt die Leute normalerweise nur davon ab.

Lovato
quelle
Ich hatte vor einiger Zeit eine sehr kürzere Version veröffentlicht, und wie mit den Moderatoren vereinbart, enthält dies eine Erklärung und einen kurzen Link zu einem Tool, das ich selbst geschrieben habe und das meiner Meinung nach anderen Entwicklern helfen könnte.
Lovato
1

Für Gradle-Benutzer

Ich fand diese Skripte sehr nützlich für Gradle-Projekte.

build.gradle

apply from: rootProject.file('gradle/install-git-hooks.gradle')

gradle / install-git-hooks.gradle

tasks.create(name: 'gitExecutableHooks') {
    doLast {
        Runtime.getRuntime().exec("chmod -R +x .git/hooks/");
    }
}
task installGitHooks(type: Copy) {
    from new File(rootProject.rootDir, 'pre-commit')
    into { new File(rootProject.rootDir, '.git/hooks') }
}
gitExecutableHooks.dependsOn installGitHooks
clean.dependsOn gitExecutableHooks

Pre-Commit

.... your pre commit scripts goes here
a3765910
quelle