Git Symlinks en Windows

246

Nuestros desarrolladores utilizan una combinación de sistemas operativos basados ​​en Windows y Unix. Por lo tanto, los enlaces simbólicos creados en máquinas Unix se convierten en un problema para los desarrolladores de Windows. En Windows (msysgit), el enlace simbólico se convierte en un archivo de texto con una ruta al archivo al que apunta. En cambio, me gustaría convertir el enlace simbólico en un enlace simbólico real de Windows.

La solución ( actualizada ) que tengo para esto es:

  • Escriba una secuencia de comandos posterior al pago que buscará recursivamente archivos de texto de "enlace simbólico".
  • Reemplácelos con un enlace simbólico de Windows (usando mklink) con el mismo nombre y extensión que el "enlace simbólico" ficticio
  • Ignore este enlace simbólico de Windows agregando una entrada en .git / info / exclude

No he implementado esto, pero creo que este es un enfoque sólido para este problema.

Preguntas:

  1. ¿Qué inconvenientes, si los hay, observa en este enfoque?
  2. ¿Es este script posterior al pago incluso implementable? es decir, ¿puedo encontrar recursivamente los archivos ficticios de "enlace simbólico" que crea git?
  3. ¿Alguien ya ha trabajado en ese guión?
Ken Hirakawa
fuente
3
Aunque Git admite enlaces simbólicos, recomiendo no almacenarlos como enlaces en su repositorio, especialmente si también está trabajando con ese código en Windows.
Greg Hewgill
2
@ Greg Hewgill - Estoy totalmente de acuerdo contigo. Desafortunadamente, la naturaleza de nuestra base de código requiere enlaces simbólicos ... por lo que eliminarlos no es una opción para nosotros.
Ken Hirakawa
12
También puede preguntar en la lista de correo de msysgit por qué no lo implementaron así en primer lugar.
drizzd
8
@GregHewgill ¿por qué no? Windows admite enlaces simbólicos y uniones, esto realmente parece una característica que falta en las versiones de Windows de Git para mí ...
BrainSlugs83
66
Con el "Modo desarrollador" habilitado en Windows 10, ¡crear enlaces simbólicos no requiere derechos de administrador! (Otros comentaron tanto sobre las respuestas con menos votos, pero no las vi. Espero que este comentario sea más visible para los futuros lectores.)
Dave Pascua

Respuestas:

105

Puede encontrar los enlaces simbólicos buscando archivos que tengan un modo 120000, posiblemente con este comando:

git ls-files -s | awk '/120000/{print $4}'

Una vez que reemplace los enlaces, recomendaría marcarlos como sin cambios git update-index --assume-unchanged, en lugar de enumerarlos .git/info/exclude.

Josh Lee
fuente
2
Tuve que reemplazar awk con gawk para msysgit, pero de lo contrario funcionó perfectamente. ¡Gracias!
Ken Hirakawa
66
hola ken ¿Le importaría compartir su secuencia de comandos que verifica los archivos de texto de enlace simbólico y los reemplaza con enlaces simbólicos en Windows usando mklink. Si bien esto realmente funciona para nosotros, la parte sin suponer cambios no lo hace. al cambiar a otra rama, git dice que los archivos de enlace simbólico se cambian y deben confirmarse primero, mientras que el estado de git dice que no hay cambios ... ¿alguna idea?
joreg
66
Aquí hay uno de PowerShell que acabo de armar - gist.github.com/ferventcoder/7995025
ferventcoder
3
@flungo Hay formas más portátiles de imprimir la cuarta columna que usando GNU awk. Por ejemplo: git ls-files -s | grep '^12' | cut -f2(segunda columna delimitada por tabulaciones; otras columnas están delimitadas por espacios)
Zenexer
1
Un revestimiento para Cygwin / bash para marcar todos los enlaces simbólicos sin cambios:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden
187

