Git y enlaces duros

98

Teniendo en cuenta que Git no reconoce los enlaces simbólicos que apuntan fuera del repositorio, ¿hay algún problema al utilizar enlaces físicos?

¿Podría Git romperlos? ¿Puede indicarme información detallada?

Alfredo Palhares
fuente
2
¿Qué intentas hacer y por qué? Un enlace físico no es diferente de un archivo normal. Si alguna vez extrajera una nueva versión de otro repositorio, sobrescribirá la que tenía, ¿cuál es el punto de vincular a algo fuera del repositorio?
Carl Norum
2
Git reconocerá los enlaces simbólicos que apuntan a una ruta fuera del repositorio.
mipadi
No mipadi, la única forma es agitando los archivos en el repositorio y los enlaces simbólicos en su ubicación "real"
Alfredo Palhares

Respuestas:

89

El objeto 'árbol', que representa directorios en Git, almacena el nombre del archivo y (subconjunto de) permisos. No almacena el número de inodo (u otro tipo de identificación de archivo). Por lo tanto, los enlaces duros no se pueden representar en git , al menos no sin herramientas de terceros como metastore o git-cache-meta (y no estoy seguro de si es posible incluso con esas herramientas).

Git intenta no tocar archivos que no necesita actualizar, pero debes tener en cuenta que git no intenta preservar los enlaces duros, por lo que pueden romperse con git.


Acerca de los enlaces simbólicos que apuntan fuera del repositorio : git no tiene problemas con ellos y debería preservar el contenido de los enlaces simbólicos ... pero la utilidad de tales enlaces es dudosa para mí, ya que si esos enlaces simbólicos se romperían o no depende del diseño del sistema de archivos fuera del repositorio de git y no bajo el control de git.

Jakub Narębski
fuente
4
Los enlaces simbólicos a rutas fuera del repositorio pueden resultar útiles. Los he usado en aplicaciones web para apuntar a la base de datos o archivos multimedia no rastreados por el repositorio. De esa manera, el archivo de configuración de la aplicación web puede apuntar a una ruta estática, pero la ubicación real de esa ruta puede variar entre el desarrollo local y los entornos de servidor.
mipadi
@mipadi: Por cierto. Gitweb moderno tiene un caso especial para mostrar enlaces simbólicos que van después de la normalización fuera del repositorio.
Jakub Narębski
6
Sí, los enlaces simbólicos fuera del repositorio están bien. Los usé para señalar un directorio de datos masivo que no necesitaba (o quería) versionado. Generalmente utilizo enlaces relativos. Entonces, en el caso de que el repositorio y el directorio de datos tuvieran que estar uno al lado del otro en algún directorio principal. Puede hacer trucos increíbles con enlaces simbólicos a ../foo.
Adrian Ratnapala
Desafortunadamente, el repositorio de Git para metastore (git: //git.hardeman.nu/metastore.git) ya no está disponible.
Derek Mahar
1
github.com/danny0838/git-store-meta es una alternativa a git-cache-meta .
Derek Mahar
22

Descubrí que, usando ganchos, puedes capturar el git pullevento (cuando hay algo que tirar ...) escribiendo el controlador de eventos del script en el .git/hooks/post-mergearchivo.

Primero, tienes que chmod +xhacerlo.

Luego, coloque los lncomandos dentro de él para recrear enlaces duros en cada extracción. ¡Genial eh!

Funciona, solo lo necesitaba para mi proyecto y ls -imuestra que los archivos se vincularon automáticamente después pull.


Mi ejemplo de .git/hooks/post-merge:

#!/bin/sh
ln -f $GIT_DIR/../apresentacao/apresentacao.pdf $GIT_DIR/../capa/apresentacao.pdf
ln -f $GIT_DIR/../avaliacoesMono/avaliacao_monografias_2011_Nilo.pdf $GIT_DIR/../capa/avaliacoes.pdf
ln -f $GIT_DIR/../posters/poster_Nilo_sci.pdf $GIT_DIR/../capa/poster.pdf
ln -f $GIT_DIR/../monografia/monografia_Nilo.pdf $GIT_DIR/../capa/monografia_Nilo.pdf

IMPORTANTE: Como puede ver, la ruta a cualquier archivo en su repositorio debe comenzar con $GIT_DIR, luego agregar la ruta relativa parcial al archivo.

También importante: -fes necesario, porque está recreando el archivo de destino.

EDITAR

El cliente moderno de git parece admitir enlaces simbólicos y enlaces físicos dentro del repositorio de forma natural, incluso cuando se empuja a una ubicación remota y luego se clona desde ella. Sin embargo, nunca volví a tener la necesidad de vincularme fuera de un repositorio de git ...

$ mkdir tmp
$ cd tmp
$ git --version
git version 2.24.3 (Apple Git-128)
$ git init .
Initialized empty Git repository in /Users/teixeira/tmp/.git/
$ mkdir x
$ cd x
$ echo 123 > original
$ cat original
123
$ cd ..
$ ln -s x/original symlink
$ cat symlink
123
$ ln x/original hardlink
$ cat hardlink
123
$ git add .
$ git commit -m 'Symlink and hardlink commit'
[master (root-commit) 8df3134] Symlink and hardlink commit
 3 files changed, 3 insertions(+)
 create mode 100644 hardlink
 create mode 120000 symlink
 create mode 100644 x/original

Clonación desde el repositorio local de git

$ cd
$ git clone tmp/ teste_tmp
Cloning into 'teste_tmp'...
done.
$ cd teste_tmp/
$ ls
hardlink  symlink  x
$ cat symlink
123
$ cat hardlink
123

Clonación desde repositorio remoto

$ cd ~/tmp
$ git remote add origin https://github.com/myUser/myRepo.git
$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (5/5), 361 bytes | 361.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/myUser/myRepo.git
 + 964dfce...8df3134 master -> master
$ cd ../
$ git clone https://github.com/myUser/myRepo.git
Cloning into 'myRepo'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 5 (delta 0), reused 5 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), done.
$ cd myRepo/
$ cat symlink
123
$ cat hardlink
123

