ti-enxame.com

Como posso obter o Git para seguir links simbólicos?

Será que o meu melhor será um script Shell que substitua links simbólicos por cópias, ou existe outra maneira de dizer ao Git para seguir links simbólicos?

PS: Eu sei que não é muito seguro, mas eu só quero fazer isso em alguns casos específicos.

174
Matt

NOTA: Este aviso agora está desatualizado conforme comentário desde o Git 1.6.1. Git costumava se comportar dessa maneira, e não faz mais isso.


O Git, por padrão, tenta armazenar links simbólicos em vez de segui-los (por compacidade, e geralmente é o que as pessoas querem).

No entanto, eu acidentalmente consegui para adicionar arquivos além do symlink quando o symlink é um diretório.

Ou seja:

  /foo/
  /foo/baz
  /bar/foo --> /foo
  /bar/foo/baz

fazendo

 git add /bar/foo/baz

parecia funcionar quando eu tentei. Esse comportamento foi, no entanto, indesejado por mim na época, então não posso lhe dar informações além disso.

37
Kent Fredric

O que eu fiz para adicionar os arquivos dentro de um symlink no Git (eu não usei um symlink, mas):

Sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

Faça este comando no diretório gerenciado pelo Git. TARGETDIRECTORY deve ser criado antes da SOURCEDIRECTORY ser montada nele.

Ele funciona bem no Linux, mas não no OS X! Esse truque me ajudou com o Subversion também. Eu o uso para incluir arquivos de uma conta do Dropbox, onde um webdesigner faz suas coisas.

124
user252400

Por que não criar links simbólicos ao contrário? Ou seja, em vez de vincular o repositório Git ao diretório do aplicativo, basta vincular o contrário.

Por exemplo, digamos que estou configurando um aplicativo instalado em ~/application que precisa de um arquivo de configuração config.conf:

  • Eu adiciono config.conf ao meu repositório Git, por exemplo, em ~/repos/application/config.conf.
  • Então eu crio um symlink de ~/application executando ln -s ~/repos/application/config.conf.

Esta abordagem pode nem sempre funcionar, mas funcionou bem para mim até agora.

65
spier

Use links físicos em vez disso. Isso difere de um link suave (simbólico). Todos os programas, incluindo git, tratarão o arquivo como um arquivo regular. Observe que o conteúdo pode ser modificado alterando ou a origem ou o destino.

No macOS (antes de 10.13 High Sierra)

Se você já tem o git e o Xcode instalados, install hardlink . É uma ferramenta microscópica para criar hard links

Para criar o link físico, simplesmente:

hln source destination

atualização macOS High Sierra

O Apple File System suporta links diretos de diretório?

Os links físicos de diretório não são suportados pelo Apple File System. Todos os links físicos de diretório são convertidos em links ou aliases simbólicos quando você converte de formatos de volume HFS + para APFS em macOS.

De APFS FAQ no developer.Apple.com

Siga https://github.com/selkhateeb/hardlink/issues/31 para alternativas futuras.

No Linux e outros sabores Unix

O comando ln pode criar links físicos:

ln source destination

No Windows (Vista, 7, 8,…)

Alguém sugeriu usar mklink criar uma junção no Windows, mas eu não tentei:

mklink /j "source" "destination"
41
bfred.it

Este é um gancho de pre-commit que substitui os blobs de symlink no índice, com o conteúdo desses links simbólicos.

Coloque isso em .git/hooks/pre-commit e torne-o executável:

#!/bin/sh
# (replace "find ." with "find ./<path>" below, to work with only specific paths)

# (these lines are really all one line, on multiple lines for clarity)
# ...find symlinks which do not dereference to directories...
find . -type l -exec test '!' -d {} ';' -print -exec sh -c \
# ...remove the symlink blob, and add the content diff, to the index/cache
    'git rm --cached "$1"; diff -au /dev/null "$1" | git apply --cached -p1 -' \
# ...and call out to "sh".
    "process_links_to_nondir" {} ';'

# the end

Notas

