Git Symlinks in Windows


246

Unsere Entwickler verwenden eine Mischung aus Windows- und Unix-basierten Betriebssystemen. Daher werden auf Unix-Computern erstellte Symlinks für Windows-Entwickler zu einem Problem. In Windows (msysgit) wird der Symlink in eine Textdatei mit einem Pfad zu der Datei konvertiert, auf die er verweist. Stattdessen möchte ich den Symlink in einen tatsächlichen Windows-Symlink konvertieren.

Die ( aktualisierte ) Lösung, die ich dafür habe, ist:

  • Schreiben Sie ein Post-Checkout-Skript, das rekursiv nach "Symlink" -Textdateien sucht.
  • Ersetzen Sie sie durch Windows Symlink (mit mklink) mit demselben Namen und derselben Erweiterung wie Dummy "Symlink".
  • Ignorieren Sie diesen Windows-Symlink, indem Sie einen Eintrag in .git / info / exclude hinzufügen

Ich habe dies nicht implementiert, aber ich glaube, dass dies ein solider Ansatz für dieses Problem ist.

Fragen:

  1. Welche Nachteile sehen Sie bei diesem Ansatz, wenn überhaupt?
  2. Ist dieses Post-Checkout-Skript überhaupt implementierbar? dh kann ich rekursiv herausfinden, welche Dummy-Symlink-Dateien git erstellt?
  3. Hat jemand schon an einem solchen Skript gearbeitet?

3
Obwohl Git Symlinks unterstützt, würde ich dringend empfehlen, diese nicht als Links in Ihrem Repository zu speichern, insbesondere wenn Sie auch unter Windows mit diesem Code arbeiten.
Greg Hewgill

2
@ Greg Hewgill - Ich stimme dir vollkommen zu. Leider erfordert die Art unserer Codebasis Symlinks. Daher ist das Entfernen dieser Links für uns keine Option.
Ken Hirakawa

12
Sie können auch auf der msysgit-Mailingliste nachfragen, warum sie das überhaupt nicht implementiert haben.
Nieselregen

8
@ GregHewgill warum nicht? Windows unterstützt sowohl symbolische Links als auch Junctions - dies scheint mir in den Windows-Versionen von Git wirklich eine fehlende Funktion zu sein ...
BrainSlugs83

6
Wenn der "Entwicklermodus" in Windows 10 aktiviert ist, sind für das Erstellen von Symlinks keine Administratorrechte erforderlich! (Andere kommentierten ebenso wenig Antworten mit weniger Stimmen, aber ich habe sie nicht gesehen. Ich hoffe, dieser Kommentar ist für zukünftige Leser sichtbarer.)
Dave Pascua

Antworten:


105

Sie können die Symlinks finden, indem Sie nach Dateien suchen, die einen Modus haben 120000, möglicherweise mit diesem Befehl:

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

Sobald Sie die Links ersetzt haben, würde ich empfehlen, sie als unverändert zu markieren git update-index --assume-unchanged, anstatt sie in aufzulisten .git/info/exclude.


2
Ich musste awk durch gawk für msysgit ersetzen, aber sonst funktionierte es perfekt. Vielen Dank!
Ken Hirakawa

6
Helo Ken. Würde es Ihnen etwas ausmachen, Ihr Skript zu teilen, das nach Symlink-Textdateien sucht und diese mithilfe von mklink durch Symlinks in Windows ersetzt? Während dies für uns tatsächlich funktioniert, funktioniert der --assume-unveränderte Teil nicht. Beim Wechsel zu einem anderen Zweig sagt Git, dass die Symlink-Dateien geändert werden und zuerst festgeschrieben werden müssen, während der Git-Status besagt, dass es keine Änderungen gibt. Irgendeine Idee?
Joreg

6
Hier ist eine PowerShell, die ich gerade zusammengestellt habe - gist.github.com/ferventcoder/7995025
ferventcoder

3
@flungo Es gibt tragbarere Möglichkeiten, die vierte Spalte zu drucken als mit GNU awk. Zum Beispiel: git ls-files -s | grep '^12' | cut -f2(zweite durch Tabulatoren getrennte Spalte; andere Spalten sind durch Leerzeichen getrennt)
Zenexer

