Git Symlinks dans Windows

nos développeurs utilisent un mélange de systèmes D'exploitation Windows et Unix. Par conséquent, les liens symboliques créés sur les machines Unix deviennent un problème pour les développeurs Windows. Dans Windows (msysgit), le lien symbolique est converti en fichier texte avec un chemin vers le fichier qu'il pointe. Au lieu de cela, je voudrais convertir le lien symbolique en un lien symbolique Windows réel.

( mise à jour ) la solution que j'ai à présent est:

  • qui de manière récursive chercher "lien" fichiers texte.
  • les remplacer par windows symlink (utilisant mklink) avec le même nom et l'extension que le mannequin "symlink "
  • ignorer ces symlink windows en ajoutant l'entrée dans .git/info/exclure

Je ne l'ai pas mis en œuvre, mais je crois que c'est une approche solide à ce problème.

Questions:

  1. Ce que, le cas échéant, inconvénients voyez-vous à cette approche?
  2. est-ce que ce script post-checkout est réalisable? c'est-à-dire est-ce que je peux trouver récursivement les faux fichiers "symlink" que git crée?
  3. quelqu'un a-t-il déjà travaillé sur un tel scénario?
183
demandé sur ROMANIA_engineer 2011-05-07 01:33:50

12 réponses

vous pouvez trouver les liens symboliques en recherchant des fichiers qui ont un mode de 120000 , éventuellement avec cette commande:

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

une fois les liens remplacés, je recommande de les marquer comme inchangés avec git update-index --assume-unchanged , plutôt que de les inscrire dans .git/info/exclude .

86
répondu Josh Lee 2011-05-08 21:17:33

je posais exactement la même question il y a quelque temps (pas ici, juste en général) et j'ai fini par trouver une solution très similaire à la proposition de L'OP. Je vais d'abord répondre directement aux questions 12 et 3, Puis je posterai la solution que j'ai finalement utilisée.

  1. il y a en effet quelques inconvénients à la solution proposée, principalement en ce qui concerne un potentiel accru de pollution du dépôt, ou en ajoutant accidentellement des fichiers en double alors qu'ils sont en leur "Windows symlink" indique. (Pour plus de détails, voir la rubrique "limitations" ci-dessous.)
  2. Oui, un post-extraction script est réalisable! Peut - être pas comme une étape post- git checkout littérale, mais la solution ci-dessous a répondu à mes besoins assez bien qu'un script post-checkout littérale n'était pas nécessaire.
  3. Oui!

La Solution:

nos développeurs sont dans la même situation que OP's: un mélange de Windows et des hôtes, des dépôts et des sous-modules basés sur Unix avec beaucoup de liens symboliques git, et aucun support natif (encore) dans la version de publication de MsysGit pour gérer intelligemment ces liens symboliques sur les hôtes Windows.