https://github.com/mokacoding/symlinks también señala una cosa importante: los enlaces simbólicos deben definirse relativamente.

Niloct
fuente
11
Por lo tanto, parece que cada vez que agrega un enlace físico a su repositorio, también debe agregar manualmente una línea a su secuencia de comandos de enlace posterior a la fusión. Sería bueno si su enlace previo a la confirmación lo hiciera completamente automático, detectando enlaces duros (y simbólicos) en su confirmación y escribiendo las líneas apropiadas en su archivo posterior a la fusión. Git no tendría que almacenar información de inodo en el repositorio, ¡almacenaría bits en los ganchos! Pero qué lío si el archivo vinculado fuera rastreado en otro repositorio de git ... ¿una edición del archivo en un lugar se propagaría al otro repositorio sin problemas? ¿Fusiones perpetuas con un bucle circular de empujar / tirar?
placas el
Enfoque inteligente, pero es desafortunado que Git no rastree los enlaces duros, incluso potencialmente representándolos como copias en sistemas de archivos que no admiten enlaces duros.
Derek Mahar
1
@hobs perdón por tardar 7 años en responder :) Tienes razón. Si un archivo fuera del repositorio estuviera vinculado por 2 repositorios diferentes, creo que cambiar un enlace en un repositorio simplemente no se vería en el otro.
Niloct
8

De este problema de msysgit

Los puntos de unión no son enlaces simbólicos; por lo tanto, los enlaces simbólicos simplemente no son compatibles con msysGit.

Además, Git nunca rastreó los enlaces duros .

El problema estaba orientado a Windows (ya que se trata de msysgit) y se debatió sobre el posible soporte del enlace simbólico.
Pero el comentario sobre el enlace duro se refiere a Git en general.

VonC
fuente
2

Google 'git preserve hard links' y muestra que git no sabe cómo preservar la estructura de hard link AFAIK, quizás por diseño.

Los proyectos web míos utilizan enlaces físicos de la siguiente manera:

www/products/index.php
www/products/dell_latitude_id577/index.php #(hard linked to above)
www/products/dell_inspiron_id323/index.php #(hard linked again to above)

me@server:www/products$ ls -l index.php
-rwxr-xr-x 3 me me 1958 Aug 22 22:10 index.php*

Si quisiera hacer cambios en index.php, lo cambio en un lugar y los enlaces duros (páginas de detalles del producto) apuntan a los cambios, excepto que git no conserva esta relación durante la clonación y extracción en otras computadoras.

me@server:www$ git pull

en otra máquina creará un nuevo index.php para cada enlace físico.

xce_git
fuente
7
Debe implementar algún tipo de enrutamiento en su aplicación web. La vinculación dura es extraña.
Nowaker
5
Sí, al menos usa enlaces simbólicos. :)
Andres Riofrio
2
Esto es realmente lo que quiero, no quiero que git preserve los enlaces duros. Tengo un directorio de Jenkins con toneladas de directorios de espacios de trabajo y, debido a las canalizaciones de múltiples ramas, hay mucha duplicación. Así que tengo un trabajo nocturno que corre hardlink --ignore-timesobre /var/lib/jenkins, para recuperar algo de espacio en disco. Durante el día, algunos archivos se desvinculan de nuevo después git pullo, mvn compilepero eso está bien, espero que eso suceda. Si git preservara los enlaces duros, entonces mi estrategia de reciclaje de espacio en disco no funcionaría.
Amedee Van Gasse