Como o Git lida com links simbólicos?


1607

Se eu tenho um arquivo ou diretório que é um link simbólico e o comprometo em um repositório Git, o que acontece com ele?

Eu diria que ele deixa como um link simbólico até que o arquivo seja excluído e, se você retirar o arquivo de uma versão antiga, ele criará um arquivo normal.

O que faz quando eu excluo o arquivo que ele faz referência? Apenas confirma o link pendente?


19
.gitignorevê o link simbólico como um arquivo, não uma pasta.
— 0xcaff

6
Bem, evidentemente, há mais na pergunta do que essa resposta implica. Por exemplo, estou me perguntando o seguinte: se eu criar um link sym no meu repositório para algum arquivo grande nesse repositório, enviar as alterações por push e depois puxá-las para outra máquina, o que acontecerá? O arquivo grande será armazenado como um arquivo grande nos dois locais ou o link sym será preservado, de modo que, na nova máquina, o arquivo de link aponte para o arquivo grande original?
— jvriesem

7
Este é um tópico antigo, mas esse comentário ainda pode ser útil. Em resposta ao jviesem, um link flexível é basicamente um arquivo com o nome de outro arquivo. Portanto, quando você o puxar para uma máquina diferente, o link será baixado e terá o nome do arquivo grande no sistema de arquivos original. Se na nova máquina o nome não for válido, o link terá um nome inválido. O arquivo grande não será baixado para a nova máquina.
— Lasaro

6
@lasaro, a maneira de evitar links quebrados em um repositório git é sempre usar caminhos relativos ao criar os links simbólicos, usando ../..conforme necessário.
— Curinga

8
Observe que na maioria das versões do Windows você precisa de permissões elevadas para criar um link simbólico. Se você estiver no Windows e git pullcriar um arquivo em vez de um link simbólico, tente executar o seu cliente Git como administrador.
— axmrnv

Respostas:


1348

O Git apenas armazena o conteúdo do link (ou seja, o caminho do objeto do sistema de arquivos ao qual ele se vincula) em um 'blob', como faria em um arquivo normal. Em seguida, ele armazena o nome, o modo e o tipo (incluindo o fato de ser um link simbólico) no objeto em árvore que representa o diretório que o contém.

Quando você faz check-out de uma árvore que contém o link, ele restaura o objeto como um link simbólico, independentemente de o objeto do sistema de arquivos de destino existir ou não.

Se você excluir o arquivo ao qual o link simbólico faz referência, ele não afetará o link simbólico controlado pelo Git. Você terá uma referência pendente. Cabe ao usuário remover ou alterar o link para apontar para algo válido, se necessário.


328
Entre. Se você estiver em um sistema de arquivos como o FAT que não suporta links simbólicos e o seu repositório os usar, poderá definir a core.symlinksvariável de configuração como false, e os links simbólicos serão verificados como pequenos arquivos de texto sem formatação que contêm o texto do link.
— Jakub Narębski

14
@ JakubNarębski Eu vi isso antes. Havia um arquivo de texto em nosso repositório com uma linha, um caminho para uma biblioteca que usamos. Não conseguia descobrir qual era o objetivo disso. Eu sei agora o que aconteceu.
— Matt K

25
Hesito em comentar sobre uma resposta altamente votada, mas acho que a expressão "como seria para um arquivo normal" pode ser enganosa para os recém-chegados.
— Matthew Hannigan

10
(ficou sem tempo de edição) É como um arquivo normal, apenas porque o conteúdo está em um blob. A diferença crítica é que, para um arquivo normal, o blob é o conteúdo do arquivo, mas para um link simbólico, o blob possui o nome do caminho do arquivo ao qual ele vincula. @ JakubNarębski Com relação a "pequenos arquivos de texto simples" .. Você esperaria que eles fossem pequenos e de texto, mas é claro que um blob é um blob e potencialmente pode ser enorme e binário. Consulte stackoverflow.com/questions/18411200/… para saber quando um arquivo está digitado incorretamente como um link simbólico.
— Matthew Hannigan