1
Ein Liner für Cygwin / Bash, um alle Symlinks unverändert zu markieren:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden

187

Ich habe vor einiger Zeit genau dieselbe Frage gestellt (nicht hier, nur im Allgemeinen) und am Ende eine sehr ähnliche Lösung gefunden wie OP. Zuerst werde ich direkte Antworten auf die Fragen 1, 2 und 3 geben und dann die Lösung veröffentlichen, die ich letztendlich verwendet habe.

  1. Die vorgeschlagene Lösung weist in der Tat einige Nachteile auf, vor allem in Bezug auf ein erhöhtes Potenzial für Repository-Verschmutzung oder das versehentliche Hinzufügen doppelter Dateien, während sie sich im Status "Windows-Symlink" befinden. (Mehr dazu unter "Einschränkungen" weiter unten.)
  2. Ja, ein Post-Checkout-Skript ist implementierbar! Vielleicht nicht als wörtlicher Post- git checkoutStep, aber die unten stehende Lösung hat meine Anforderungen gut genug erfüllt, dass ein wörtliches Post-Checkout-Skript nicht erforderlich war.
  3. Ja!

Die Lösung:

Unsere Entwickler befinden sich in einer ähnlichen Situation wie OPs: eine Mischung aus Windows- und Unix-ähnlichen Hosts, Repositorys und Submodulen mit vielen Git-Symlinks und (noch) keiner nativen Unterstützung in der Release-Version von MsysGit für den intelligenten Umgang mit diesen Symlinks auf Windows-Hosts .

Vielen Dank an Josh Lee für den Hinweis, dass git Symlinks mit einem speziellen Dateimodus festlegt 120000. Mit diesen Informationen können einige Git-Aliase hinzugefügt werden, mit denen Git-Symlinks auf Windows-Hosts erstellt und bearbeitet werden können.

  1. Erstellen von Git-Symlinks unter 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
    )"
    

    Verwendung: git add-symlink <source_file_or_dir> <target_symlink>Dabei muss das der Quelldatei oder dem Quellverzeichnis entsprechende Argument die Form eines Pfads relativ zum Zielsymlink haben. Sie können diesen Alias ​​genauso verwenden, wie Sie es normalerweise tun würden ln.

    ZB der Repository-Baum:

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

    Kann unter Windows wie folgt erstellt werden:

    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. Ersetzen von Git-Symlinks durch NTFS-Hardlinks + Junctions

    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.
    

    Verwendung:

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

    Dieser Alias ​​kann Git-Symlinks einzeln oder auf einmal auf einen Schlag entfernen. Symlinks werden durch NTFS-Hardlinks (bei Dateien) oder NTFS-Junctions (bei Verzeichnissen) ersetzt. Der Vorteil der Verwendung von Hardlinks + Junctions gegenüber "echten" NTFS-Symlinks besteht darin, dass keine erhöhten UAC-Berechtigungen erforderlich sind, damit sie erstellt werden können.

    Um Symlinks aus Submodulen zu entfernen, verwenden Sie einfach die integrierte Unterstützung von git, um diese zu durchlaufen:

    git submodule foreach --recursive git rm-symlinks
    

    Aber für jede drastische Aktion wie diese ist eine Umkehrung schön ...

  3. Wiederherstellen von Git-Symlinks unter 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'
    

    Verwendung git checkout-symlinks [symlink] [symlink] [...]:, die rückgängig gemacht git rm-symlinkswird und das Repository effektiv in seinen natürlichen Zustand zurückversetzt (mit Ausnahme Ihrer Änderungen, die intakt bleiben sollten ).

    Und für Submodule:

    git submodule foreach --recursive git checkout-symlinks
    
  4. Einschränkungen:

    • Verzeichnisse / Dateien / Symlinks mit Leerzeichen in ihren Pfaden sollten funktionieren. Aber Tabs oder Zeilenumbrüche? YMMV… (Damit meine ich: Tu das nicht, weil es nicht funktionieren wird.)

    • Wenn Sie oder andere dies vergessen, git checkout-symlinksbevor Sie etwas mit möglicherweise weitreichenden Konsequenzen wie tun git add -A, kann das lokale Repository in einen verschmutzten Zustand geraten.

      Verwenden Sie unser "Beispiel-Repo" von zuvor:

      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
      #
      

      Hoppla...

      Aus diesem Grund ist es hilfreich, diese Aliase als Schritte einzuschließen, die Windows-Benutzer vor und nach dem Erstellen eines Projekts ausführen müssen, anstatt nach dem Auschecken oder vor dem Push. Aber jede Situation ist anders. Diese Aliase waren für mich so nützlich, dass eine echte Post-Checkout-Lösung nicht erforderlich war.

