Link simbólico para um gancho no git

86

Eu escrevi meu próprio gancho pós-mesclagem personalizado, agora adicionei um diretório "ganchos" à pasta principal do meu projeto (já que o git não rastreia as alterações em .git / ganchos), em algum lugar li que posso fazer um link simbólico a partir de ganchos para .git / hooks para não ter que copiar o arquivo de uma pasta para a outra toda vez que alguém o altera, então tentei:

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

Mas não parece funcionar, alguma ideia por quê? "ln hooks / post-merge .git / hooks / post-merge" funciona bem, mas criar um link físico é o mesmo que copiar, eu acho ...

Mateusz Dymczyk
fonte
22
Porque o link simbólico é resolvido em relação à sua localização. Um link simbólico .git/hooks/que aponta para hooks/post-mergeé resolvido para .git/hooks/hooks/post-merge, que não existe. Você quer ln -s -f ../../hooks/post-merge .git/hooks/post-merge. Ou facilitar a sua vida: ln -s -f ../hooks .git/hooks. Seu problema não tem nada a ver com o git.
Aristóteles Pagaltzis
Corrija-me se eu estiver errado, mas um Symlink ainda precisa ser configurado por estação de trabalho. A única coisa que isso salva é copiá-lo manualmente ou escrever outro comando que copie o arquivo de gancho rastreado para o .git/hooks.
adi518 de

Respostas:

161

você acabou de usar o caminho errado, deveria ser:

ln -s -f ../../hooks/post-merge .git/hooks/post-merge
Michal Čihař
fonte
10
Não entendo por que preciso subir dois diretórios para vincular um recurso que reside na pasta em que eu coloquei cd. Não deveria ser ln -s ./hooks/?
Droogans
45
Isto. Quando o git está avaliando o link simbólico, ele aparentemente o faz usando .git/hookscomo seu diretório de trabalho, então os caminhos relativos devem ser relativos a esse diretório. Isso é mais evidente se você primeiro cdem .git/hooksantes de fazer a ligação simbólica, e descobrir o caminho relativo de lá.
Eliot de
12
@Eliot nem a criação nem a resolução de links simbólicos são afetados pelo diretório de trabalho. O que quer que você forneça lnserá armazenado como o destino e resolvido em relação à localização do link.
Joó Ádám
2
@ JoóÁdám Você está certo. Portanto, o problema aqui é que o comando original especifica um caminho relativo incorreto. Ainda assim, cdentrar no .git/hooksantes de fazer o link o ajudará a escrever o comando, já que você pode preencher automaticamente para o caminho correto.
Eliot
1
Tudo isso funcionou para mim no final. A única diferença é que estou me ligando ao meu prepare-commit-msg. O problema é se eu estou editando a mensagem de commit usando nano, então Ctl + X sai para abortar, git ainda completa um commit de qualquer maneira ao invés de abortar como costumava fazer antes de eu fazer essa mudança. Existe uma maneira de fazer o nano sair sem fazer com que esse commit seja concluído?
frakman1 de
15

Embora você possa usar links simbólicos, também pode alterar a pasta de ganchos para seu projeto nas configurações do git com:

git config core.hooksPath hooks/

Que é local por padrão, então não vai arruinar os ganchos do git para seus outros projetos. Ele funciona para todos os ganchos neste repositório, então é especialmente útil se você tiver mais de um gancho.

Se você já tem ganchos personalizados .git/hooks/que não deseja compartilhar com sua equipe, pode adicioná-los aos ganchos / e adicionar um .gitignorepara que não sejam compartilhados.

Pierre.Sassoulas
fonte
Muito agradável! Um truque útil :) Parece muito mais à prova de futuro do que vinculá-los um por um.
jkp de
2

Mudar de diretório antes de vincular

cd /path/to/project-repo/.git/hooks
ln -s -f ../../hooks/post-merge ./post-merge
Jekis
fonte
Ainda mais simples, após cd:ln -s -f ../../hooks/post-merge
jamesdlin
0

O cálculo do caminho é feito em relação ao link simbólico. Vamos entender usando um exemplo,

ln -s path/to/file symlink/file

Aqui, o caminho para o arquivo deve realmente ser o caminho relativo do caminho do link simbólico.
O sistema realmente calcula o caminho do arquivo como symlink/path/path/to/file
O comando acima deve ser reescrito como

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

A estrutura da pasta sendo,

/ code
------ link simbólico / arquivo
------ caminho / para / arquivo

Swayamraina
fonte
0

Utilizando o comentário de Michael Cihar, aqui está um exemplo de um script bash que escrevi para simplesmente criar esses links simbólicos. Este script está localizado em git_hooks / dir, que está na raiz do projeto. Meu .git / pasta também está no mesmo nível de diretório.

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

Meu script deve ser executado de dentro do diretório git_hooks / real. Você pode modificá-lo para se comportar de maneira diferente, se desejar.

Este script criará um link simbólico para qualquer arquivo que não tenha uma extensão de arquivo no diretório git_hooks /. Eu tenho um README.txt neste diretório + este script (chamado symlink.sh). Todos os git hooks atuais são nomeados 'pre-commit', 'pre-push', etc., então eles serão vinculados simbolicamente.

cchoe1
fonte
-1

por que não apenas cp ./hooks/* .git / hooks /

isso funcionou para mim no Mac OS

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