In che modo Git gestisce i collegamenti simbolici?


1607

Se ho un file o una directory che è un collegamento simbolico e lo commetto in un repository Git, cosa succede?

Suppongo che lo lasci come un collegamento simbolico fino a quando il file non viene eliminato e quindi se si estrae il file da una versione precedente, crea semplicemente un file normale.

Cosa fa quando elimino il file a cui fa riferimento? Impegna semplicemente il collegamento penzolante?


19
.gitignorevede il collegamento simbolico come un file e non una cartella.
0xcaff,

6
Bene, evidentemente c'è di più alla domanda di quanto la risposta implichi. Ad esempio, mi chiedo quanto segue: se creo un collegamento sym nel mio repository a un file di grandi dimensioni in quel repository, invio delle modifiche e quindi invio di tali modifiche su un'altra macchina, cosa accadrà? Il file di grandi dimensioni verrà archiviato come file di grandi dimensioni in entrambe le posizioni o verrà conservato il collegamento sym, in modo tale che sulla nuova macchina il file di collegamento punti al file di grandi dimensioni originale?
jvriesem,

7
Questo è un vecchio thread ma questo commento potrebbe essere ancora utile. In risposta a jviesem, un soft link è sostanzialmente un file con il nome di un altro file. Quindi, una volta scaricato su un altro computer, il collegamento verrà scaricato e avrà il nome del file grande sul file system originale. Se sulla nuova macchina il nome non è valido, il collegamento avrà un nome non valido. Il file di grandi dimensioni non verrà scaricato sulla nuova macchina.
Lasaro,

6
@lasaro, il modo per evitare collegamenti interrotti in un repository git è utilizzare sempre percorsi relativi durante la creazione dei collegamenti simbolici, usando ../..secondo necessità.
Wildcard il

8
Si noti che nella maggior parte delle versioni di Windows sono necessarie autorizzazioni elevate per creare un collegamento simbolico. Se sei su Windows e git pullcrea un file anziché un collegamento simbolico, prova a eseguire il tuo client Git come amministratore.
axmrnv,

Risposte:


1347