Hoffentlich hilft das!

Verweise:

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

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

Letzte Aktualisierung: 2019-03-13

  • POSIX-Konformität (außer diesen mklinkAnrufen natürlich) - keine Bashisms mehr !
  • Verzeichnisse und Dateien mit Leerzeichen werden unterstützt.
  • Null- und Nicht-Null-Exit-Statuscodes (zur Übermittlung von Erfolg / Misserfolg des angeforderten Befehls) werden jetzt ordnungsgemäß beibehalten / zurückgegeben.
  • Der add-symlinkAlias ​​funktioniert jetzt eher wie ln (1) und kann von jedem Verzeichnis im Repository aus verwendet werden, nicht nur vom Stammverzeichnis des Repositorys.
  • Der rm-symlinkAlias ​​(Singular) wurde durch den rm-symlinksAlias ​​(Plural) ersetzt, der nun mehrere Argumente (oder überhaupt keine Argumente, die wie zuvor alle Symlinks im gesamten Repository finden) akzeptiert, um Git-Symlinks selektiv in NTFS-Hardlinks + Junctions umzuwandeln .
  • Der checkout-symlinksAlias ​​wurde ebenfalls aktualisiert, um mehrere Argumente (oder gar keine, == alles) für die selektive Umkehrung der oben genannten Transformationen zu akzeptieren.

Letzte Anmerkung: Während ich das Laden und Ausführen dieser Aliase mit Bash 3.2 (und sogar 3.1) für diejenigen getestet habe, die aus einer Reihe von Gründen immer noch an solchen alten Versionen hängen bleiben, sollten Sie sich darüber im Klaren sein, dass so alte Versionen für ihren Parser berüchtigt sind Fehler. Wenn beim Installieren eines dieser Aliase Probleme auftreten, sollten Sie zunächst die Aktualisierung Ihrer Shell prüfen (für Bash überprüfen Sie die Version mit STRG + X, STRG + V). Wenn Sie versuchen, sie durch Einfügen in Ihren Terminalemulator zu installieren, haben Sie möglicherweise mehr Glück, wenn Sie sie in eine Datei einfügen und stattdessen beschaffen, z. B. als

. ./git-win-symlinks.sh

Viel Glück!


Kannst du es dir bitte hier ansehen? stackoverflow.com/questions/21403772/…
Goofy

Dies ist ein großartiges und wunderbares Skript, aber gibt es einen Grund, warum das Wort "git" zufällig am Ende einiger meiner Dateien angebracht werden sollte, die ich mit git add-symlink erstelle?
Peter Turner

Wenn Ihr Dateiname "-h" enthält, erhalten Sie auch die Verwendung. Immer noch ein sehr nützliches Skript!
Peter Turner

Ihr git add-symlinkRezept war für mich fantastisch wertvoll. Danke vielmals.
Dan Lenski

1
Gibt es eine Möglichkeit, diese Skripte mithilfe von Hooks automatisch auszuführen?
ARF

74

Die neueste Version von git scm (testet 2.11.1) ermöglicht das Aktivieren symbolischer Links. Sie müssen das Repository jedoch erneut mit den Symlinks klonen git clone -c core.symlinks=true <URL>. Sie müssen diesen Befehl mit Administratorrechten ausführen. Es ist auch möglich, Symlinks unter Windows mit mklink zu erstellen. Schauen Sie sich das Wiki an .

Geben Sie hier die Bildbeschreibung ein


