Lien symbolique vers un hook dans git

86

J'ai écrit mon propre hook post-merge personnalisé, maintenant j'ai ajouté un répertoire "hooks" à mon dossier principal de projet (puisque git ne suit pas les changements dans .git / hooks), quelque part j'ai lu que je peux créer un lien symbolique à partir de hooks en .git / hooks pour ne pas avoir à copier le fichier d'un dossier à l'autre chaque fois que quelqu'un le modifie, alors j'ai essayé:

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

Mais cela ne semble pas fonctionner, des idées pourquoi? "ln hooks / post-merge .git / hooks / post-merge" fonctionne très bien mais créer un lien physique est le même que copier je suppose ...

Mateusz Dymczyk
la source
22
Parce que le lien symbolique est résolu par rapport à son emplacement. Un lien symbolique .git/hooks/qui pointe vers hooks/post-mergeest résolu .git/hooks/hooks/post-merge, ce qui n'existe pas. Tu veux ln -s -f ../../hooks/post-merge .git/hooks/post-merge. Ou vous rendre la vie plus facile: ln -s -f ../hooks .git/hooks. Votre problème n'a rien à voir avec git.
Aristotle Pagaltzis
1
stackoverflow.com/questions/3462955/… et stackoverflow.com/questions/427207/… (et stackoverflow.com/questions/3703159/… ) soulignent le fait que le lien symbolique peut fonctionner.
VonC le
Corrigez-moi si je me trompe, mais un lien symbolique doit toujours être configuré par poste de travail. La seule chose que cela enregistre, est de le copier manuellement ou d'écrire une autre commande qui copie le fichier hook suivi .git/hooks.
adi518

Réponses:

161

vous venez d'utiliser un mauvais chemin, cela devrait être:

ln -s -f ../../hooks/post-merge .git/hooks/post-merge
Michal Čihař
la source
10
Je ne comprends pas pourquoi j'ai besoin de remonter deux répertoires pour lier une ressource qui vit dans le dossier dans lequel je me trouve cd. Ne devrait-il pas être juste ln -s ./hooks/?
Droogans
45
Ce. Lorsque git évalue le lien symbolique, il le fait apparemment en utilisant .git/hookscomme répertoire de travail, donc les chemins relatifs doivent être relatifs à ce répertoire. Ceci est plus explicite si vous commencez cdpar .git/hookscréer le lien symbolique et déterminez le chemin relatif à partir de là.
Eliot
12
@Eliot ni la création ni la résolution des liens symboliques ne sont affectées par le répertoire de travail. Tout ce que vous donnez lnsera stocké en tant que cible et résolu par rapport à l'emplacement du lien.
Joó Ádám
2
@ JoóÁdám Vous avez raison. Le problème ici est donc que la commande d'origine spécifie un chemin relatif incorrect. Néanmoins, cdentrer .git/hooksavant de créer le lien vous aidera à écrire la commande, car vous pouvez ensuite effectuer une saisie semi-automatique vers le chemin correct.
Eliot
1
Tout cela a fonctionné pour moi à la fin. La seule différence est que je me connecte à la mienne prepare-commit-msg. Le problème est que si j'édite le message de validation en utilisant nano, puis Ctl + X pour abandonner, git termine quand même un commit au lieu d'abandonner comme avant de faire ce changement. Existe-t-il un moyen d'avoir la sortie nano sans provoquer la fin de cet engagement?
frakman1
15

Bien que vous puissiez utiliser des liens symboliques, vous pouvez également modifier le dossier hooks de votre projet dans vos paramètres git avec:

git config core.hooksPath hooks/

Ce qui est local par défaut pour ne pas ruiner les hooks git pour vos autres projets. Cela fonctionne pour tous les hooks de ce référentiel, c'est donc particulièrement utile si vous avez plus d'un hook.

Si vous avez déjà des hooks personnalisés .git/hooks/que vous ne souhaitez pas partager avec votre équipe, vous pouvez les ajouter dans des hooks / et ajouter un .gitignoreafin qu'ils ne soient pas partagés.

Pierre Assoulas
la source
Très agréable! Une astuce pratique :) Cela semble bien plus à l'épreuve du temps que de les relier un par un.
jkp
2

Changer de répertoire avant de lier

cd /path/to/project-repo/.git/hooks
ln -s -f ../../hooks/post-merge ./post-merge
Jekis
la source
Encore plus simple, après le cd:ln -s -f ../../hooks/post-merge
jamesdlin
0

Le calcul du chemin est effectué par rapport au lien symbolique. Comprenons à l'aide d'un exemple,

ln -s path/to/file symlink/file

Ici, le chemin vers le fichier doit en fait être le chemin relatif du chemin du lien symbolique.
Le système calcule en fait le chemin du fichier comme symlink/path/path/to/file
La commande ci-dessus doit être réécrite comme

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

La structure du dossier étant,

/ code
------ lien symbolique / fichier
------ chemin / vers / fichier

swayamraina
la source
0

En utilisant le commentaire de Michael Cihar, voici un exemple de script bash que j'ai écrit pour créer simplement ces liens symboliques. Ce script se trouve dans git_hooks / dir qui se trouve à la racine du projet. Mon dossier .git / est également dans le même niveau de répertoire.

#!/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

Mon script doit être exécuté à partir du répertoire git_hooks /. Vous pouvez le modifier pour qu'il se comporte différemment, si vous le souhaitez.

Ce script créera un lien symbolique tout fichier qui n'est pas suffixé avec une extension de fichier dans le répertoire git_hooks /. J'ai un README.txt dans ce répertoire + ce script (nommé symlink.sh). Tous les hooks git réels sont nommés 'pre-commit', 'pre-push', etc. donc ils seront liés par un lien symbolique.

cchoe1
la source
-1

pourquoi pas simplement cp ./hooks/* .git / hooks /

cela a fonctionné pour moi sous Mac OS

Frazko
la source
15
Parce queI don't have to copy the file from one folder to the other every time someone changes
George Dimitriadis