Git archivia semplicemente il contenuto del collegamento (ovvero il percorso dell'oggetto del file system a cui si collega) in un 'BLOB' proprio come farebbe per un file normale. Quindi memorizza il nome, la modalità e il tipo (incluso il fatto che si tratta di un collegamento simbolico) nell'oggetto albero che rappresenta la sua directory di contenimento.

Quando si esegue il checkout di un albero contenente il collegamento, ripristina l'oggetto come collegamento simbolico indipendentemente dall'esistenza o meno dell'oggetto del file system di destinazione.

Se elimini il file a cui fa riferimento il collegamento simbolico, ciò non influisce in alcun modo sul collegamento simbolico controllato da Git. Avrai un riferimento penzolante. Spetta all'utente rimuovere o modificare il collegamento per puntare a qualcosa di valido se necessario.


328
BTW. Se si utilizza un file system come FAT che non supporta i collegamenti simbolici e il repository li utilizza, è possibile impostare la core.symlinksvariabile di configurazione su false e i collegamenti simbolici verrebbero estratti come piccoli file di testo semplice che contengono il testo del collegamento.
Jakub Narębski,

14
@ JakubNarębski L'ho visto prima. Nel nostro repository c'era un file di testo con una riga, un percorso per una libreria che usiamo. Non riuscivo a capire quale fosse lo scopo. Ora so cosa è successo.
Matt K,

25
Esito a commentare una risposta molto votata, ma penso che la frase "proprio come farebbe per un file normale" potrebbe essere fuorviante per i nuovi arrivati.
Matthew Hannigan,

10
(ha terminato il tempo di modifica) È come un normale file solo in quanto il contenuto è in un BLOB. La differenza fondamentale è che per un file normale il BLOB è il contenuto del file ma per un collegamento simbolico il BLOB ha il percorso del file a cui si collega. @ JakubNarębski Per quanto riguarda i "piccoli file di testo semplice" .. Spero che siano piccoli e di testo, ma ovviamente un blob è un blob e potenzialmente potrebbe essere enorme e binario. Vedere stackoverflow.com/questions/18411200/… per quando un file viene erroneamente digitato come link simbolico.
Matthew Hannigan,

2
Assicurati di controllare le impostazioni globali per i collegamenti simbolici e le impostazioni locali per i collegamenti simbolici. Se le impostazioni sono state copiate da TortiseGit o Windows, allora potresti avere symlinks = falseproblemi con loro.
Phyatt,

251

Puoi scoprire cosa fa Git con un file vedendo cosa fa quando lo aggiungi all'indice. L'indice è come un pre-commit. Con l'indice impegnato, è possibile utilizzare git checkoutper riportare tutto ciò che era nell'indice nella directory di lavoro. Quindi, cosa fa Git quando si aggiunge un collegamento simbolico all'indice?

Per scoprire, innanzitutto, crea un link simbolico:

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

Git non è ancora a conoscenza di questo file. git ls-filesti consente di ispezionare il tuo indice ( -sstampe statsimili a output):

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

Ora, aggiungi il contenuto del link simbolico all'archivio oggetti Git aggiungendolo all'indice. Quando aggiungi un file all'indice, Git archivia il suo contenuto nell'archivio oggetti Git.

$ git add ./symlink

Quindi, cosa è stato aggiunto?

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

L'hash è un riferimento all'oggetto compresso creato nell'archivio oggetti Git. Puoi esaminare questo oggetto se cerchi nella .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15cradice del tuo repository. Questo è il file che Git archivia nel repository, che puoi successivamente verificare. Se esamini questo file, vedrai che è molto piccolo. Non memorizza il contenuto del file collegato.

(Nota 120000è la modalità elencata ls-filesnell'output. Sarebbe qualcosa di simile 100644a un file normale.)

Ma cosa fa Git con questo oggetto quando lo si estrae dal repository e nel proprio filesystem? Dipende dalla core.symlinksconfigurazione. Da man git-config:

core.symlinks

Se falso, i collegamenti simbolici vengono estratti come piccoli file semplici che contengono il testo del collegamento.

Quindi, con un collegamento simbolico nel repository, al momento del pagamento si ottiene un file di testo con un riferimento a un percorso completo del file system o un collegamento simbolico appropriato, a seconda del valore della core.symlinksconfigurazione.

In entrambi i casi, i dati a cui fa riferimento il collegamento simbolico non vengono archiviati nel repository.


1
Risposta
eccezionale

147

Nota "redattore": questo post può contenere informazioni obsolete. Si prega di consultare i commenti e questa domanda riguardo alle modifiche in Git dalla 1.6.1.

Directory con collegamenti simbolici:

È importante notare cosa succede quando esiste una directory che è un collegamento software. Qualsiasi pull di Git con un aggiornamento rimuove il collegamento e lo rende una directory normale. Questo è quello che ho imparato duramente. Alcuni approfondimenti qui e qui.

Esempio

Prima

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

git add/commit/push

It remains the same

Dopo git pullE alcuni aggiornamenti trovati

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

4
Vale la pena notare che questi avvisi sulle directory con collegamenti simbolici non si applicano ai collegamenti simbolici con versione. Il caso limite principale in questione è stato quello di persone che collegavano in modo simbolico parte o tutto l'albero di lavoro in un percorso diverso (diciamo su una partizione diversa con più spazio su disco) e si aspettavano che git controllasse il codice attraverso il collegamento simbolico esistente. In altre parole, se si dispone di un progetto che contiene collegamenti simbolici con versione a file o directory, il normale comportamento del collegamento simbolico come BLOB conserverà i collegamenti simbolici, le modifiche di versione corrette a tali collegamenti simbolici e altrimenti funzionerà come previsto.
John Whitley,

Il comportamento sopra è stato testato con git 1.6.5.6; ma sospetto fortemente che il comportamento con versione sia stato corretto in git per un bel po 'di tempo.
John Whitley,

22
Questo comportamento è presente su tutte le versioni di git o è stato corretto con?
jbotnik,

24
Sembra che questo comportamento è stato risolto, vedi: stackoverflow.com/a/1943656/1334781
Ron Wertlen

2
Shekar: Farai modificare la tua risposta per riflettere i cambiamenti di git negli ultimi anni?
einpoklum,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.