Usamos a funcionalidade compatível com POSIX tanto quanto possível; no entanto, diff -a não é compatível com POSIX, possivelmente entre outras coisas.

Pode haver alguns erros/erros neste código, mesmo que tenha sido testado um pouco.

16
Abbafei

Eu costumava adicionar arquivos além de links simbólicos por algum tempo agora. Isso costumava funcionar muito bem, sem fazer nenhum arranjo especial. Desde que eu atualizei para o Git 1.6.1, isso não funciona mais.

Você pode ser capaz de mudar para o Git 1.6.0 para fazer este trabalho. Espero que uma versão futura do Git tenha um sinalizador para git-add permitindo que ele siga os links simbólicos novamente.

12
Erik Schnetter

Com o Git 2.3.2+ (Q1 2015), há um outro caso onde o Git irá não seguir mais o symlink: veja commit e0d201b por Junio ​​C Hamano (gitster) (mantenedor principal do Git )

apply: não toque em um arquivo além de um link simbólico

Como o Git rastreia links simbólicos como links simbólicos, um caminho que tenha um link simbólico em sua parte principal (por exemplo, path/to/dir/file, onde path/to/dir é um link simbólico para outro lugar, seja dentro ou fora da árvore de trabalho) nunca pode aparecer em um patch aplica-se validamente, a menos que o mesmo patch primeiro remova o link simbólico para permitir que um diretório seja criado nele.

Detecte e rejeite tal patch.

Da mesma forma, quando uma entrada cria um link simbólico path/to/dir e, em seguida, cria um arquivo path/to/dir/file, precisamos sinalizá-lo como um erro sem realmente criar o link simbólico path/to/dir no sistema de arquivos.

Em vez disso, para qualquer patch na entrada que deixa um caminho (isto é, uma não exclusão) no resultado, verificamos todos os caminhos principais contra a árvore resultante que o patch criaria inspecionando todos os patches na entrada e depois o destino do patch aplicação (o índice ou a árvore de trabalho).

Desta forma, nós:

  • pegar um mal ou um erro para adicionar um link simbólico path/to/dir e um arquivo path/to/dir/file ao mesmo tempo, 
  • enquanto permite um patch válido que remove um link path/to/dir simbólico e adiciona um arquivo path/to/dir/file.

Isso significa que, nesse caso, a mensagem de erro não será genérica como "%s: patch does not apply", mas uma mais específica:

affected file '%s' is beyond a symbolic link
6
VonC

Eu me cansei de todas as soluções aqui estarem desatualizadas ou exigirem root, então eu fiz uma solução baseada em LD_PRELOAD (somente Linux).

Ele se encaixa no interior do Git, ignorando o 'isso é um link simbólico?' função, permitindo que os links simbólicos sejam tratados como seu conteúdo. Por padrão, todos os links para fora do repositório estão alinhados; veja o link para detalhes.

5
Alcaro

Hmmm, mount --bind não parece funcionar em Darwin.

Alguém tem um truque que faz?

[editado]

OK, eu encontrei a resposta no Mac OS X é fazer um hardlink. Só que essa API não é exposta via ln, então você tem que usar seu próprio programa para fazer isso. Aqui está um link para esse programa:

Criando links diretos de diretório no Mac OS X

Apreciar!

4
J Chris A

Eu estou usando o Git 1.5.4.3 e ele está seguindo o symlink passado se ele tiver uma barra final. Por exemplo.

# Adds the symlink itself
$ git add symlink

# Follows symlink and adds the denoted directory's contents
$ git add symlink/
1
artistoex

Em MacOS, use bindfs

brew install bindfs

cd /path/to/git_controlled_dir 

mkdir local_copy_dir

bindfs <source_dir> local_copy_dir

Tem sido sugerido por outros comentários, mas não claramente fornecidos em outras respostas. Espero que isso economize alguém algum tempo. 

0
ijoseph

Conversão de links simbólicos pode ser útil. Link em uma pasta Git em vez de um symlink por um script .

0
Yurij73