¿Hay alguna desventaja en usar enlaces duros para algo como esto?
Ehtesh Choudhury
12
Con Windows 7, "mklink / d" (enlace simbólico de directorio) no funciona con git, pero "mklink / j" (juction) funciona bien.
yoyo
1
Si el archivo es autogenerado por una aplicación que lo regenera de tal manera que elimina el archivo y crea uno nuevo, entonces sí, este es un problema que los enlaces duros a los archivos no resolverán.
Martin Pecka
1
@EhteshChoudhury no puedes hacer enlaces duros para directorios
Gaurav Kansal
Respuestas:
46
NOTA: Este consejo ahora está desactualizado según el comentario desde Git 1.6.1. Git solía comportarse de esta manera, y ya no lo hace.
Git intenta de forma predeterminada almacenar enlaces simbólicos en lugar de seguirlos (por compacidad, y generalmente es lo que la gente quiere).
Sin embargo, accidentalmente logré agregar archivos más allá del enlace simbólico cuando el enlace simbólico es un directorio.
Es decir:
/foo/
/foo/baz
/bar/foo --> /foo
/bar/foo/baz
haciendo
git add /bar/foo/baz
parecía funcionar cuando lo probé. Sin embargo, ese comportamiento no era deseado por mí en ese momento, por lo que no puedo darle más información.
Los commits 725b06050a083474e240a2436121e0a80bb9f175 y 806d13b1ccdbdde4bbdfb96902791c4b7ed125f6 introdujeron cambios que le impidieron agregar archivos más allá de los directorios enlazados, por lo que esto no funcionará en versiones de git desde 1.6.1
Mark Longair
1
$ git add src / main / path / ConvertSymlinkToDir fatal: 'src / main / path / ConvertSymlinkToDir' está más allá de un enlace simbólico
user1767316
2
@ user1767316 leyó todo y los comentarios. Solía funcionar, ya no funciona. El software cambia, pero las respuestas aceptadas de desbordamiento de pila no. He aclarado que esto no funciona ya. Mira otra respuesta.
Kent Fredric
Sí @KentFrederic, pero el mensaje de error exacto devolvió la ayuda de la búsqueda del usuario para encontrar la solución a su problema. Intenté cancelar el voto negativo pero lo bloqueé. Por un lado, su respuesta es correcta dada la advertencia, por otro lado, se debe dar prioridad a la respuesta que funciona ahora más que en el pasado
user1767316
143
Lo que hice para agregar los archivos dentro de un enlace simbólico a Git (no usé un enlace simbólico pero):
sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY
Ejecute este comando en el directorio administrado por Git. TARGETDIRECTORYtiene que ser creado antes de que SOURCEDIRECTORYse monte en él.
¡Funciona bien en Linux, pero no en OS X! Ese truco también me ayudó con Subversion. Lo uso para incluir archivos de una cuenta de Dropbox, donde un diseñador web hace sus cosas.
sshfs puede lograr ese tipo de truco sin requerir el sudo, aquí.
PypeBros
75
¿Por qué no crear enlaces simbólicos al revés? Es decir, en lugar de vincular desde el repositorio de Git al directorio de la aplicación, simplemente vincula al revés.
Por ejemplo, supongamos que estoy configurando una aplicación instalada ~/applicationque necesita un archivo de configuración config.conf:
Agrego config.confa mi repositorio Git, por ejemplo, en ~/repos/application/config.conf.
Luego creo un enlace simbólico ~/applicationejecutando ln -s ~/repos/application/config.conf.
Es posible que este enfoque no siempre funcione, pero hasta ahora funcionó bien para mí.
Parece ser la única forma, y no es tan malo ... creo que el tuyo es un enfoque bastante elegante. git rastrea contenido, no archivos. Por lo tanto, mantener todo el contenido unido y hacer enlaces simbólicos desde allí a otros lugares tiene sentido
MestreLion
12
En mi caso, quería un enlace de un repositorio de git a otro, para poder editar archivos en cualquier ubicación y volver a comprometerme con sus controles remotos respectivos. En Windows 7, un cruce ("mklink / j") hizo el truco.
yoyo
3
por supuesto. a veces la respuesta es así de simple.
BBW Antes de Windows
¿Qué pasa si quieres obtener tanto el origen como el destino? (porque ambos pertenecen a diferentes códigos que desea tener en diferentes repositorios)
DrGC
1
No responde la pregunta :( Quería que parte de mi repositorio se sincronizara con mi iCloud. Desafortunadamente, iCloud no sigue los enlaces simbólicos, así que pensé que podría hacer que git siga los enlaces simbólicos y almacene los archivos originales en iCloud. Resulta que nadie sigue enlaces simbólicos: \
Jerry Green
49
Use enlaces duros en su lugar. Esto difiere de un enlace suave (simbólico). Todos los programas, incluido git, tratarán el archivo como un archivo normal. Tenga en cuenta que los contenidos pueden ser modificados por el cambio , ya sea el origen o el destino.
¿Apple File System admite enlaces duros de directorio?
Los enlaces duros de directorio no son compatibles con Apple File System. Todos los enlaces duros de directorio se convierten en enlaces simbólicos o alias cuando convierte de HFS + a formatos de volumen APFS en macOS.
Solo una nota: esto es básicamente lo que estaba buscando, pero luego aprendí que en Linux, un enlace duro desafortunadamente no puede cruzar los límites del sistema de archivos (que es mi caso de uso).
sdaau
26
No puedes enlazar a los directorios, ¿verdad?
Nanne
1
ln source destinationtambién funciona en OS X. Probado en El Capitan.
Mahdi Dibaiee
77
@Nanne no, pero se puede hacer: cp -al source destination. `-l 'significa archivos de enlace duro en lugar de copiar.
Paolo
66
Lamentablemente, no puede vincular directorios, ni a través de los límites del sistema de archivos. Esto hace que esta solución sea doblemente inviable para mí.
Konrad Rudolph el
25
Este es un enlace previo a la confirmación que reemplaza los blobs de enlaces simbólicos en el índice, con el contenido de esos enlaces simbólicos.
Pon esto en .git/hooks/pre-commit y hazlo ejecutable:
#!/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
Utilizamos la funcionalidad compatible con POSIX tanto como sea posible; sin embargo, diff -ano es compatible con POSIX, posiblemente entre otras cosas.
Puede haber algunos errores / errores en este código, aunque se haya probado un poco.
Es genial ver un intento de responder realmente la pregunta para archivos y no directorios. Sin embargo, nota que el anterior seguirá mostrando typechangeen git statuslos archivos que en realidad son enlaces simbólicos aunque git ahora las cosas que no son.
David Fraser
1
Gracias por esto; solo quería saber, ¿qué es process_links_to_nondir?
sdaau
@sdaau Es el nombre / argv[0]que se utiliza como nombre de comando para el shproceso. (Me tomó un poco entenderlo, ya que tampoco recordaba lo que era ☺😃)
Abbafei
3
@Abbafei ¿Puedes modificar el script para que funcione en Ubuntu (14.04)? Se está mostrando find: missing argument to -exec'. Puede ser necesario ejecutar un comando paso a paso en lugar de canalizar y combinar todo en una sola línea.
Khurshid Alam
1
@KhurshidAlam Para mí funcionó eliminar las líneas comentadas entre las líneas de comando. Sin embargo, el gancho no funciona como se esperaba (obtengo el me typechangegusta @DavidFraser, pero el archivo vinculado parece que ya no está en escena)
Scz
14
Encendido MacOS(tengo Mojave / 10.14, gitversión 2.7.1), use bindfs.
Parece genial para los equipos que se ejecutan en Mac OS, creo que los enlaces duros que se describen a continuación deberían funcionar para Windows y Linux.
Devin G Rhode
Esto fue útil, y creo que la mejor solución para una capacidad útil pero faltante en MacOS. Sin embargo, tenga en cuenta que estaba recibiendo Failed to resolve... No such file or directoryerrores a menos que use nombres de ruta completos con el bindfscomando.
electromaggot
Gracias @electromaggot. Se agregó la aclaración de que los caminos completos son necesarios
ijoseph
1
¡Funciona muy bien en macos Catalina!
Jerry Green
13
Solía agregar archivos más allá de los enlaces simbólicos desde hace bastante tiempo. Esto solía funcionar bien, sin hacer ningún arreglo especial. Desde que actualicé a Git 1.6.1, esto ya no funciona.
Es posible que pueda cambiar a Git 1.6.0 para que esto funcione. Espero que una versión futura de Git tenga una bandera git-addque le permita seguir enlaces simbólicos nuevamente.
Se engancha en las partes internas de Git, anulando el '¿es esto un enlace simbólico?' función, permitiendo que los enlaces simbólicos sean tratados como sus contenidos. Por defecto, todos los enlaces externos al repositorio están en línea; ver el enlace para más detalles.
Solución muy creativa que utiliza LD_PRELOADpara anular las funciones de la biblioteca.
iBug
Sí, pero debería elaborarse aquí. ¿Puedes hacer eso?
Peter Mortensen
No estoy seguro de cuánta elaboración ayudaría; a menos que copie el código fuente completo, esta respuesta siempre se basará en ese enlace, donde también se puede encontrar un archivo Léame. Pero sí, supongo que podría reproducir las partes importantes del archivo Léame.
Alcaro
Esto no se compila en OS X (Mojave 10.14.2). Obtenga cuatro errores quejándose de 'strchrnul' (¿quiso decir 'strchr'?) Y uno sobre '__xstat64' (quiso decir '__lxstat64'?). Finalmente obtengo un error de "acceso de miembro a tipo incompleto 'dirent64'". Ocurre independientemente si uso "make", "make OPT = 1" o "sh install.sh".
Erik Veland el
@ErikVeland Lo intenté un poco, pero parece que OSX no es compatible con LD_PRELOAD, ni nada similar. Varios documentos sugieren varias cosas, pero todos tienen varios años, y a Apple le encantan las cosas despreciables; No pude conseguir que ninguno de ellos funcionara. Lo siento.
Alcaro
6
Con Git 2.3.2+ (Q1 2015), hay otro caso en el que Git ya no seguirá el enlace simbólico: consulte commit e0d201b de Junio C Hamano ( gitster) (principal mantenedor de Git)
apply: no toque un archivo más allá de un enlace simbólico
Debido a que Git rastrea enlaces simbólicos como enlaces simbólicos, una ruta que tiene un enlace simbólico en su parte principal (por ejemplo path/to/dir/file, dondepath/to/dir hay un enlace simbólico a otro lugar, ya sea dentro o fuera del árbol de trabajo) nunca puede aparecer en un parche que se aplique de manera válida , a menos que el mismo parche elimine primero el enlace simbólico para permitir que se cree un directorio allí.
Detectar y rechazar tal parche.
Del mismo modo, cuando una entrada crea un enlace simbólico path/to/diry luego crea un archivo path/to/dir/file, debemos marcarlo como un error sin crear realmente path/to/dirun enlace simbólico en el sistema de archivos.
En cambio, para cualquier parche en la entrada que deja una ruta (es decir, una no eliminación) en el resultado, verificamos todas las rutas principales contra el árbol resultante que el parche crearía al inspeccionar todos los parches en la entrada y luego el objetivo del parche aplicación (ya sea el índice o el árbol de trabajo).
De esta manera, nosotros:
detectar una travesura o un error al agregar un enlace simbólico path/to/diry un archivo path/to/dir/fileal mismo tiempo,
mientras permite un parche válido que elimina un símbolo link path/to/diry luego agrega un archivo path/to/dir/file.
Eso significa que, en ese caso, el mensaje de error no será genérico "%s: patch does not apply", sino más específico:
OK, encontré que la respuesta en Mac OS X es hacer un enlace duro. Excepto que esa API no está expuesta a través de ln, por lo que debe usar su propio pequeño programa para hacer esto. Aquí hay un enlace a ese programa:
Si el directorio de destino de este enlace duro es un subdirectorio de otro repositorio git, esto sería un caos. Hacer operaciones git en el enlace rígido se aplicaría a este otro repositorio git. Solo revisa lo que estás haciendo.
yegle
44
Es posible hacer esto a través de code.google.com/p/bindfs que se puede instalar usando el puerto.
Kit Sunde
0
Estoy usando Git 1.5.4.3 y sigue el enlace simbólico pasado si tiene una barra inclinada final. P.ej
# Adds the symlink itself
$ git add symlink
# Follows symlink and adds the denoted directory's contents
$ git add symlink/
Respuestas:
NOTA: Este consejo ahora está desactualizado según el comentario desde Git 1.6.1. Git solía comportarse de esta manera, y ya no lo hace.
Git intenta de forma predeterminada almacenar enlaces simbólicos en lugar de seguirlos (por compacidad, y generalmente es lo que la gente quiere).
Sin embargo, accidentalmente logré agregar archivos más allá del enlace simbólico cuando el enlace simbólico es un directorio.
Es decir:
haciendo
parecía funcionar cuando lo probé. Sin embargo, ese comportamiento no era deseado por mí en ese momento, por lo que no puedo darle más información.
fuente
Lo que hice para agregar los archivos dentro de un enlace simbólico a Git (no usé un enlace simbólico pero):
Ejecute este comando en el directorio administrado por Git.
TARGETDIRECTORY
tiene que ser creado antes de queSOURCEDIRECTORY
se monte en él.¡Funciona bien en Linux, pero no en OS X! Ese truco también me ayudó con Subversion. Lo uso para incluir archivos de una cuenta de Dropbox, donde un diseñador web hace sus cosas.
fuente
umount [mydir]
. (+1 por tu gran consejo, @ user252400)¿Por qué no crear enlaces simbólicos al revés? Es decir, en lugar de vincular desde el repositorio de Git al directorio de la aplicación, simplemente vincula al revés.
Por ejemplo, supongamos que estoy configurando una aplicación instalada
~/application
que necesita un archivo de configuraciónconfig.conf
:config.conf
a mi repositorio Git, por ejemplo, en~/repos/application/config.conf
.~/application
ejecutandoln -s ~/repos/application/config.conf
.Es posible que este enfoque no siempre funcione, pero hasta ahora funcionó bien para mí.
fuente
Use enlaces duros en su lugar. Esto difiere de un enlace suave (simbólico). Todos los programas, incluido
git
, tratarán el archivo como un archivo normal. Tenga en cuenta que los contenidos pueden ser modificados por el cambio , ya sea el origen o el destino.En macOS (antes de 10.13 High Sierra)
Si ya tiene instalado git y Xcode, instale hardlink . Es una herramienta microscópica para crear enlaces duros .
Para crear el enlace duro, simplemente:
Actualización de macOS High Sierra
Siga https://github.com/selkhateeb/hardlink/issues/31 para futuras alternativas.
En Linux y otros sabores de Unix
El
ln
comando puede hacer enlaces duros:En Windows (Vista, 7, 8, ...)
Alguien sugirió usar mklink para crear una unión en Windows, pero no lo he probado:
fuente
ln source destination
también funciona en OS X. Probado en El Capitan.cp -al source destination
. `-l 'significa archivos de enlace duro en lugar de copiar.Este es un enlace previo a la confirmación que reemplaza los blobs de enlaces simbólicos en el índice, con el contenido de esos enlaces simbólicos.
Pon esto en
.git/hooks/pre-commit
y hazlo ejecutable:Notas
Utilizamos la funcionalidad compatible con POSIX tanto como sea posible; sin embargo,
diff -a
no es compatible con POSIX, posiblemente entre otras cosas.Puede haber algunos errores / errores en este código, aunque se haya probado un poco.
fuente
typechange
engit status
los archivos que en realidad son enlaces simbólicos aunque git ahora las cosas que no son.process_links_to_nondir
?argv[0]
que se utiliza como nombre de comando para elsh
proceso. (Me tomó un poco entenderlo, ya que tampoco recordaba lo que era ☺😃)find: missing argument to -exec'
. Puede ser necesario ejecutar un comando paso a paso en lugar de canalizar y combinar todo en una sola línea.typechange
gusta @DavidFraser, pero el archivo vinculado parece que ya no está en escena)Encendido
MacOS
(tengo Mojave / 10.14,git
versión 2.7.1), usebindfs
.brew install bindfs
cd /path/to/git_controlled_dir
mkdir local_copy_dir
bindfs </full/path/to/source_dir> </full/path/to/local_copy_dir>
Ha sido insinuado por otros comentarios, pero no se proporciona claramente en otras respuestas. Esperemos que esto ahorre algo de tiempo.
fuente
Failed to resolve
...No such file or directory
errores a menos que use nombres de ruta completos con elbindfs
comando.Solía agregar archivos más allá de los enlaces simbólicos desde hace bastante tiempo. Esto solía funcionar bien, sin hacer ningún arreglo especial. Desde que actualicé a Git 1.6.1, esto ya no funciona.
Es posible que pueda cambiar a Git 1.6.0 para que esto funcione. Espero que una versión futura de Git tenga una bandera
git-add
que le permita seguir enlaces simbólicos nuevamente.fuente
Me cansé de que todas las soluciones aquí estuvieran desactualizadas o requirieran root, así que creé una solución basada en LD_PRELOAD (solo Linux).
Se engancha en las partes internas de Git, anulando el '¿es esto un enlace simbólico?' función, permitiendo que los enlaces simbólicos sean tratados como sus contenidos. Por defecto, todos los enlaces externos al repositorio están en línea; ver el enlace para más detalles.
fuente
LD_PRELOAD
para anular las funciones de la biblioteca.Con Git 2.3.2+ (Q1 2015), hay otro caso en el que Git ya no seguirá el enlace simbólico: consulte commit e0d201b de Junio C Hamano (
gitster
) (principal mantenedor de Git)apply
: no toque un archivo más allá de un enlace simbólicoEso significa que, en ese caso, el mensaje de error no será genérico
"%s: patch does not apply"
, sino más específico:fuente
Hmmm,
mount --bind
no parece funcionar en Darwin.¿Alguien tiene un truco que tenga?
[editado]
OK, encontré que la respuesta en Mac OS X es hacer un enlace duro. Excepto que esa API no está expuesta a través de
ln
, por lo que debe usar su propio pequeño programa para hacer esto. Aquí hay un enlace a ese programa:Crear enlaces de directorio en Mac OS X
¡Disfrutar!
fuente
Estoy usando Git 1.5.4.3 y sigue el enlace simbólico pasado si tiene una barra inclinada final. P.ej
fuente
fatal: 'src/' is beyond a symbolic link
La conversión de enlaces simbólicos podría ser útil. Enlace en una carpeta Git en lugar de un enlace simbólico mediante un script .
fuente