Estaba haciendo esta misma pregunta hace un tiempo (no aquí, solo en general) y terminé encontrando una solución muy similar a la propuesta de OP. Primero proporcionaré respuestas directas a las preguntas 1 2 y 3, y luego publicaré la solución que terminé usando.

  1. De hecho, hay algunas desventajas en la solución propuesta, principalmente con respecto a un mayor potencial de contaminación del repositorio, o al agregar accidentalmente archivos duplicados mientras están en sus estados de "enlace simbólico de Windows". (Más información sobre esto en "limitaciones" a continuación).
  2. ¡Sí, un script posterior al pago es implementable! Tal vez no como un git checkoutpaso posterior literal , pero la solución a continuación ha satisfecho mis necesidades lo suficientemente bien como para que no fuera necesario un script literal posterior al pago.
  3. ¡Si!

La solución:

Nuestros desarrolladores se encuentran en la misma situación que los OP: una mezcla de hosts, repositorios y submódulos similares a Windows y Unix con muchos enlaces simbólicos git, y no hay soporte nativo (todavía) en la versión de lanzamiento de MsysGit para manejar de manera inteligente estos enlaces simbólicos en hosts Windows .

Gracias a Josh Lee por señalar el hecho de que git confirma enlaces simbólicos con un modo de archivo especial 120000. Con esta información, es posible agregar algunos alias de git que permiten la creación y manipulación de enlaces simbólicos git en hosts de Windows.

  1. Crear enlaces simbólicos git en Windows

    git config --global alias.add-symlink '!'"$(cat <<'ETX'
    __git_add_symlink() {
      if [ $# -ne 2 ] || [ "$1" = "-h" ]; then
        printf '%b\n' \
            'usage: git add-symlink <source_file_or_dir> <target_symlink>\n' \
            'Create a symlink in a git repository on a Windows host.\n' \
            'Note: source MUST be a path relative to the location of target'
        [ "$1" = "-h" ] && return 0 || return 2
      fi
    
      source_file_or_dir=${1#./}
      source_file_or_dir=${source_file_or_dir%/}
    
      target_symlink=${2#./}
      target_symlink=${target_symlink%/}
      target_symlink="${GIT_PREFIX}${target_symlink}"
      target_symlink=${target_symlink%/.}
      : "${target_symlink:=.}"
    
      if [ -d "$target_symlink" ]; then
        target_symlink="${target_symlink%/}/${source_file_or_dir##*/}"
      fi
    
      case "$target_symlink" in
        (*/*) target_dir=${target_symlink%/*} ;;
        (*) target_dir=$GIT_PREFIX ;;
      esac
    
      target_dir=$(cd "$target_dir" && pwd)
    
      if [ ! -e "${target_dir}/${source_file_or_dir}" ]; then
        printf 'error: git-add-symlink: %s: No such file or directory\n' \
            "${target_dir}/${source_file_or_dir}" >&2
        printf '(Source MUST be a path relative to the location of target!)\n' >&2
        return 2
      fi
    
      git update-index --add --cacheinfo 120000 \
          "$(printf '%s' "$source_file_or_dir" | git hash-object -w --stdin)" \
          "${target_symlink}" \
        && git checkout -- "$target_symlink" \
        && printf '%s -> %s\n' "${target_symlink#$GIT_PREFIX}" "$source_file_or_dir" \
        || return $?
    }
    __git_add_symlink
    ETX
    )"
    

    Uso:, git add-symlink <source_file_or_dir> <target_symlink>donde el argumento correspondiente al archivo o directorio fuente debe tomar la forma de una ruta relativa al enlace simbólico objetivo. Puede usar este alias de la misma manera que lo haría normalmente ln.

    Por ejemplo, el árbol del repositorio:

    dir/
    dir/foo/
    dir/foo/bar/
    dir/foo/bar/baz      (file containing "I am baz")
    dir/foo/bar/lnk_file (symlink to ../../../file)
    file                 (file containing "I am file")
    lnk_bar              (symlink to dir/foo/bar/)
    

    Se puede crear en Windows de la siguiente manera:

    git init
    mkdir -p dir/foo/bar/
    echo "I am baz" > dir/foo/bar/baz
    echo "I am file" > file
    git add -A
    git commit -m "Add files"
    git add-symlink ../../../file dir/foo/bar/lnk_file
    git add-symlink dir/foo/bar/ lnk_bar
    git commit -m "Add symlinks"
    
  2. Reemplazo de enlaces simbólicos git con enlaces duros NTFS + uniones

    git config --global alias.rm-symlinks '!'"$(cat <<'ETX'
    __git_rm_symlinks() {
      case "$1" in (-h)
        printf 'usage: git rm-symlinks [symlink] [symlink] [...]\n'
        return 0
      esac
      ppid=$$
      case $# in
        (0) git ls-files -s | grep -E '^120000' | cut -f2 ;;
        (*) printf '%s\n' "$@" ;;
      esac | while IFS= read -r symlink; do
        case "$symlink" in
          (*/*) symdir=${symlink%/*} ;;
          (*) symdir=. ;;
        esac
    
        git checkout -- "$symlink"
        src="${symdir}/$(cat "$symlink")"
    
        posix_to_dos_sed='s_^/\([A-Za-z]\)_\1:_;s_/_\\\\_g'
        doslnk=$(printf '%s\n' "$symlink" | sed "$posix_to_dos_sed")
        dossrc=$(printf '%s\n' "$src" | sed "$posix_to_dos_sed")
    
        if [ -f "$src" ]; then
          rm -f "$symlink"
          cmd //C mklink //H "$doslnk" "$dossrc"
        elif [ -d "$src" ]; then
          rm -f "$symlink"
          cmd //C mklink //J "$doslnk" "$dossrc"
        else
          printf 'error: git-rm-symlink: Not a valid source\n' >&2
          printf '%s =/=> %s  (%s =/=> %s)...\n' \
              "$symlink" "$src" "$doslnk" "$dossrc" >&2
          false
        fi || printf 'ESC[%d]: %d\n' "$ppid" "$?"
    
        git update-index --assume-unchanged "$symlink"
      done | awk '
        BEGIN { status_code = 0 }
        /^ESC\['"$ppid"'\]: / { status_code = $2 ; next }
        { print }
        END { exit status_code }
      '
    }
    __git_rm_symlinks
    ETX
    )"
    
    git config --global alias.rm-symlink '!git rm-symlinks'  # for back-compat.
    

    Uso:

    git rm-symlinks [symlink] [symlink] [...]
    

    Este alias puede eliminar los enlaces simbólicos de git uno por uno o todo a la vez de una sola vez. Los enlaces simbólicos se reemplazarán por enlaces duros NTFS (en el caso de los archivos) o uniones NTFS (en el caso de los directorios). El beneficio de usar enlaces duros + uniones sobre enlaces simbólicos NTFS "verdaderos" es que no se requieren permisos UAC elevados para poder crearlos.

    Para eliminar enlaces simbólicos de submódulos, solo use el soporte incorporado de git para iterar sobre ellos:

    git submodule foreach --recursive git rm-symlinks
    

    Pero, por cada acción drástica como esta, es bueno tener una inversión ...

  3. Restaurar enlaces simbólicos git en Windows

    git config --global alias.checkout-symlinks '!'"$(cat <<'ETX'
    __git_checkout_symlinks() {
      case "$1" in (-h)
        printf 'usage: git checkout-symlinks [symlink] [symlink] [...]\n'
        return 0
      esac
      case $# in
        (0) git ls-files -s | grep -E '^120000' | cut -f2 ;;
        (*) printf '%s\n' "$@" ;;
      esac | while IFS= read -r symlink; do
        git update-index --no-assume-unchanged "$symlink"
        rmdir "$symlink" >/dev/null 2>&1
        git checkout -- "$symlink"
        printf 'Restored git symlink: %s -> %s\n' "$symlink" "$(cat "$symlink")"
      done
    }
    __git_checkout_symlinks
    ETX
    )"
    
    git config --global alias.co-symlinks '!git checkout-symlinks'
    

    Uso:, git checkout-symlinks [symlink] [symlink] [...]que se deshace git rm-symlinks, restaurando efectivamente el repositorio a su estado natural (a excepción de sus cambios, que deben permanecer intactos).

    Y para submódulos:

    git submodule foreach --recursive git checkout-symlinks
    
  4. Limitaciones:

    • Los directorios / archivos / enlaces simbólicos con espacios en sus rutas deberían funcionar. Pero pestañas o nuevas líneas? YMMV ... (Con esto quiero decir: no hagas eso, porque no funcionará).

    • Si usted u otras personas se olvidan git checkout-symlinksantes de hacer algo con consecuencias potencialmente amplias git add -A, como el depósito local podría terminar en un estado contaminado.

      Usando nuestro "ejemplo de repositorio" de antes:

      echo "I am nuthafile" > dir/foo/bar/nuthafile
      echo "Updating file" >> file
      git add -A
      git status
      # On branch master
      # Changes to be committed:
      #   (use "git reset HEAD <file>..." to unstage)
      #
      #       new file:   dir/foo/bar/nuthafile
      #       modified:   file
      #       deleted:    lnk_bar           # POLLUTION
      #       new file:   lnk_bar/baz       # POLLUTION
      #       new file:   lnk_bar/lnk_file  # POLLUTION
      #       new file:   lnk_bar/nuthafile # POLLUTION
      #
      

      Whoops ...

      Por esta razón, es bueno incluir estos alias como pasos a realizar para los usuarios de Windows antes y después de construir un proyecto, en lugar de después de finalizar la compra o antes de presionar. Pero cada situación es diferente. Estos alias me han sido lo suficientemente útiles como para que no haya sido necesaria una verdadera solución posterior al pago.

¡Espero que ayude!

Referencias

http://git-scm.com/book/en/Git-Internals-Git-Objects

http://technet.microsoft.com/en-us/library/cc753194

Última actualización: 2019-03-13

  • Cumplimiento POSIX (bueno, excepto por esas mklinkllamadas, por supuesto) - ¡no más Bashisms !
  • Se admiten directorios y archivos con espacios en ellos.
  • Los códigos de estado de salida cero y no cero (para comunicar el éxito / fallo del comando solicitado, respectivamente) ahora se conservan / devuelven correctamente.
  • El add-symlinkalias ahora funciona más como ln (1) y se puede usar desde cualquier directorio del repositorio, no solo desde el directorio raíz del repositorio.
  • El rm-symlinkalias (singular) ha sido reemplazado por el rm-symlinksalias (plural), que ahora acepta múltiples argumentos (o ningún argumento en absoluto, que encuentra todos los enlaces simbólicos en todo el repositorio, como antes) para transformar selectivamente enlaces simbólicos git en enlaces duros + uniones NTFS .
  • El checkout-symlinksalias también se ha actualizado para aceptar múltiples argumentos (o ninguno en absoluto, == todo) para la reversión selectiva de las transformaciones mencionadas anteriormente.

Nota final: si bien probé cargar y ejecutar estos alias usando Bash 3.2 (e incluso 3.1) para aquellos que todavía pueden estar atrapados en versiones antiguas por varias razones, tenga en cuenta que versiones tan antiguas como estas son notorias por su analizador loco. Si experimenta problemas al intentar instalar cualquiera de estos alias, lo primero que debe considerar es actualizar su shell (para Bash, verifique la versión con CTRL + X, CTRL + V). Alternativamente, si está tratando de instalarlos pegándolos en su emulador de terminal, es posible que tenga más suerte pegándolos en un archivo y comprándolos en su lugar, por ejemplo, como

. ./git-win-symlinks.sh

¡Buena suerte!

Mark G.
fuente
¿Puedes echarle un vistazo aquí? stackoverflow.com/questions/21403772/…
Goofy
este es un excelente y maravilloso script, pero ¿hay alguna razón por la cual esto debería colocar la palabra "git" al azar al final de algunos de mis archivos que creo con git add-symlink?
Peter Turner
Además, si su nombre de archivo contiene "-h", obtendrá el uso. Sigue siendo un guión muy útil!
Peter Turner
Tu git add-symlinkreceta ha sido fantásticamente valiosa para mí. Muchas gracias.
Dan Lenski
1
¿Hay alguna forma de ejecutar automáticamente estos scripts usando ganchos?
ARF
74

La versión más reciente de git scm (testet 2.11.1) permite habilitar enlaces simbólicos. Pero tienes que clonar el repositorio con los enlaces simbólicos nuevamente git clone -c core.symlinks=true <URL>. Debe ejecutar este comando con derechos de administrador. También es posible crear enlaces simbólicos en Windows con mklink. Echa un vistazo a la wiki .

ingrese la descripción de la imagen aquí

sirlunchalot
fuente
1
Esto no funcionó para mí. Reinstalé git para Windows, recuerde marcar la casilla de verificación del enlace simbólico y clonar mi proyecto nuevamente. Mi tslint.jsonarchivo que hace referencia al archivo en el directorio principal todavía contiene ../tslint.json. Lástima, porque realmente parecía la más fácil de todas las soluciones propuestas allí.
Jan Aagaard
8
@ JanAagaard Debe clonarlo así: git clone -c core.symlinks=true <URL> y en Windows debe ejecutarlo con derechos de administrador.
sirlunchalot
66
@ARF "Inicie gpedit.msc (es decir, el editor de políticas de grupo) y agregue las cuentas a la Configuración del equipo \ Configuración de Windows \ Configuración de seguridad \ Políticas locales \ Asignación de derechos de usuario \ Crear enlaces simbólicos".
sirlunchalot
2
@sirlunchalot Gracias por la ayuda. Desde entonces me di cuenta de que mi problema es que mi usuario es parte del grupo Administradores y que esta propiedad no tiene ningún efecto para estos usuarios. Requieren elevación de UAC que git no hace.
ARF
99
Los derechos de administrador no son necesarios en el "Modo de desarrollador" en Windows 10 Creators Update. Gracias @dennis en su comentario .
Dominik
16

Debería implementarse en msysgit, pero hay dos desventajas:

  • Los enlaces simbólicos solo están disponibles en Windows Vista y versiones posteriores (no debería ser un problema en 2011, y sin embargo lo es ...), ya que las versiones anteriores solo admiten uniones de directorio.
  • (el grande) Microsoft considera que los enlaces simbólicos son un riesgo de seguridad, por lo que solo los administradores pueden crearlos de forma predeterminada. Deberá elevar los privilegios del proceso de git o usar fstool para cambiar este comportamiento en cada máquina en la que trabaje.

Hice una búsqueda rápida y se está trabajando activamente en esto, vea el número 224 .

djs
fuente
2
Actualización: por las razones anteriores, el problema se cerró como wontfix. La discusión indica que se podría aceptar una solución con algo más de trabajo en el parche (por ejemplo, usando enlaces simbólicos solo si funcionan).
Blaisorblade
2
A.) actualmente msysgit no admite enlaces simbólicos en absoluto, entonces, ¿por qué no hacer que detecte "oh, estás en vista con NTFS, déjame usar enlaces simbólicos" o "oh, estás en un sistema operativo que admite uniones con NTFS, déjame usar esos ", u" ¡oh, estás en Windows 98 / fat32, déjame recurrir a no tener esta característica y darte una advertencia en su lugar! " y luego B.) Prácticamente todos los desarrolladores de microsoft. las herramientas no funcionan correctamente (al menos no para todas sus funciones) si no las ejecuta como administrador; todos en TI saben que los desarrolladores deben ser administradores en sus propias cajas.
BrainSlugs83
1
Si bien ejecuto ciertas máquinas en la cuenta de administrador, no sigo esa filosofía en mi máquina de desarrollo. Siempre corro como un usuario normal con UAC habilitado. Mantengo una consola separada abierta para operaciones que requieren privilegios elevados. En cuanto a implementar esto, se trata de que alguien (como usted) se ofrezca como voluntario para implementarlo. Los desarrolladores de msysgit no son conocidos por la caridad ...
djs
@djs Un usuario debe abrir un símbolo del sistema con "Ejecutar como administrador". Se ejecuta casi literalmente como el Usuario administrador, lo que cambia completamente el entorno. No hay una manera de ejecutar 'mklink / d' como un usuario que también está en el grupo de administración. No se solicitará UAC. Fracasará, siempre. Solo funciona de dos maneras: Literalmente como usuario Administrador (RunAs Verb), o Usuario no administrador con cambio de política de grupo. Las uniones deben ser las predeterminadas y deben ser reconocidas por todas las herramientas. El 'riesgo de seguridad' es que los enlaces simbólicos en Windows pueden 'redirigir' los recursos compartidos SMB. Esto es un dolor y cruel.
Andrew T Finnell
8
Anunciado en diciembre de 2016, Symlinks en Windows 10 ya no es una acción del administrador. blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/…
Dennis
16

así como las cosas han cambiado con GIT desde que se publicaron muchas de estas respuestas aquí están las instrucciones correctas para que los enlaces simbólicos funcionen correctamente en Windows a partir de

AGOSTO 2018


1. Asegúrese de que git esté instalado con soporte de enlace simbólico

Durante la instalación de git en windows

2. Dile a Bash que cree enlaces duros en lugar de enlaces simbólicos

EDITAR - (carpeta git) /etc/bash.bashrc

AÑADIR AL FONDO - MSYS=winsymlinks:nativestrict

3. Configure git config para usar enlaces simbólicos

git config core.symlinks true

o

git clone -c core.symlinks=true <URL>

NOTA: He intentado agregar esto a la configuración global de git y en este momento no funciona para mí, así que recomiendo agregar esto a cada repositorio ...

4. tirar del repositorio

NOTA: a menos que haya habilitado el modo de desarrollador en la última versión de Windows 10, debe ejecutar bash como administrador para crear enlaces simbólicos

5. Restablezca todos los enlaces simbólicos (opcional) Si tiene un repositorio existente o está utilizando submódulos, puede encontrar que los enlaces simbólicos no se están creando correctamente, de modo que para actualizar todos los enlaces simbólicos en el repositorio puede ejecutar estos comandos.

find -type l -delete
git reset --hard

NOTA: esto restablecerá cualquier cambio desde la última confirmación, así que asegúrese de haber confirmado primero

Simón
fuente
15

Respuesta corta: ahora son compatibles, si puede habilitar el modo desarrollador.

Desde https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/

Ahora en Windows 10 Creators Update, un usuario (con derechos de administrador) puede habilitar primero el Modo de desarrollador, y luego cualquier usuario en la máquina puede ejecutar el comando mklink sin elevar una consola de línea de comandos.

¿Qué impulsó este cambio? La disponibilidad y el uso de enlaces simbólicos es un gran problema para los desarrolladores modernos:

Muchas herramientas de desarrollo populares como git y gestores de paquetes como npm reconocen y persisten los enlaces simbólicos al crear repositorios o paquetes, respectivamente. Cuando esos repositorios o paquetes se restauran en otro lugar, los enlaces simbólicos también se restauran, asegurando que el espacio en disco (y el tiempo del usuario) no se desperdicie.

Fácil de pasar por alto con todos los otros anuncios de la "Actualización del creador", pero si habilita el Modo de desarrollador, puede crear enlaces simbólicos sin privilegios elevados. Es posible que deba volver a instalar git y asegurarse de que la compatibilidad con enlaces simbólicos esté habilitada, ya que no está predeterminada.

Los enlaces simbólicos no están habilitados por defecto

Orangutech
fuente
1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmentha sido la forma canónica de asignar derechos de usuario como SeCreateSymbolicLinky amigos por siglos. Aparte ntrights.exedel Kit de recursos o el PowerShell ...
0xC0000022L
11

Respuesta 2020

  1. Habilite el "Modo desarrollador" en Windows 10: otorga mklinkpermisos
  2. Asegúrese de que los enlaces simbólicos estén habilitados en git
    • git config --global core.symlinks true
    • o marque la casilla de verificación al instalar msysgit

El cambio de ramas forzará la recreación de enlaces simbólicos faltantes.

Tenga cuidado, el soporte para Symlinks en Windows con algunos otros clientes Git no está completo. Notablemente GitKraken.

Cameron Tacklind
fuente
Todos mis repositorios locales tienen core.symlinks = false, lo que anularía su solución. ¿Alguna idea de lo que está produciendo esta configuración local automáticamente? ¿Posiblemente instalar Git para Windows sin marcar la casilla de verificación?
gravidThoughts
@gravidThoughts ¿qué cliente (s) de git tiene instalado? Tal vez algunas herramientas están haciendo esto? ¿Es esto cierto en un clon nuevo?
Cameron Tacklind
10

Te sugiero que no uses enlaces simbólicos dentro del repositorio '. Almacene el contenido real dentro del repositorio 'y luego coloque los enlaces simbólicos fuera del repositorio' que apuntan al contenido.

Digamos que está utilizando un repositorio para comparar el alojamiento de su sitio en * nix con el alojamiento en win. Almacene el contenido en su repositorio ', digamos /httpRepoContenty c:\httpRepoContentsiendo esta la carpeta que se sincroniza a través de GIT, SVN, etc.

Luego, reemplace la carpeta de contenido de su servidor web ( /var/wwwy c:\program files\web server\www{los nombres realmente no importan, edite si es necesario}) con un enlace simbólico al contenido en su repositorio '. Los servidores web verán el contenido como realmente en el lugar "correcto", pero puede usar su control de fuente.

Sin embargo, si necesita utilizar enlaces simbólicos con en el repositorio, deberá buscar algo así como algún tipo de scripts de confirmación previa / posterior. Sé que puede usarlos para hacer cosas, como analizar archivos de código a través de un formateador, por ejemplo, por lo que debería ser posible convertir los enlaces simbólicos entre plataformas.

si alguien conoce un buen lugar para aprender cómo hacer estos scripts para los controles de fuente comunes, SVN GIT MG, entonces agregue un comentario.

thecoshman
fuente
Al final, elegí este enfoque para crear una carpeta de enlace simbólico y crear los enlaces simbólicos a donde solía estar el archivo original. El otro enfoque no funcionó incluso después de cambiar la configuración .git / config core.symlinks = true. Solo el archivo de enlace simbólico se guardó en el repositorio y no los datos. También tuve problemas con las marcas de tiempo de la carpeta en el enlace simbólico, por lo que git bash nunca vio cuándo un archivo cambió dentro de la carpeta.
Huevos
@ Eggs, lo que podrías haber estado viendo, supongo, es que el enlace estaba dentro del repositorio, por lo que git lo guardó, simple. Sin embargo, el problema es que el objetivo estaba fuera del repositorio y git no sigue el enlace a los datos del objetivo. En Linux, tiene un tipo de enlace que funcionaría para esto, básicamente le permite tener dos rutas a los mismos datos almacenados en el disco; Tengo la sensación de que las ventanas nuevas pueden hacer esto ahora. De cualquier manera, todavía no creo que vaya a hacer lo que la gente quiere.
thecoshman
@thecoshman Esto no es una solución, sino una solución alternativa. Sin embargo, a veces esto no es una opción. Tengo un repositorio con git-annex y todas sus obras de arquitectura debido a enlaces simbólicos.
marcelo.guedes
8

Para aquellos que usan CygWin en Vista, Win7 o superior, el gitcomando nativo puede crear enlaces simbólicos "apropiados" que son reconocidos por aplicaciones de Windows como Android Studio . Solo necesita establecer la CYGWINvariable de entorno para incluir winsymlinks:nativeo winsymlinks:nativestrictcomo tal:

export CYGWIN="$CYGWIN winsymlinks:native"

La desventaja de esto (y una importante) es que el shell CygWin debe ser "Ejecutar como administrador" para que tenga los permisos del sistema operativo necesarios para crear ese tipo de enlaces simbólicos. Sin embargo, una vez que se crean, no se requieren permisos especiales para usarlos . Mientras otro desarrollador no los cambie en el repositorio, a gitpartir de entonces se ejecutará bien con los permisos de usuario normales.

Personalmente, uso esto solo para enlaces simbólicos que se navegan por aplicaciones de Windows (es decir, que no son CygWin) debido a esta dificultad adicional.

Para obtener más información sobre esta opción, consulte esta pregunta SO: Cómo hacer un enlace simbólico con cygwin en Windows 7

Brian White
fuente
6

Aquí hay un script por lotes para convertir enlaces simbólicos en el repositorio, solo para archivos, basado en la respuesta de Josh Lee. El script con alguna verificación adicional para los derechos de administrador está en https://gist.github.com/Quazistax/8daf09080bf54b4c7641 .

@echo off
pushd "%~dp0"
setlocal EnableDelayedExpansion

for /f "tokens=3,*" %%e in ('git ls-files -s ^| findstr /R /C:"^120000"') do (
     call :processFirstLine %%f
)
REM pause
goto :eof

:processFirstLine
@echo.
@echo FILE:    %1

dir "%~f1" | find "<SYMLINK>" >NUL && (
  @echo FILE already is a symlink
  goto :eof
)

for /f "usebackq tokens=*" %%l in ("%~f1") do (
  @echo LINK TO: %%l

  del "%~f1"
  if not !ERRORLEVEL! == 0 (
    @echo FAILED: del
    goto :eof
  )

  setlocal
  call :expandRelative linkto "%1" "%%l"
  mklink "%~f1" "!linkto!"
  endlocal
  if not !ERRORLEVEL! == 0 (
    @echo FAILED: mklink
    @echo reverting deletion...
    git checkout -- "%~f1"
    goto :eof
  )

  git update-index --assume-unchanged "%1"
  if not !ERRORLEVEL! == 0 (
    @echo FAILED: git update-index --assume-unchanged
    goto :eof
  )
  @echo SUCCESS
  goto :eof
)
goto :eof

:: param1 = result variable
:: param2 = reference path from which relative will be resolved
:: param3 = relative path
:expandRelative
  pushd .
  cd "%~dp2"
  set %1=%~f3
  popd
goto :eof
Quazistax
fuente
Una respuesta indocumentada realmente no sirve de mucho cuando ya hay respuestas tan extensas y detalladas presentes.
Xennex81
4

Uso enlaces sym todo el tiempo entre la raíz de mi documento y el directorio git repo. Me gusta mantenerlos separados. En Windows uso la opción mklink / j. La unión parece dejar que git se comporte normalmente:

>mklink /j <location(path) of link> <source of link>

por ejemplo:

>mklink /j c:\gitRepos\Posts C:\Bitnami\wamp\apache2\htdocs\Posts

mmv_sat
fuente
2
Tenga mucho cuidado con el Explorador de Windows y las uniones; no diferencia las uniones de la ubicación base y una eliminación se repetirá en el destino y eliminará su contenido, mientras que la eliminación de un enlace simbólico simplemente eliminará el enlace simbólico. Solo una trampa para los incautos.
Lawrence Dol
55
En realidad, acabo de probar esto en la última versión de Windows7, y ya no lo hace, por lo que el manejo de las uniones se ha mejorado en algún momento en los últimos años.
Lawrence Dol
3

Estaba buscando una solución fácil para lidiar con los enlaces simbólicos de Unix en Windows. Muchas gracias por los alias de Git anteriores. Hay una pequeña optimización que se puede hacer a los enlaces simbólicos rm para que no elimine los archivos en la carpeta de destino en caso de que el alias se ejecute por segunda vez accidentalmente. Observe la nueva condición if en el bucle para asegurarse de que el archivo no sea un enlace a un directorio antes de ejecutar la lógica.

git config --global alias.rm-symlinks '!__git_rm_symlinks(){
for symlink in $(git ls-files -s | egrep "^120000" | cut -f2); do
    *if [ -d "$symlink" ]; then
      continue
    fi*
    git rm-symlink "$symlink"
    git update-index --assume-unchanged "$symlink"
done
}; __git_rm_symlinksenter 
prgrminglover
fuente
2

Un truco simple que usamos es llamar git add --alldos veces seguidas.

Por ejemplo, nuestro script de confirmación de Windows 7 invoca:

$ git add --all
$ git add --all

La primera adición trata el enlace como texto y agrega las carpetas para eliminar.

La segunda adición atraviesa el enlace correctamente y deshace la eliminación restaurando los archivos.

Es menos elegante que algunas de las otras soluciones propuestas, pero es una solución simple para algunos de nuestros entornos heredados que agregaron enlaces simbólicos.

Mike Panoff
fuente