merci à Josh Lee d'avoir souligné le fait que git commits symlinks avec le code de fichier spécial 120000 . Avec cette information, il est possible d'ajouter quelques alias git qui permettent la création et la manipulation de liens symboliques git sur les hôtes Windows.

  1. création de Git symlinks sur Windows

    mise à jour 2014-11-12 (voir ci-dessous)

    git config --global alias.add-symlink '!__git_add_symlink(){
        argv=($@)
        argc=${#argv[@]}
    
        # Look for options
        options=(" -h")
        o_help="false"
        case "${argv[@]}" in *" -h"*) o_help="true" ;; esac
        if [ "$o_help" == "true" -o "$argc" -lt "2" ]; then
            echo "\
    Usage: git add-symlink <target> <link>
    
    * <target> is a RELATIVE PATH, respective to <link>.
    * <link> is a RELATIVE PATH, respective to the repository'\''s root dir.
    * Command must be run from the repository'\''s root dir."
            return 0
        fi
    
        target_arg=${argv[0]}
        link_arg=${argv[1]}
    
        if [ ! -e "$target_arg" ]; then
            echo "ERROR: Target $target_arg does not exist; not creating invalid symlink."
            return 1
        fi
    
        hash=$(echo -n "$target_arg" | git hash-object -w --stdin)
        git update-index --add --cacheinfo 120000 "$hash" "$link_arg"
        git checkout -- "$link_arg"
    
    }; __git_add_symlink "$@"'
    

    Usage: git add-symlink <src> <dst> , où <src> est une référence relative (en ce qui concerne <dst> ) à l'emplacement actuel du fichier ou du répertoire à relier, et <dst> est une référence relative (par rapport à la racine du dépôt) à la destination désirée du lien.

    E. G., l'arbre du dépôt:

    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/)
    

    peut être créé sur Windows comme suit:

    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. Remplacement de git liens symboliques avec les liens NTFS+jonctions

    git config --global alias.rm-symlink '!__git_rm_symlink(){
        git checkout -- ""
        link=$(echo "")
        POS=$'\''/'\''
        DOS=$'\''\\'\''
        doslink=${link//$POS/$DOS}
        dest=$(dirname "$link")/$(cat "$link")
        dosdest=${dest//$POS/$DOS}
        if [ -f "$dest" ]; then
            rm -f "$link"
            cmd //C mklink //H "$doslink" "$dosdest"
        elif [ -d "$dest" ]; then
            rm -f "$link"
            cmd //C mklink //J "$doslink" "$dosdest"
        else
            echo "ERROR: Something went wrong when processing  . . ."
            echo "       $dest may not actually exist as a valid target."
        fi
    }; __git_rm_symlink ""'
    
    git config --global alias.rm-symlinks '!__git_rm_symlinks(){
        for symlink in $(git ls-files -s | egrep "^120000" | cut -f2); do
            git rm-symlink "$symlink"
            git update-index --assume-unchanged "$symlink"
        done
    }; __git_rm_symlinks'
    

    Utilisation:

    git rm-symlink dir/foo/bar/lnk_file
    git rm-symlink lnk_bar
    git update-index --assume-unchanged dir/foo/bar/lnk_file
    git update-index --assume-unchanged lnk_bar
    

    Cela supprime git liens symboliques un par un, les remplacer par des liens durs NTFS (dans le cas de fichiers) ou des jonctions NTFS (dans le cas de répertoires). L'avantage d'utiliser hardlinks+junctions plutôt que" true "NTFS symlinks est que les permissions UAC élevées ne sont pas nécessaires pour qu'ils soient créés. enfin, à votre guise, vous pouvez choisir de débloquer (ou non) les liens symboliques "supprimés" avec git update-index .

    pour des raisons de commodité, vous pouvez aussi simplement courir:

    git rm-symlinks
    

    supprime tous les liens symboliques git dans le dépôt courant, en les remplaçant par des liens durs+jonctions si nécessaire, et automatiquement signale les changements à ignorer par git status .

    pour supprimer les liens symboliques des sous-modules, utilisez simplement le support intégré de git pour les itérer:

    git submodule foreach --recursive git rm-symlinks
    

    mais, pour chaque action drastique comme celle-ci, un renversement est agréable d'avoir...

  3. restauration de git symlinks sur Windows

    git config --global alias.checkout-symlinks '!__git_checkout_symlinks(){
        POS=$'\''/'\''
        DOS=$'\''\\'\''
        for symlink in $(git ls-files -s | egrep "^120000" | cut -f2); do
            git update-index --no-assume-unchanged "$symlink"
            dossymlink=${symlink//$POS/$DOS}
            cmd //C rmdir //Q "$dossymlink" 2>/dev/null
            git  checkout -- "$symlink"
            echo "Restored git symlink $symlink <<===>> $(cat $symlink)"
        done
    }; __git_checkout_symlinks'
    

    Usage: git checkout-symlinks , qui annule git rm-symlinks , en rétablissant effectivement le dépôt à son état naturel (sauf pour vos modifications, qui devrait rester intact).

    et pour les sous-modules:

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

    1. ne peut être exécuté qu'à partir de la racine du repo, sinon, des bizarreries se produisent...
    2. de l'Onglet base de l'auto-complétion est cassé lors de la saisie de l'un de ces alias
    3. si les gens oublient git checkout-symlinks avant de faire quelque chose comme git add -A , ils pourraient polluer la réputation!

      en utilisant notre "exemple repo" d'avant:

      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...

      pour cette raison, il est agréable d'inclure ces alias comme étapes à effectuer pour les utilisateurs de Windows avant-et-après la construction d'un projet, plutôt qu'après la vérification ou avant de pousser. Mais chaque situation est différente. Ces alias ont été assez utiles pour moi qu'une VRAIE solution de post-départ n'ait pas été nécessaire.

Espère que ça aide!

références:

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

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