1
Das hat bei mir nicht funktioniert. Ich habe git für Windows neu installiert. Denken Sie daran, das Kontrollkästchen symlink zu aktivieren und mein Projekt erneut zu klonen. Meine tslint.jsonDatei, die auf die Datei im übergeordneten Verzeichnis verweist, enthält noch ../tslint.json. Schade, denn dies sah wirklich nach der einfachsten aller dort vorgeschlagenen Lösungen aus.
Jan Aagaard

8
@JanAagaard Sie müssen es wie folgt klonen: git clone -c core.symlinks=true <URL> Und unter Windows müssen Sie es mit Administratorrechten ausführen.
Sirlunchalot

6
@ARF "Starten Sie gpedit.msc (dh den Gruppenrichtlinien-Editor) und fügen Sie die Konten zu Computerkonfiguration \ Windows-Einstellungen \ Sicherheitseinstellungen \ Lokale Richtlinien \ Zuweisung von Benutzerrechten \ Symbolische Links erstellen hinzu."
Sirlunchalot

2
@sirlunchalot Danke für die Hilfe. Inzwischen ist mir klar geworden, dass mein Problem darin besteht, dass mein Benutzer Teil der Gruppe Administratoren ist und dass diese Eigenschaft für diese Benutzer keine Auswirkungen hat. Sie erfordern eine UAC-Erhöhung, die Git nicht tut.
ARF

9
Administratorrechte sind im "Entwicklermodus" in Windows 10 Creators Update nicht erforderlich . Danke @dennis in seinem Kommentar .
Dominik

16

Es sollte in msysgit implementiert werden, aber es gibt zwei Nachteile:

  • Symbolische Links sind nur in Windows Vista und höher verfügbar (sollte 2011 kein Problem sein und ist es dennoch ...), da ältere Versionen nur Verzeichnisübergänge unterstützen.
  • (der große) Microsoft betrachtet symbolische Links als Sicherheitsrisiko, sodass nur Administratoren sie standardmäßig erstellen können. Sie müssen die Berechtigungen des Git-Prozesses erhöhen oder fstool verwenden, um dieses Verhalten auf jedem Computer zu ändern, auf dem Sie arbeiten.

Ich habe eine schnelle Suche durchgeführt und es wird aktiv daran gearbeitet, siehe Ausgabe 224 .


2
Update: Aus den oben genannten Gründen wurde das Problem als Wontfix geschlossen. Die Diskussion zeigt, dass ein Fix mit etwas mehr Arbeit am Patch akzeptiert werden könnte (z. B. Symlinks nur verwenden, wenn sie funktionieren).
Blaisorblade

2
A.) Derzeit unterstützt msysgit überhaupt keine Symlinks. Warum sollte es nicht erkennen, dass "Oh, Sie sind mit NTFS auf Vista? Lassen Sie mich Symlinks verwenden" oder "Oh, Sie arbeiten mit einem Betriebssystem, das Junctions mit NTFS unterstützt." Lassen Sie mich diese verwenden "oder" Oh, Sie arbeiten unter Windows 98 / Fat32. Lassen Sie mich darauf zurückgreifen, diese Funktion einfach nicht zu haben und Ihnen stattdessen eine Warnung zu geben! " und dann B.) So ziemlich alle Microsoft-Entwickler. Tools funktionieren nicht richtig (zumindest nicht für alle Funktionen), wenn Sie sie nicht als Administrator ausführen - jeder in der IT weiß, dass Entwickler Administratoren auf ihren eigenen Boxen sein müssen.
BrainSlugs83

1
Während ich bestimmte Computer im Administratorkonto ausführe, folge ich dieser Philosophie auf meinem Entwicklungscomputer nicht. Ich laufe immer als normaler Benutzer mit UAC-fähiger. Ich halte eine separate Konsole für Vorgänge offen, für die erhöhte Berechtigungen erforderlich sind. Um dies umzusetzen, muss sich jemand (wie Sie) freiwillig melden, um es umzusetzen. Die msysgit-Entwickler sind nicht für wohltätige Zwecke bekannt ...
DJs

