Symbolische Verknüpfung zu einem Hook in Git

86

Ich habe meinen eigenen benutzerdefinierten Post-Merge-Hook geschrieben und jetzt meinem Hauptprojektordner ein "Hooks" -Verzeichnis hinzugefügt (da git keine Änderungen in .git / hooks verfolgt). Irgendwo habe ich gelesen, dass ich aus Hooks einen symbolischen Link erstellen kann in .git / hooks, damit ich die Datei nicht jedes Mal von einem Ordner in den anderen kopieren muss, wenn jemand sie ändert, also habe ich versucht:

ln -s -f hooks/post-merge .git/hooks/post-merge

Aber es scheint nicht zu funktionieren, irgendwelche Ideen warum? "ln hooks / post-merge .git / hooks / post-merge" funktioniert gut, aber das Erstellen eines harten Links ist dasselbe wie das Kopieren, denke ich ....

Mateusz Dymczyk
quelle
22
Weil der Symlink relativ zu seiner Position aufgelöst wird. Ein Symlink in .git/hooks/diesem Punkt hooks/post-mergewird aufgelöst .git/hooks/hooks/post-merge, der nicht vorhanden ist. Du willst ln -s -f ../../hooks/post-merge .git/hooks/post-merge. Oder machen Sie Ihr Leben leichter : ln -s -f ../hooks .git/hooks. Dein Problem hat nichts mit Git zu tun.
Aristoteles Pagaltzis
Korrigieren Sie mich, wenn ich falsch liege, aber ein Symlink muss noch pro Workstation eingerichtet werden. Das einzige, was dadurch gespeichert wird, ist das manuelle Kopieren oder das Schreiben eines anderen Befehls, in den die verfolgte Hook-Datei kopiert wird .git/hooks.
adi518

Antworten:

161

Sie haben gerade einen falschen Pfad verwendet, es sollte sein:

ln -s -f ../../hooks/post-merge .git/hooks/post-merge
Michal Čihař
quelle
10
Ich verstehe nicht, warum ich zwei Verzeichnisse aufrufen muss, um eine Ressource zu verknüpfen, die sich in dem Ordner befindet, in dem ich mich befunden habe cd. Sollte es nicht einfach so sein ln -s ./hooks/?
Droogans
45
Dies. Wenn git den Symlink auswertet, wird es anscheinend .git/hooksals Arbeitsverzeichnis verwendet, daher sollten relative Pfade relativ zu diesem Verzeichnis sein. Dies ist selbsterklärend , wenn Sie zum ersten Mal cdin .git/hooksvor dem symbolischen Link und Figur aus dem relativen Pfad von dort zu machen.
Eliot
12
@Eliot Weder die Erstellung noch die Auflösung von Symlinks wird vom Arbeitsverzeichnis beeinflusst. Was auch immer Sie geben, lnwird als Ziel gespeichert und relativ zum Standort des Links aufgelöst.
Joó Ádám
2
@ JoóÁdám Du hast recht. Das Problem hierbei ist also, dass der ursprüngliche Befehl einen falschen relativen Pfad angibt. Noch cdin ing , .git/hooksbevor Sie den Link zu machen, helfen Ihnen den Befehl schreiben, da Sie dann auf den richtigen Pfad automatisch vervollständigen können.
Eliot
1
Das alles hat am Ende für mich funktioniert. Der einzige Unterschied ist, dass ich mich mit meinem eigenen verbinde prepare-commit-msg. Das Problem ist, wenn ich die Festschreibungsnachricht mit nano bearbeite und dann Ctl + X zum Abbrechen ausgibt, git git trotzdem ein Festschreiben abschließt, anstatt wie früher abzubrechen, bevor ich diese Änderung vorgenommen habe. Gibt es eine Möglichkeit, einen Nano-Exit durchzuführen, ohne dass dieses Commit abgeschlossen wird?
frakman1
14

Während Sie symbolische Links verwenden können, können Sie den Hooks-Ordner für Ihr Projekt in Ihren Git-Einstellungen auch ändern mit:

git config core.hooksPath hooks/

Dies ist standardmäßig lokal, damit Git-Hooks für Ihre anderen Projekte nicht ruiniert werden. Es funktioniert für alle Hooks in diesem Repository. Daher ist es besonders nützlich, wenn Sie mehr als einen Hook haben.

Wenn Sie bereits benutzerdefinierte Hooks haben .git/hooks/, die Sie nicht mit Ihrem Team teilen möchten, können Sie diese in Hooks / hinzufügen und ein hinzufügen, .gitignoredamit sie nicht geteilt werden.

Pierre.Sassoulas
quelle
Sehr schön! Ein praktischer Trick :) Scheint weitaus zukunftssicherer zu sein, als sie einzeln zu verknüpfen.
JKP
2

Vor dem Verknüpfen das Verzeichnis wechseln

cd /path/to/project-repo/.git/hooks
ln -s -f ../../hooks/post-merge ./post-merge
Jekis
quelle
Noch einfacher, nach dem cd:ln -s -f ../../hooks/post-merge
Jamesdlin
0

Die Pfadberechnung erfolgt relativ zum Symlink. Lassen Sie uns anhand eines Beispiels verstehen:

ln -s path/to/file symlink/file

Hier sollte der Pfad zur Datei tatsächlich der relative Pfad vom Symlink-Pfad sein.
Das System berechnet den Dateipfad tatsächlich wie folgt: symlink/path/path/to/file
Der obige Befehl sollte wie folgt umgeschrieben werden:

ln -s ../path/to/file symlink/path

Die Ordnerstruktur lautet:

/ code
------ symlink / file
------ path / to / file

Swayamraina
quelle
0

Anhand des Kommentars von Michael Cihar finden Sie hier ein Beispiel für ein Bash-Skript, das ich geschrieben habe, um diese Symlinks einfach zu erstellen. Dieses Skript befindet sich in git_hooks / dir, das sich im Projektstamm befindet. Mein .git / -Ordner befindet sich ebenfalls auf derselben Verzeichnisebene.

#!/usr/bin/env bash

pwd=$(pwd);

# Script is designed to be ran from git_hooks/ dir
if [[ "$pwd" == *"git_hooks"* ]]; then

  files=$(ls | grep -v -e '.*\.');

   while read -r file; do

     ln -s ../../git_hooks/$file ../.git/hooks/
     echo "Linked $file -> ../.git/hooks/$file"

   done <<< "$files";

else

  echo "";
  echo "ERROR: ";
  echo "You must be within the git_hooks/ dir to run this command";
  exit 1;

fi

Mein Skript muss aus dem tatsächlichen Verzeichnis git_hooks / ausgeführt werden. Sie können es ändern, um sich anders zu verhalten, wenn Sie möchten.

Dieses Skript verknüpft alle Dateien, denen keine Dateierweiterung im Verzeichnis git_hooks / zugeordnet ist. Ich habe eine README.txt in diesem Verzeichnis + dieses Skript (mit dem Namen symlink.sh). Alle tatsächlichen Git-Hooks heißen "Pre-Commit", "Pre-Push" usw., sodass sie miteinander verknüpft werden.

cchoe1
quelle
-1

warum nicht einfach cp ./hooks/* .git / hooks /

Das hat bei mir unter Mac OS funktioniert

Frazko
quelle
15
WeilI don't have to copy the file from one folder to the other every time someone changes
George Dimitriadis