mise à jour 2014-11-12: parce que je n'ai personnellement fait qu'un usage intensif des alias rm-symlinks et checkout-symlinks ci-dessus, j'ai réussi à ignorer un bogue assez méchant dans le add-symlink alias. Auparavant, -n n'était pas passé à la déclaration echo responsable de la création du fichier GIT symlink qui serait plus tard ajouté à la zone de transit dans le cadre des opérations de add-symlink . Cela signifie qu'une nouvelle ligne ( 0x0D 0x0A sur les hôtes Windows) était ajoutée à tous les liens git créés avec add-symlink . Alors que ces liens symboliques git seraient encore "amovible" sur les hôtes Windows avec rm-symlinks très bien, si jamais ils ont été ces liens sortiraient toujours cassés de l'autre côté . Cette question a été corrigée, et add-symlink devrait maintenant fonctionner comme prévu.

164
répondu Mark G. 2018-02-06 21:06:02

la version la plus récente de git scm (testet 2.11.1) permet d'activer les liens symboliques. Mais vous devez cloner le dépôt avec les liens symboliques à nouveau git clone -c core.symlinks=true <URL> . Vous devez exécuter cette commande avec les droits d'administrateur. Il est également possible de créer des liens symboliques sur Windows avec mklink. Consultez le wiki .

enter image description here

39
répondu sirlunchalot 2017-02-21 08:57:25