@djs Ein Benutzer muss eine Eingabeaufforderung mit "Als Administrator ausführen" öffnen. Es wird fast buchstäblich als Administrator ausgeführt, wodurch die Umgebung vollständig geändert wird. Es gibt keine Möglichkeit, 'mklink / d' als Benutzer auszuführen, der sich ebenfalls in der Admin-Gruppe befindet. Es wird keine UAC-Eingabeaufforderung angezeigt. Es wird immer scheitern. Es gibt nur zwei Möglichkeiten: Buchstäblich als Administrator (RunAs Verb) oder als Benutzer ohne Administratorrechte mit Gruppenrichtlinienänderung. Junctions sollten die Standardeinstellung sein und von allen Tools erkannt werden. Das "Sicherheitsrisiko" besteht darin, dass Symlinks unter Windows SMB-Freigaben "umleiten" können. Das ist ein Schmerz und grausam.
Andrew T Finnell

8
Symlinks in Windows 10 wurden im Dezember 2016 angekündigt und sind keine Administratoraktion mehr. blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/…
Dennis

16

Da sich die Dinge mit GIT geändert haben, seit viele dieser Antworten hier veröffentlicht wurden, finden Sie hier die richtigen Anweisungen, damit Symlinks ab Windows ordnungsgemäß funktionieren

AUGUST 2018


1. Stellen Sie sicher, dass git mit Symlink-Unterstützung installiert ist

Während der Installation von Git unter Windows

2. Weisen Sie Bash an, Hardlinks anstelle von Symlinks zu erstellen

EDIT - (Git-Ordner) /etc/bash.bashrc

UNTEN HINZUFÜGEN - MSYS=winsymlinks:nativestrict

3. Stellen Sie git config so ein, dass Symlinks verwendet werden

git config core.symlinks true

oder

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

HINWEIS: Ich habe versucht, dies zur globalen Git-Konfiguration hinzuzufügen, und im Moment funktioniert es nicht für mich. Ich empfehle daher, dies jedem Repo hinzuzufügen ...

4. Ziehen Sie das Repo

HINWEIS: Sofern Sie den Entwicklermodus in der neuesten Version von Windows 10 nicht aktiviert haben, müssen Sie bash als Administrator ausführen, um Symlinks zu erstellen

5. Alle Symlinks zurücksetzen (optional) Wenn Sie ein vorhandenes Repo haben oder Submodule verwenden, werden die Symlinks möglicherweise nicht korrekt erstellt. Um alle Symlinks im Repo zu aktualisieren, können Sie diese Befehle ausführen.

find -type l -delete
git reset --hard

HINWEIS: Dadurch werden alle Änderungen seit dem letzten Festschreiben zurückgesetzt. Stellen Sie daher sicher, dass Sie zuerst festgeschrieben haben


15

Kurze Antwort: Sie werden jetzt gut unterstützt, wenn Sie den Entwicklermodus aktivieren können.

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

In Windows 10 Creators Update kann ein Benutzer (mit Administratorrechten) zuerst den Entwicklermodus aktivieren, und dann kann jeder Benutzer auf dem Computer den Befehl mklink ausführen, ohne eine Befehlszeilenkonsole zu öffnen.

Was hat diese Veränderung vorangetrieben? Die Verfügbarkeit und Verwendung von Symlinks ist für moderne Entwickler eine große Sache:

Viele beliebte Entwicklungstools wie git und Paketmanager wie npm erkennen und behalten Symlinks beim Erstellen von Repos bzw. Paketen bei. Wenn diese Repos oder Pakete dann an anderer Stelle wiederhergestellt werden, werden auch die Symlinks wiederhergestellt, um sicherzustellen, dass kein Speicherplatz (und keine Zeit für den Benutzer) verschwendet wird.

Bei allen anderen Ankündigungen des "Creator's Update" leicht zu übersehen, aber wenn Sie den Entwicklermodus aktivieren, können Sie Symlinks ohne erhöhte Berechtigungen erstellen. Möglicherweise müssen Sie git neu installieren und sicherstellen, dass die Symlink-Unterstützung aktiviert ist, da dies nicht standardmäßig der Fall ist.

Symbolische Links sind standardmäßig nicht aktiviert


1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmentist seit Jahrhunderten die kanonische Methode, Benutzerrechte wie SeCreateSymbolicLinkund Freunde zuzuweisen . Anders als ntrights.exeaus dem Resource Kit oder der PowerShell ...
0xC0000022L

