Enlace simbólico a un gancho en git

86

Escribí mi propio gancho posterior a la fusión personalizado, ahora agregué un directorio "hooks" a la carpeta principal de mi proyecto (ya que git no rastrea los cambios en .git / hooks), en algún lugar leí que puedo hacer un enlace simbólico desde hooks a .git / hooks para no tener que copiar el archivo de una carpeta a otra cada vez que alguien lo cambia, así que intenté:

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

Pero no parece funcionar, ¿alguna idea de por qué? "ln hooks / post-merge .git / hooks / post-merge" funciona bien, pero hacer un enlace duro es lo mismo que copiar, supongo ...

Mateusz Dymczyk
fuente
22
Porque el enlace simbólico se resuelve en relación con su ubicación. Se resuelve un enlace simbólico .git/hooks/que apunta hooks/post-mergea .git/hooks/hooks/post-merge, que no existe. Quieres ln -s -f ../../hooks/post-merge .git/hooks/post-merge. O hacer su vida más fácil: ln -s -f ../hooks .git/hooks. Tu problema no tiene nada que ver con git.
Aristóteles Pagaltzis
1
stackoverflow.com/questions/3462955/… y stackoverflow.com/questions/427207/… (y stackoverflow.com/questions/3703159/… ) señalan el hecho de que el enlace simbólico puede funcionar.
VonC
Corríjame si me equivoco, pero aún se debe configurar un enlace simbólico por estación de trabajo. Lo único que esto guarda es copiarlo manualmente o escribir otro comando que copie el archivo de gancho rastreado en .git/hooks.
adi518

Respuestas:

161

acabas de utilizar un camino incorrecto, debería ser:

ln -s -f ../../hooks/post-merge .git/hooks/post-merge
Michal Čihař
fuente
10
No entiendo por qué necesito subir dos directorios para vincular un recurso que se encuentra en la carpeta en la que he cdentrado. ¿No debería ser así ln -s ./hooks/?
Droogans
45
Esta. Cuando git está evaluando el enlace simbólico, aparentemente lo hace usando .git/hookscomo su directorio de trabajo, por lo que las rutas relativas deben ser relativas a ese directorio. Esto se explica más por sí mismo si primero cdingresa .git/hooksantes de hacer el enlace simbólico y averigua la ruta relativa desde allí.
Eliot
12
@Eliot ni la creación ni la resolución de enlaces simbólicos se ven afectadas por el directorio de trabajo. Todo lo que dé lnse almacenará como destino y se resolverá en relación con la ubicación del enlace.
Joó Ádám
2
@ JoóÁdám Tienes razón. Entonces, el problema aquí es que el comando original especifica una ruta relativa incorrecta. Aún así, cdingresar .git/hooksantes de hacer el enlace lo ayudará a escribir el comando, ya que luego puede autocompletar en la ruta correcta.
Eliot
1
Todo esto funcionó para mí al final. La única diferencia es que me estoy vinculando al mío prepare-commit-msg. El problema es que si estoy editando el mensaje de confirmación usando nano, luego Ctl + X para abortar, git aún completa una confirmación de todos modos en lugar de abortar como solía hacer antes de hacer este cambio. ¿Hay alguna manera de tener una salida nano sin que se complete este compromiso?
frakman1
15

Si bien puede usar enlaces simbólicos, también puede cambiar la carpeta de ganchos para su proyecto en su configuración de git con:

git config core.hooksPath hooks/

Que es local de forma predeterminada, por lo que no arruinará los ganchos de git para sus otros proyectos. Funciona para todos los enganches de este repositorio, por lo que es especialmente útil si tiene más de un gancho.

Si ya tiene ganchos personalizados .git/hooks/que no desea compartir con su equipo, puede agregarlos en ganchos / y agregar un .gitignorepara que no se compartan.

Pierre.Sassoulas
fuente
¡Muy agradable! Un truco útil :) Parece mucho más preparado para el futuro que vincularlos uno a uno.
jkp
2

Cambiar de directorio antes de vincular

cd /path/to/project-repo/.git/hooks
ln -s -f ../../hooks/post-merge ./post-merge
Jekis
fuente
Aún más simple, después del cd:ln -s -f ../../hooks/post-merge
jamesdlin
0

El cálculo de la ruta se realiza en relación con el enlace simbólico. Entendamos usando un ejemplo,

ln -s path/to/file symlink/file

Aquí, la ruta al archivo debería ser la ruta relativa desde la ruta del enlace simbólico.
El sistema realmente calcula la ruta del archivo como symlink/path/path/to/file
El comando anterior debe reescribirse como

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

La estructura de la carpeta es,

/ código
------ enlace simbólico / archivo
------ ruta / a / archivo

swayamraina
fuente
0

Utilizando el comentario de Michael Cihar, aquí hay un ejemplo de un script bash que escribí para crear simplemente estos enlaces simbólicos. Este script se encuentra en git_hooks / dir, que está en la raíz del proyecto. Mi carpeta .git / también está en el mismo nivel de directorio.

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

Mi script debe ejecutarse desde el directorio git_hooks / real. Puede modificarlo para que se comporte de manera diferente, si lo desea.

Este script enlazará simbólicamente cualquier archivo que no tenga el sufijo de una extensión de archivo dentro del directorio git_hooks /. Tengo un README.txt en este directorio + este script (llamado symlink.sh). Todos los ganchos de git reales se denominan 'pre-commit', 'pre-push', etc., por lo que estarán vinculados simbólicamente.

cchoe1
fuente
-1

por qué no simplemente cp ./hooks/* .git / hooks /

esto funcionó para mí en Mac OS

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