2
Verifique as configurações globais para links simbólicos e as configurações locais para links simbólicos. Se as configurações foram copiadas do TortiseGit ou do Windows, você pode estar symlinks = falsemexendo com elas.
— phyatt

250

Você pode descobrir o que o Git faz com um arquivo, vendo o que ele faz quando o adiciona ao índice. O índice é como um pré-commit. Com o índice confirmado, você pode usar git checkoutpara trazer tudo o que estava no índice de volta ao diretório de trabalho. Então, o que o Git faz quando você adiciona um link simbólico ao índice?

Para descobrir, primeiro, faça um link simbólico:

$ ln -s /path/referenced/by/symlink symlink

O Git ainda não sabe sobre esse arquivo. git ls-filespermite inspecionar seu índice ( saída semelhante a -simpressões stat):

$ git ls-files -s ./symlink
[nothing]

Agora, adicione o conteúdo do link simbólico ao armazenamento de objetos Git, adicionando-o ao índice. Quando você adiciona um arquivo ao índice, o Git armazena seu conteúdo no armazenamento de objetos Git.

$ git add ./symlink

Então, o que foi adicionado?

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink

O hash é uma referência ao objeto compactado que foi criado no armazenamento de objetos Git. Você pode examinar esse objeto se procurar na .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15craiz do seu repositório. Este é o arquivo que o Git armazena no repositório, que você pode conferir posteriormente. Se você examinar esse arquivo, verá que ele é muito pequeno. Não armazena o conteúdo do arquivo vinculado.

(Note 120000é o modo listado na ls-filessaída. Seria como 100644um arquivo normal.)

Mas o que o Git faz com esse objeto quando você faz o check-out do repositório e do seu sistema de arquivos? Depende da core.symlinksconfiguração. De man git-config:

core.symlinks

Se falso, os links simbólicos são retirados como pequenos arquivos simples que contêm o texto do link.

Portanto, com um link simbólico no repositório, no check-out, você obtém um arquivo de texto com uma referência a um caminho completo do sistema de arquivos ou um link simbólico adequado, dependendo do valor da core.symlinksconfiguração.

De qualquer forma, os dados referenciados pelo link simbólico não são armazenados no repositório.


1
— Ótima

147

Nota do "editor": esta postagem pode conter informações desatualizadas. Por favor, veja os comentários e esta pergunta sobre as mudanças no Git desde 1.6.1.

Diretórios com links simbólicos:

É importante observar o que acontece quando há um diretório que é um link direto. Qualquer pull do Git com uma atualização remove o link e o torna um diretório normal. Isto é o que eu aprendi da maneira mais difícil. Algumas idéias aqui e aqui.

Exemplo

Antes

 ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

Depois git pullE algumas atualizações encontradas

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir

4
Vale a pena notar que esses avisos sobre diretórios com links simbólicos não se aplicam a links simbólicos com versão. O principal problema em questão foi o de pessoas vinculando parte ou a totalidade da árvore de trabalho em um caminho diferente (digamos em uma partição diferente com mais espaço em disco) e esperando que o git verifique o código através do link simbólico existente. Ou seja, se você tiver um projeto que contém links simbólicos com versão para arquivos ou diretórios, o comportamento normal do link simbólico como blob preservará os links simbólicos, a versão correta das alterações nesses links simbólicos e funcionará conforme o esperado.
— John Whitley

O comportamento acima testado com git 1.6.5.6; mas suspeito fortemente que o comportamento de versão esteja correto no git há algum tempo.
— John Whitley

22
Esse comportamento está presente em todas as versões do git ou foi corrigido?
— Jbotnik

24
Parece que este comportamento é corrigido agora, veja: stackoverflow.com/a/1943656/1334781
— Ron Wertlen

2
Shekar: Você editará sua resposta para refletir as mudanças no git nos últimos anos?
— einpoklum
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.