11

2020 Antwort

  1. Aktivieren Sie "Entwicklermodus" in Windows 10 - gibt mklinkBerechtigungen
  2. Stellen Sie sicher, dass Symlinks in Git aktiviert sind
    • git config --global core.symlinks true
    • oder aktivieren Sie das Kontrollkästchen bei der Installation von msysgit

Durch das Wechseln der Zweige werden fehlende Symlinks neu erstellt.

Seien Sie vorsichtig, die Unterstützung für Symlinks unter Windows mit einigen anderen Git-Clients ist nicht vollständig. Insbesondere GitKraken.


Alle meine lokalen Repositorys haben core.symlinks = false, was Ihre Lösung überschreiben würde. Irgendeine Idee, was diese lokale Konfiguration automatisch erzeugt? Möglicherweise Git für Windows installieren, ohne das Kontrollkästchen zu aktivieren?
gravidThoughts

@gravidThoughts Welche Git-Clients haben Sie installiert? Vielleicht macht das ein Werkzeug? Trifft dies auf einen frischen Klon zu?
Cameron Tacklind

10

Ich würde vorschlagen, dass Sie keine Symlinks innerhalb des Repos verwenden. Speichern Sie den eigentlichen Inhalt im Repo und platzieren Sie dann Symlinks außerhalb des Repos, die auf den Inhalt verweisen.

Nehmen wir also an, Sie verwenden ein Repo, um das Hosting Ihrer Website auf * nix mit dem Hosting auf win zu vergleichen. Speichern Sie den Inhalt in Ihrem Repo ', sagen wir, /httpRepoContentund c:\httpRepoContentdies ist der Ordner, der über GIT, SVN usw. synchronisiert wird.

Ersetzen Sie dann den Inhaltsordner Ihres Webservers ( /var/wwwund c:\program files\web server\www{Namen spielen keine Rolle, bearbeiten Sie sie, wenn Sie müssen}) durch einen symbolischen Link zum Inhalt Ihres Repos. Die Webserver sehen den Inhalt tatsächlich am "richtigen" Ort, aber Sie können Ihre Quellcodeverwaltung verwenden.

Wenn Sie jedoch Symlinks mit im Repo 'verwenden müssen, müssen Sie sich mit so etwas wie Pre / Post-Commit-Skripten befassen. Ich weiß, dass Sie sie verwenden können, um Dinge zu tun, wie zum Beispiel Code-Dateien über einen Formatierer zu analysieren, sodass es möglich sein sollte, die Symlinks zwischen Plattformen zu konvertieren.

Wenn jemand einen guten Ort kennt, um zu lernen, wie man diese Skripte für die allgemeinen Quellcodeverwaltungen, SVN GIT MG, erstellt, fügen Sie bitte einen Kommentar hinzu.


Am Ende habe ich diesen Ansatz gewählt, um einen Symlink-Out-Ordner zu erstellen und die symbolischen Links zu der ursprünglichen Datei zu erstellen. Der andere Ansatz hat nicht funktioniert, selbst nachdem ich die Einstellung .git / config geändert habe. Core.symlinks = true. Nur die symbolische Linkdatei wurde im Repo gespeichert und nicht die Daten. Hatte auch Probleme mit Ordner-Zeitstempeln auf dem symbolischen Link, so dass git bash nie sah, wann sich eine Datei innerhalb des Ordners änderte.
Eier

@Eggs, was Sie vielleicht gesehen haben, ist, dass der Link innerhalb des Repos war, und so hat Git ihn einfach gespeichert. Das Problem ist jedoch, dass sich das Ziel außerhalb des Repos befand und git nicht dem Link zu den Zieldaten folgt. Unter Linux haben Sie eine Art Link, der dafür funktioniert. Grundsätzlich können Sie zwei Pfade zu denselben Daten auf der Festplatte speichern. Ich habe das Gefühl, dass neue Fenster dies jetzt tun können. Auf jeden Fall glaube ich immer noch nicht, dass es tun wird, was die Leute wollen.
Thecoshman

