Come posso fare in modo che Git segua i collegamenti simbolici?
Domanda
La soluzione migliore sarà uno script di shell che sostituisca i collegamenti simbolici con copie o esiste un altro modo per dire a Git di seguire i collegamenti simbolici?
PS:So che non è molto sicuro, ma voglio farlo solo in alcuni casi specifici.
Soluzione
NOTA: Questo consiglio è ormai obsoleto come da commento da Git 1.6.1.Git si comportava in questo modo e non lo fa più.
Git per impostazione predefinita tenta di memorizzare i collegamenti simbolici invece di seguirli (per compattezza, ed è generalmente ciò che le persone vogliono).
Tuttavia, sono riuscito accidentalmente a far sì che aggiungesse file oltre il collegamento simbolico quando il collegamento simbolico è una directory.
Cioè.:
/foo/
/foo/baz
/bar/foo --> /foo
/bar/foo/baz
facendo
git add /bar/foo/baz
sembrava funzionare quando l'ho provato.Tuttavia quel comportamento era da me indesiderato in quel momento, quindi non posso darti informazioni oltre a queste.
Altri suggerimenti
Cosa ho fatto per aggiungere i file all'interno di un collegamento simbolico in Git (non ho usato un collegamento simbolico ma):
sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY
Esegui questo comando nella directory gestita da Git. TARGETDIRECTORY
deve essere creato prima del SOURCEDIRECTORY
è montato al suo interno.
Funziona bene su Linux, ma non su OS X!Quel trucco mi ha aiutato anche con Subversion.Lo uso per includere file da un account Dropbox, dove un webdesigner fa le sue cose.
Perché non creare collegamenti simbolici al contrario?Significa invece di collegarsi dal repository Git alla directory dell'applicazione, basta collegarsi al contrario.
Ad esempio, supponiamo che sto configurando un'applicazione installata in ~/application
che necessita di un file di configurazione config.conf
:
- aggiungo
config.conf
al mio repository Git, ad esempio, su~/repos/application/config.conf
. - Quindi creo un collegamento simbolico da
~/application
correndoln -s ~/repos/application/config.conf
.
Questo approccio potrebbe non funzionare sempre, ma finora ha funzionato bene per me.
Utilizzare invece collegamenti reali.Questo differisce da un collegamento morbido (simbolico).Tutti i programmi, compresi git
tratterà il file come un file normale.Tieni presente che il contenuto può essere modificato modificando O la fonte o la destinazione.
Su macOS (prima della 10.13 High Sierra)
Se hai già installato git e Xcode, installare il collegamento fisico.E' microscopico strumento per creare collegamenti reali.
Per creare il collegamento reale, semplicemente:
hln source destination
Aggiornamento macOS High Sierra
Apple File System supporta i collegamenti fisici alle directory?
I collegamenti reali alle directory non sono supportati dal file system Apple.Tutti i collegamenti reali alle directory vengono convertiti in collegamenti simbolici o alias quando esegui la conversione dai formati di volume HFS+ a APFS su macOS.
Seguire https://github.com/selkhateeb/hardlink/issues/31 per alternative future.
Su Linux e altre versioni di Unix
IL ln
il comando può creare collegamenti fisici:
ln source destination
Su Windows (Vista, 7, 8, …)
Qualcuno ha suggerito di usarlo mklink creare una giunzione su Windows, ma non l'ho provato:
mklink /j "source" "destination"
Questo è un gancio pre-impegno che sostituisce i BLOB dei collegamenti simbolici nell'indice, con il contenuto di tali collegamenti simbolici.
Inserisci questo .git/hooks/pre-commit
, e renderlo eseguibile:
#!/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
Appunti
Utilizziamo il più possibile funzionalità conformi a POSIX;Tuttavia, diff -a
non è conforme a POSIX, forse tra le altre cose.
Potrebbero esserci alcuni sbagli/errori in questo codice, anche se è stato in qualche modo testato.
È da un po' di tempo che aggiungo file oltre i collegamenti simbolici.Funzionava perfettamente, senza prendere accordi particolari.Da quando ho aggiornato a Git 1.6.1, questo non funziona più.
Potresti essere in grado di passare a Git 1.6.0 per farlo funzionare.Spero che una versione futura di Git abbia un flag git-add
permettendogli di seguire nuovamente i collegamenti simbolici.
Mi sono stancato che ogni soluzione qui sia obsoleta o richieda il root, quindi Ho creato una soluzione basata su LD_PRELOAD (Solo Linux).
Si aggancia agli interni di Git, sovrascrivendo "è un collegamento simbolico?" funzione, consentendo i collegamenti simbine di essere trattati come il loro contenuto.Per impostazione predefinita, tutti i collegamenti all'esterno del repository sono incorporati;vedere il collegamento per i dettagli.
Con Git 2.3.2+ (Q1 2015), c'è un altro caso in cui Git non segui più il collegamento simbolico:Vedere commettere e0d201b di Junio C Hamano (gitster
) (manutentore principale di Git)
apply
:non toccare un file oltre un collegamento simbolico
Poiché Git tiene traccia dei collegamenti simbolici come collegamenti simbolici, un percorso che ha un collegamento simbolico nella sua parte principale (ad es.
path/to/dir/file
, Dovepath/to/dir
è un collegamento simbolico a qualche altra parte, sia all'interno che all'esterno dell'albero di lavoro) non può mai apparire in una patch validamente applicata, a meno che la stessa patch non rimuova prima il collegamento simbolico per consentire la creazione di una directory lì.Rileva e rifiuta tale patch.
Allo stesso modo, quando un input crea un collegamento simbolico
path/to/dir
e quindi crea un filepath/to/dir/file
, dobbiamo contrassegnarlo come errore senza effettivamente crearlopath/to/dir
collegamento simbolico nel filesystem.Invece, per qualsiasi patch nell'input che lascia un percorso (ad esempiouna mancata eliminazione) nel risultato, controlliamo tutti i percorsi principali rispetto all'albero risultante che la patch creerebbe controllando tutte le patch nell'input e quindi la destinazione dell'applicazione della patch (l'indice o l'albero di lavoro).
In questo modo:
- cogliere un errore o un errore nell'aggiungere un collegamento simbolico
path/to/dir
e un filepath/to/dir/file
allo stesso tempo,- pur consentendo una patch valida che rimuove un simbolico
link path/to/dir
e quindi aggiunge un filepath/to/dir/file
.
Ciò significa che, in tal caso, il messaggio di errore non sarà generico come "%s: patch does not apply"
, ma uno più specifico:
affected file '%s' is beyond a symbolic link
Hmmm, mount --bind
non sembra funzionare su Darwin.
Qualcuno ha un trucco che fa?
[modificato]
OK, ho scoperto che la risposta su Mac OS X è creare un collegamento fisico.Tranne che quell'API non è esposta tramite ln
, quindi devi usare il tuo piccolo programma per farlo.Ecco un collegamento a quel programma:
Creazione di collegamenti fisici alle directory in Mac OS X
Godere!
SU MacOS
(Ho Mojave/ 10.14, git
versione 2.7.1), utilizzare bindfs
.
brew install bindfs
cd /path/to/git_controlled_dir
mkdir local_copy_dir
bindfs <source_dir> local_copy_dir
È stato suggerito da altri commenti, ma non chiaramente fornito in altre risposte.Speriamo che questo faccia risparmiare tempo a qualcuno.
Sto usando Git 1.5.4.3 e segue il collegamento simbolico passato se ha una barra finale.Per esempio.
# Adds the symlink itself
$ git add symlink
# Follows symlink and adds the denoted directory's contents
$ git add symlink/
La conversione dai collegamenti simbolici potrebbe essere utile.Collegamento in una cartella Git anziché in un collegamento simbolico da una sceneggiatura.