il devrait être mis en œuvre dans msysgit, mais il y a deux inconvénients:

  • les liens symboliques ne sont disponibles que dans Windows Vista et plus tard (ne devrait pas être un problème en 2011, et pourtant il l'est...), car les anciennes versions ne prennent en charge que les jonctions de répertoires.
  • (le gros) Microsoft considère les liens symboliques d'un risque de sécurité et, ainsi, seuls les administrateurs peuvent créer par défaut. Vous aurez besoin d'élever les privilèges du processus git ou d'utiliser fstool pour changer ce comportement sur chaque machine sur laquelle vous travaillez.

j'ai fait une recherche rapide et il y a un travail en cours activement fait sur ce, voir le numéro 224 .

14
répondu djs 2011-05-08 22:06:54

je vous suggérerais de ne pas utiliser de liens symboliques dans la déclaration. Stockez le contenu réel à l'intérieur du repo' et placez ensuite des liens symboliques à l'extérieur du repo' qui pointent vers le contenu.

alors disons que vous utilisez un repo' pour comparer l'hébergement de votre site sur *nix avec l'hébergement sur win. Stockez le contenu dans votre repo', disons /httpRepoContent et c:\httpRepoContent avec ceci étant le dossier qui est synchronisé via GIT, SVN etc.

ensuite, remplacer le dossier de contenu de votre serveur web ( /var/www et c:\program files\web server\www {les noms n'ont pas vraiment d'importance, éditez si vous le DEVEZ}) avec un lien symbolique vers le contenu de votre repo'. Les serveurs web verront le contenu comme étant réellement au " bon " endroit, mais vous pourrez utiliser votre contrôle source.

cependant, si vous avez besoin d'utiliser des liens symboliques avec dans le repo', vous aurez besoin de regarder dans quelque chose comme une sorte de scripts pré/post de propagation. Je sais que vous pouvez les utiliser pour faire des choses, comme analyser des fichiers formater par exemple, il devrait donc être possible de convertir les liens symboliques entre les plateformes.

si quelqu'un connaît un bon endroit pour apprendre comment faire ces scripts pour les contrôles source communs, SVN GIT MG, alors s'il vous plaît ajouter un commentaire.

9
répondu thecoshman 2012-02-09 09:45:25

pour ceux qui utilisent CygWin sur Vista, Win7, ou au-dessus, la commande native git peut créer des liens" appropriés "qui sont reconnus par les applications Windows telles que Android Studio . Vous avez juste besoin de définir la variable d'environnement CYGWIN pour inclure winsymlinks:native ou winsymlinks:nativestrict comme tel:

export CYGWIN="$CYGWIN winsymlinks:native"

l'inconvénient de ceci (et un important à cela) est que le shell CygWin doit être " exécuté comme Administrateur" pour qu'il ait les permissions D'OS nécessaires pour créer ce genre de liens symboliques. Une fois qu'ils sont créés, cependant, aucune permissions spéciales ne sont nécessaires pour utiliser eux. Tant qu'elles ne sont pas modifiées dans le dépôt par un autre développeur, git fonctionne ensuite correctement avec les permissions normales des utilisateurs.

personnellement, J'utilise ce seulement pour les liens symboliques qui sont navigués par les applications Windows (c.-à-d. non-CygWin) en raison de cette difficulté supplémentaire.

pour plus d'informations sur cette option, voir cette question SO: Comment faire le lien symbolique avec cygwin dans Windows 7

7
répondu Brian White 2017-05-23 11:47:12

voici un script par lots pour convertir les liens symboliques dans le dépôt, pour les fichiers seulement, basé sur la réponse de Josh Lee. Le Script avec quelques vérifications supplémentaires pour les droits d'administrateur est à 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
4
répondu Quazistax 2015-02-28 16:38:10

brève réponse: ils sont maintenant bien pris en charge, si vous pouvez activer le mode développeur.

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

maintenant sous Windows 10 Mise à jour des créateurs, un utilisateur (avec les droits d'administrateur) peut activez d'abord le mode développeur, puis n'importe quel utilisateur de la machine peut exécuter la commande mklink sans élever une console de ligne de commande.

Ce qui a poussé à ce changement? La disponibilité et l'utilisation de liens symboliques est un grand face à moderne développeurs:

de nombreux outils de développement populaires comme git et les gestionnaires de paquets comme npm reconnaître et persister les liens symboliques lors de la création de repos ou de paquets, respectivement. Lorsque ces repos ou paquets sont alors restaurés ailleurs, les liens symboliques sont également restaurés, assurant l'espace disque (et le temps de l'utilisateur) n'est pas perdu.

facile à regarder avec toutes les autres annonces de la "mise à jour du Créateur", mais si vous activez le mode développeur, vous pouvez créer des liens symboliques sans privilèges élevés. Vous devrez peut-être réinstaller et vous assurer que le support est activé, car ce n'est pas par défaut.

Symbolic Links aren't enabled by default

3
répondu Orangutech 2018-04-19 04:58:42

je cherchais une solution facile pour gérer les liens symboliques unix sur windows. Merci beaucoup pour le dessus de Git alias. Il y a une petite optimisation qui peut être faite sur les RM-symlinks pour qu'il ne supprime pas les fichiers dans le dossier de destination au cas où l'alias serait lancé une deuxième fois accidentellement. Veuillez observer la nouvelle condition if dans la boucle pour s'assurer que le fichier n'est pas déjà un lien vers un répertoire avant la logique est exécuté.

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 
2
répondu prgrminglover 2016-02-25 23:43:16

j'utilise les liens sym tout le temps entre mon répertoire racine de document et git repo. Je tiens à les garder séparés. Sous windows, j'utilise l'option mklink /J. La jonction semble laisser git se comporter normalement:

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

par exemple:

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

1
répondu mmv_sat 2015-06-16 16:55:41

un truc simple que nous utilisons est d'appeler git add --all deux fois de suite.

par exemple, nos appels de script de propagation de Windows 7:

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

le premier add traite le lien comme du texte et ajoute les dossiers à supprimer.

le second add traverse le lien correctement et annule la suppression en restaurant les fichiers.

il est moins élégant que certaines des autres solutions proposées, mais il est un simple correction à certains de nos environnements hérités qui ont obtenu des liens symboliques ajoutés.

1
répondu Mike Panoff 2018-07-20 13:10:12

donc, comme les choses ont changé avec GIT depuis que beaucoup de ces réponses ont été publiées voici les instructions correctes pour obtenir des liens symboliques fonctionnant correctement dans windows à partir de

AUGUST 2018


1. Assurez-vous que git est installé avec le support de symlink

During the install of git on windows

2. Dites à Bash de créer des liens durs au lieu des liens symboliques

EDIT -- git (dossier)/etc/bash.bashrc

AJOUTER AU BAS - MSYS=winsymlinks:nativestrict

3. Ensemble git config pour utiliser des liens symboliques

git config core.symlinks true

ou

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

NOTE: j'ai essayé d'ajouter ceci à la config global git et pour le moment cela ne fonctionne pas pour moi donc je recommande en ajoutant ceci à chaque repo...

4. tirer le rapport

NOTE: sauf si vous avez activé le mode développeur dans la dernière version de Windows 10, vous devez exécuter bash en tant qu'administrateur pour créer des liens symboliques

5. Réinitialiser tous les liens symboliques (optionnel)) Si vous disposez déjà d'une opération de pension ou utilisez submodules vous pouvez trouver que les liens symboliques ne sont pas créés correctement afin d'actualiser tous les liens symboliques dans le repo vous pouvez exécuter ces commandes.

find -type l -delete
git reset --hard

NOTE: cela va réinitialiser tous les changements depuis le dernier commit alors assurez-vous que vous avez commis en premier

0
répondu Simon 2018-08-30 12:47:57