@thecoshman Dies ist keine Lösung, sondern eine Problemumgehung. Manchmal ist dies jedoch keine Option. Ich habe ein Repository mit Git-Annex und all seine Architekturen funktionieren aufgrund symbolischer Verknüpfungen.
marcelo.guedes

8

Für Benutzer von CygWin unter Vista, Win7 oder höher kann der native gitBefehl "richtige" Symlinks erstellen, die von Windows-Apps wie Android Studio erkannt werden . Sie müssen nur die festlegen CYGWINUmgebungsvariable enthalten winsymlinks:nativeoder winsymlinks:nativestrictals solche:

export CYGWIN="$CYGWIN winsymlinks:native"

Der Nachteil (und ein wesentlicher) ist, dass die CygWin-Shell "Als Administrator ausführen" sein muss, damit sie über die zum Erstellen dieser Art von Symlinks erforderlichen Betriebssystemberechtigungen verfügt. Sobald sie erstellt wurden, sind jedoch keine besonderen Berechtigungen erforderlich, um sie zu verwenden . Solange sie nicht von einem anderen Entwickler im Repository geändert werden, gitläuft sie anschließend mit normalen Benutzerberechtigungen einwandfrei.

Persönlich verwende ich dies nur für Symlinks, die aufgrund dieser zusätzlichen Schwierigkeit von Windows-Apps (dh Nicht-CygWin) navigiert werden.

Weitere Informationen zu dieser Option finden Sie in dieser SO-Frage: Herstellen einer symbolischen Verknüpfung mit Cygwin in Windows 7


6

Hier ist ein Batch-Skript zum Konvertieren von Symlinks im Repository, nur für Dateien, basierend auf Josh Lees Antwort. Das Skript mit einigen zusätzlichen Überprüfungen der Administratorrechte finden Sie unter 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

Eine undokumentierte Antwort ist wirklich nicht sehr nützlich, wenn bereits so lange und ausführliche Antworten vorhanden sind.
Xennex81

4

Ich verwende ständig Sym-Links zwischen meinem Dokumentenstamm und dem Git-Repo-Verzeichnis. Ich mag es, sie getrennt zu halten. Unter Windows verwende ich die Option mklink / j. Die Kreuzung scheint zuzulassen, dass sich Git normal verhält:

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

beispielsweise:

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


2
Seien Sie sehr vorsichtig mit Windows Explorer und Junctions. Junctions werden nicht vom Basisort unterschieden, und ein Löschvorgang wird in das Ziel zurückgeführt und dessen Inhalt gelöscht, während beim Löschen eines Symlinks nur der Symlink entfernt wird. Nur eine Falle für Unvorsichtige.
Lawrence Dol

5
Ich habe dies gerade auf dem neuesten Windows7 getestet und es funktioniert nicht mehr. Daher wurde die Handhabung von Junctions in den letzten Jahren irgendwann verbessert.
Lawrence Dol

3

Ich suchte nach einer einfachen Lösung, um mit den symbolischen Unix-Links unter Windows umzugehen. Vielen Dank für die oben genannten Git-Aliase. Es gibt eine kleine Optimierung, die an den rm-symlinks vorgenommen werden kann, damit die Dateien im Zielordner nicht gelöscht werden, falls der Alias ​​versehentlich ein zweites Mal ausgeführt wird. Beachten Sie die neue if-Bedingung in der Schleife, um sicherzustellen, dass die Datei noch kein Link zu einem Verzeichnis ist, bevor die Logik ausgeführt wird.

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

Ein einfacher Trick, den wir verwenden, besteht darin, einfach anzurufen git add --all zweimal hintereinander .

Zum Beispiel ruft unser Windows 7-Festschreibungsskript Folgendes auf:

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

Beim ersten Hinzufügen wird der Link als Text behandelt und die zu löschenden Ordner werden hinzugefügt.

Das zweite Hinzufügen durchläuft den Link korrekt und macht das Löschen durch Wiederherstellen der Dateien rückgängig.

Es ist weniger elegant als einige der anderen vorgeschlagenen Lösungen, aber es ist eine einfache Lösung für einige unserer Legacy-Umgebungen, denen Symlinks hinzugefügt wurden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.