Git Symlinks w Windows

246

Nasi programiści używają kombinacji systemów operacyjnych Windows i Unix. Dlatego dowiązania symboliczne utworzone na maszynach Unix stają się problemem dla programistów Windows. W systemie Windows (msysgit) dowiązanie symboliczne jest konwertowane na plik tekstowy ze ścieżką do pliku, na który wskazuje. Zamiast tego chciałbym przekonwertować dowiązanie symboliczne w rzeczywiste dowiązanie symboliczne Windows.

Mam ( zaktualizowane ) rozwiązanie tego problemu:

  • Napisz skrypt po kasie, który będzie rekurencyjnie szukał plików tekstowych „dowiązanie symboliczne”.
  • Zastąp je symlink Windows (używając mklink) o tej samej nazwie i rozszerzeniu co atrapa „symlink”
  • Zignoruj ​​te dowiązanie symboliczne systemu Windows, dodając wpis do .git / info / exclude

Nie wdrożyłem tego, ale uważam, że jest to solidne podejście do tego problemu.

Pytania:

  1. Jakie są wady tego podejścia?
  2. Czy ten skrypt po wykonaniu transakcji jest nawet możliwy do wdrożenia? tj. czy mogę rekurencyjnie dowiedzieć się, jakie pliki git „symlink” tworzy git?
  3. Czy ktoś już pracował nad takim skryptem?
Ken Hirakawa
źródło
3
Chociaż Git obsługuje dowiązania symboliczne, zdecydowanie odradzam ich przechowywanie jako łącza w repozytorium, szczególnie jeśli pracujesz z tym kodem w systemie Windows.
Greg Hewgill
2
@Greg Hewgill - Całkowicie się z tobą zgadzam. Niestety, natura naszej bazy kodu wymaga dowiązań symbolicznych ... więc ich usunięcie nie jest dla nas opcją.
Ken Hirakawa,
12
Możesz również zapytać na liście mailingowej msysgit, dlaczego nie zaimplementowali go w ten sposób.
drizzd
8
@GregHewgill, dlaczego nie? Windows obsługuje zarówno dowiązania symboliczne, jak i skrzyżowania - to naprawdę wydaje mi się brakującą funkcją w wersjach Gita dla Windows ...
BrainSlugs83
6
Po włączeniu „Trybu programisty” w systemie Windows 10 tworzenie dowiązań symbolicznych nie wymaga uprawnień administratora! (Inni komentowali tyle samo odpowiedzi na mniej głosowane odpowiedzi, ale ich nie widziałem. Mam nadzieję, że ten komentarz będzie bardziej widoczny dla przyszłych czytelników.)
Dave Pascua,

Odpowiedzi:

105

Możesz znaleźć dowiązania symboliczne, szukając plików o trybie 120000, prawdopodobnie za pomocą tego polecenia:

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

Po wymianie linków zalecam oznaczanie ich jako niezmienionych git update-index --assume-unchangedzamiast wpisywania ich .git/info/exclude.

Josh Lee
źródło
2
Musiałem zamienić awk na gawk dla msysgit, ale poza tym działało idealnie. Dzięki!
Ken Hirakawa
6
Helo Ken. czy mógłbyś udostępnić swój skrypt, który sprawdza pliki tekstowe dowiązań symbolicznych i zastępuje je dowiązaniami symbolicznymi w systemie Windows za pomocą mklink? podczas gdy to faktycznie działa dla nas, część --assume-niezmieniona nie działa. po przejściu do innej gałęzi git mówi, że pliki dowiązań symbolicznych zostały zmienione i należy je najpierw zatwierdzić, podczas gdy status git mówi, że nie ma żadnych zmian ... jakiś pomysł?
jutro
6
Oto PowerShell, który właśnie utworzyłem
gist.github.com/ferventcoder/7995025
3
@flungo Istnieje więcej przenośnych sposobów drukowania czwartej kolumny niż używanie GNU awk. Na przykład: git ls-files -s | grep '^12' | cut -f2(druga kolumna rozdzielana tabulatorami; inne kolumny są rozdzielane
spacjami
1
Jeden linijka dla Cygwin / bash do oznaczania wszystkich dowiązań symbolicznych bez zmian:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden
187

Zadałem to samo pytanie jakiś czas temu (nie tutaj, ogólnie) i znalazłem bardzo podobne rozwiązanie do propozycji OP. Najpierw udzielę bezpośrednich odpowiedzi na pytania 1 2 i 3, a następnie opublikuję rozwiązanie, z którego ostatecznie skorzystałem.

  1. Rzeczywiście istnieje kilka wad proponowanego rozwiązania, głównie dotyczących zwiększonego potencjału zanieczyszczenia repozytorium lub przypadkowego dodania duplikatów plików, gdy są w stanie „dowiązania symbolicznego Windows”. (Więcej na ten temat w „ograniczeniach” poniżej.)
  2. Tak, skrypt po wykonaniu transakcji jest możliwy do wdrożenia! Może nie jako dosłowny git checkoutkrok po kroku, ale poniższe rozwiązanie spełniło moje potrzeby na tyle dobrze, że dosłowny skrypt po przejściu do kasy nie był konieczny.
  3. Tak!

Rozwiązanie:

Nasi programiści znajdują się w podobnej sytuacji co OP: mieszanka hostów Windows, Unix, repozytoriów i podmodułów z wieloma dowiązaniami symbolicznymi git oraz brak natywnej obsługi (jeszcze) w wersji MsysGit dla inteligentnej obsługi tych dowiązań symbolicznych na hostach Windows .

Dzięki Josh Lee za zwrócenie uwagi na fakt, że git zatwierdza dowiązania symboliczne ze specjalnym trybem pliku 120000. Dzięki tym informacjom można dodać kilka aliasów git, które pozwalają na tworzenie i manipulowanie dowiązaniami symbolicznymi git na hostach Windows.

  1. Tworzenie dowiązań symbolicznych git w systemie 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
    )"
    

    Zastosowanie: git add-symlink <source_file_or_dir> <target_symlink>gdzie argument odpowiadający plikowi źródłowemu lub katalogowi musi mieć postać ścieżki względem docelowego dowiązania symbolicznego. Możesz użyć tego aliasu w taki sam sposób, jak zwykle ln.

    Np. Drzewo repozytorium:

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

    Można go utworzyć w systemie Windows w następujący sposób:

    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. Zamiana dowiązań symbolicznych git na dowiązania twarde NTFS + połączenia

    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.
    

    Stosowanie:

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

    Ten alias może usuwać dowiązania symboliczne git jeden po drugim lub naraz za jednym zamachem. Dowiązania symboliczne zostaną zastąpione dowiązaniami stałymi NTFS (w przypadku plików) lub połączeniami NTFS (w przypadku katalogów). Zaletą używania hardlinks + skrzyżowań nad „prawdziwymi” dowiązaniami symbolicznymi NTFS jest to, że podwyższone uprawnienia UAC nie są wymagane do ich utworzenia.

    Aby usunąć dowiązania symboliczne z podmodułów, po prostu użyj wbudowanej obsługi git do iteracji nad nimi:

    git submodule foreach --recursive git rm-symlinks
    

    Ale w przypadku każdego takiego drastycznego działania miło jest mieć odwrócenie ...

  3. Przywracanie dowiązań symbolicznych git w systemie 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'
    

    Użycie git checkout-symlinks [symlink] [symlink] [...]:, które się cofa git rm-symlinks, skutecznie przywracając repozytorium do jego naturalnego stanu (z wyjątkiem zmian, które powinny pozostać nienaruszone).

    A dla podmodułów:

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

    • Katalogi / pliki / dowiązania symboliczne ze spacjami na ścieżkach powinny działać. Ale karty czy nowe linie? YMMV… (Rozumiem przez to: nie rób tego, ponieważ to nie zadziała.)

    • Jeśli ty lub inni zapomnicie, git checkout-symlinkszanim zrobicie coś o potencjalnie szerokich konsekwencjach, np git add -A. Lokalne repozytorium może skończyć się zanieczyszczonym stanem.

      Korzystając z naszego „przykładowego repozytorium” sprzed:

      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
      #
      

      Ups ...

      Z tego powodu fajnie jest dołączyć te aliasy jako kroki do wykonania dla użytkowników systemu Windows przed i po zbudowaniu projektu, a nie po kasie lub przed wypchnięciem. Ale każda sytuacja jest inna. Te aliasy były dla mnie na tyle przydatne, że prawdziwe rozwiązanie po przejściu do kasy nie było konieczne.

Mam nadzieję, że to pomaga!

Bibliografia:

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

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

Ostatnia aktualizacja: 13.03.2019

  • Zgodność z POSIX (no cóż, z wyjątkiem tych mklinkwywołań, oczywiście) - koniec z bashizmami !
  • Obsługiwane są katalogi i pliki ze spacjami.
  • Zerowe i niezerowe kody statusu wyjścia (odpowiednio dla pomyślnego zakończenia / niepowodzenia żądanego polecenia) są teraz poprawnie zachowane / zwrócone.
  • add-symlinkAlias działa teraz podobnie ln (1) i może być używany z dowolnym katalogu w repozytorium, a nie tylko katalogu głównego repozytorium.
  • rm-symlinkPs (pojedyncza) został zastąpiony przez rm-symlinksalias (mnoga), który obecnie przyjmuje wiele argumentów (lub żadnych parametrów w ogóle, która znajduje wszystkich dowiązania przez repozytorium, jak poprzednio), dla selektywnego przekształcenia symlinki git w NTFS hardlinki + węzłów .
  • checkout-symlinksAlias została zaktualizowana, aby zaakceptować wiele argumentów (lub wcale, == wszystko) do selektywnego odwrócenia wspomnianych przekształceń.

Uwaga końcowa: podczas gdy testowałem ładowanie i uruchamianie tych aliasów przy użyciu Bash 3.2 (a nawet 3.1) dla tych, którzy nadal mogą utknąć na tak starożytnych wersjach z wielu powodów, pamiętaj, że wersje tak stare jak te są znane ze względu na parser robaki. Jeśli wystąpią problemy podczas próby zainstalowania któregokolwiek z tych aliasów, pierwszą rzeczą, na którą powinieneś zwrócić uwagę, jest aktualizacja powłoki (w przypadku Bash sprawdź wersję za pomocą CTRL + X, CTRL + V). Alternatywnie, jeśli próbujesz je zainstalować, wklejając je do emulatora terminala, możesz mieć więcej szczęścia wklejając je do pliku i zamiast tego, np. Jako

. ./git-win-symlinks.sh

Powodzenia!

Mark G.
źródło
czy możesz na to rzucić okiem? stackoverflow.com/questions/21403772/…
Goofy
to świetny i wspaniały skrypt, ale czy jest jakiś powód, dla którego powinien losowo umieszczać słowo „git” na końcu niektórych moich plików, które tworzę za pomocą git add-symlink?
Peter Turner
Ponadto, jeśli nazwa pliku zawiera „-h”, otrzymasz użycie. Nadal bardzo przydatny skrypt!
Peter Turner
Twój git add-symlinkprzepis był dla mnie fantastycznie cenny. Wielkie dzięki.
Dan Lenski
1
Czy istnieje jakiś sposób automatycznego wykonywania tych skryptów przy użyciu haków?
ARF
74

Najnowsza wersja git scm (testet 2.11.1) umożliwia włączanie dowiązań symbolicznych. Ale musisz ponownie sklonować repozytorium za pomocą dowiązań symbolicznych git clone -c core.symlinks=true <URL>. Musisz uruchomić to polecenie z uprawnieniami administratora. Możliwe jest również tworzenie dowiązań symbolicznych w systemie Windows za pomocą mklink. Sprawdź wiki .

wprowadź opis zdjęcia tutaj

sirlunchalot
źródło
1
To mi nie zadziałało. Ponownie zainstalowałem git dla Windows, pamiętaj, aby zaznaczyć pole wyboru dowiązania symbolicznego i ponownie sklonować mój projekt. Mój tslint.jsonplik odwołujący się do pliku w katalogu nadrzędnym nadal zawiera ../tslint.json. Szkoda, bo to naprawdę wyglądało na najłatwiejsze ze wszystkich proponowanych tam rozwiązań.
Jan Aagaard,
8
@JanAagaard Musisz sklonować go w następujący sposób: git clone -c core.symlinks=true <URL> A w systemie Windows musisz go uruchomić z uprawnieniami administratora.
sirlunchalot
6
@ARF „Uruchom gpedit.msc (tj. Edytor zasad grupy) i dodaj konta do konfiguracji komputera \ Ustawienia systemu Windows \ Ustawienia zabezpieczeń \ Zasady lokalne \ Przypisywanie praw użytkownika \ Utwórz dowiązania symboliczne.”
sirlunchalot
2
@sirlunchalot Dzięki za pomoc. Od tego czasu zdałem sobie sprawę, że moim problemem jest to, że mój użytkownik należy do grupy Administratorzy i że ta właściwość nie ma wpływu na tych użytkowników. Wymagają podniesienia UAC, czego nie robi git.
ARF,
9
Prawa administratora nie są konieczne w „Trybie programisty” w Windows 10 Creators Update. Dzięki @dennis w swoim komentarzu .
Dominik,
16

Powinien zostać zaimplementowany w msysgit, ale są dwie wady:

  • Łącza symboliczne są dostępne tylko w systemie Windows Vista i nowszych (nie powinno to stanowić problemu w 2011 r., A jednak tak jest ...), ponieważ starsze wersje obsługują tylko połączenia katalogów.
  • (duży) Microsoft uważa, że ​​dowiązania symboliczne stanowią zagrożenie bezpieczeństwa, dlatego domyślnie mogą je tworzyć tylko administratorzy. Będziesz musiał podnieść uprawnienia procesu git lub użyć fstool, aby zmienić to zachowanie na każdej maszynie, na której pracujesz.

Przeprowadziłem szybkie wyszukiwanie i nad tym trwają prace, patrz problem 224 .

djs
źródło
2
Aktualizacja: z powyższych powodów problem został zamknięty jako wontfix. Dyskusja wskazuje, że poprawka może zostać zaakceptowana przy dodatkowej pracy nad łatką (powiedzmy, używając dowiązań symbolicznych tylko wtedy, gdy działają).
Blaisorblade,
2
A.) Obecnie msysgit w ogóle nie obsługuje dowiązań symbolicznych - więc dlaczego nie wykryje „oh jesteś na Vista z NTFS, pozwól mi użyć dowiązań symbolicznych” lub „och, masz system operacyjny obsługujący połączenia z NTFS, pozwól, że użyję tych ”lub„ och, jesteś na Windows 98 / fat32, pozwól mi wrócić do tego, że nie mam tej funkcji i zamiast tego dam ci ostrzeżenie! ” a następnie B.) Prawie wszyscy deweloperzy Microsoft. narzędzia nie działają poprawnie (przynajmniej nie dla wszystkich ich funkcji), jeśli nie uruchomisz ich jako administrator - wszyscy w IT wiedzą, że programiści muszą być administratorami na własnych urządzeniach.
BrainSlugs83
1
Chociaż uruchamiam niektóre komputery na koncie administratora, nie przestrzegam tej filozofii na moim komputerze programistycznym. Zawsze działam jako zwykły użytkownik z włączoną funkcją UAC. Trzymam osobną konsolę otwartą dla operacji wymagających podwyższonych uprawnień. Jeśli chodzi o wdrożenie tego, sprowadza się to do kogoś (takiego jak ty) zgłaszającego się do jego wdrożenia. Programiści msysgit nie są znani z działalności charytatywnej ...
djs
@djs Użytkownik musi otworzyć wiersz polecenia za pomocą polecenia „Uruchom jako administrator”. Jest prawie dosłownie uruchomiony jako Administrator, który całkowicie zmienia środowisko. Nie ma sposobu na uruchomienie „mklink / d” jako użytkownik, który również należy do grupy administratorów. Nie wyświetli monit UAC. Zawsze zawiedzie. Działa tylko na dwa sposoby: dosłownie jako użytkownik Administrator (czasownik RunAs) lub użytkownik niebędący administratorem ze zmianą zasad grupy. Połączenia powinny być domyślne i powinny być rozpoznawane przez wszystkie narzędzia. „Zagrożenie bezpieczeństwa” polega na tym, że dowiązania symboliczne w systemie Windows mogą „przekierowywać” udziały SMB. To jest bolesne i okrutne.
Andrew T Finnell,
8
Ogłoszony w grudniu 2016 r. Symlinks w Windows 10 nie jest już działaniem administratora. blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/…
Dennis
16

tak więc, jak zmieniło się w GIT od czasu opublikowania wielu odpowiedzi tutaj, są prawidłowe instrukcje, aby linki symboliczne działały poprawnie w systemie Windows od

SIERPIEŃ 2018


1. Upewnij się, że git jest zainstalowany z obsługą dowiązań symbolicznych

Podczas instalacji gita w systemie Windows

2. Powiedz Bashowi, aby tworzył dowiązania twarde zamiast dowiązań symbolicznych

EDYCJA - (folder git) /etc/bash.bashrc

DODAJ DO DOLNEJ - MSYS=winsymlinks:nativestrict

3. Ustaw git config, aby używał dowiązań symbolicznych

git config core.symlinks true

lub

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

UWAGA: Próbowałem dodać to do globalnej konfiguracji git iw tej chwili nie działa dla mnie, więc polecam dodanie tego do każdego repo ...

4. wyciągnij repozytorium

UWAGA: Jeśli nie włączyłeś trybu programisty w najnowszej wersji systemu Windows 10, musisz uruchomić bash jako administrator, aby utworzyć dowiązania symboliczne

5. Zresetuj wszystkie dowiązania symboliczne (opcjonalnie) Jeśli masz istniejące repozytorium lub korzystasz z submodułów, może się okazać, że dowiązania symboliczne nie są tworzone poprawnie, więc aby odświeżyć wszystkie dowiązania symboliczne w repozytorium, możesz uruchomić te polecenia.

find -type l -delete
git reset --hard

UWAGA: spowoduje to zresetowanie wszelkich zmian od ostatniego zatwierdzenia, więc upewnij się, że dokonałeś pierwszego

Szymon
źródło
15

Krótka odpowiedź: są teraz ładnie obsługiwane, jeśli możesz włączyć tryb programisty.

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

Teraz w Windows 10 Creators Update użytkownik (z uprawnieniami administratora) może najpierw włączyć tryb programisty, a następnie każdy użytkownik na komputerze może uruchomić polecenie mklink bez podnoszenia konsoli wiersza poleceń.

Co spowodowało tę zmianę? Dostępność i użycie dowiązań symbolicznych to wielka sprawa dla współczesnych programistów:

Wiele popularnych narzędzi programistycznych, takich jak git i menedżery pakietów, np. Npm, rozpoznaje i utrzymuje dowiązania symboliczne odpowiednio podczas tworzenia repozytoriów lub pakietów. Gdy te repozytoria lub pakiety są następnie przywracane gdzie indziej, dowiązania symboliczne są również przywracane, zapewniając, że miejsce na dysku (i czas użytkownika) nie zostanie zmarnowane.

Łatwo przeoczyć wszystkie pozostałe ogłoszenia „Aktualizacja twórcy”, ale jeśli włączysz tryb programisty, możesz tworzyć dowiązania symboliczne bez podwyższonych uprawnień. Być może będziesz musiał ponownie zainstalować git i upewnić się, że obsługa dowiązań symbolicznych jest włączona, ponieważ nie jest to domyślnie.

Łącza symboliczne nie są domyślnie włączone

Orangutech
źródło
1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmentto kanoniczny sposób przypisywania praw użytkowników, takich jak SeCreateSymbolicLinki znajomi, na całe wieki. Inne niż ntrights.exez zestawu zasobów lub programu PowerShell ...
0xC0000022L
11

Odpowiedź 2020

  1. Włącz „tryb programisty” w systemie Windows 10 - daje mklink uprawnienia
  2. Upewnij się, że dowiązania symboliczne są włączone w git
    • git config --global core.symlinks true
    • lub zaznacz pole wyboru podczas instalowania msysgit

Zmiana gałęzi wymusi odtworzenie brakujących dowiązań symbolicznych.

Uważaj, obsługa Symlinks w systemie Windows w przypadku niektórych innych klientów Git nie jest pełna. Zwłaszcza GitKraken.

Cameron Tacklind
źródło
Wszystkie moje lokalne repozytoria mają core.symlinks = false, co zastąpiłoby twoje rozwiązanie. Masz pojęcie, co automatycznie wytwarza tę konfigurację lokalną? Być może instalujesz Git dla Windows bez zaznaczenia pola wyboru?
gravidThoughts
@gravidThoughts, których klientów git zainstalowałeś? Może robi to jakieś oprzyrządowanie? Czy to prawda na świeżym klonie?
Cameron Tacklind
10

Sugeruję, abyś nie używał dowiązań symbolicznych w repozytorium ”. Przechowuj rzeczywistą treść w repozytorium, a następnie umieść dowiązania symboliczne na zewnątrz repozytorium, które wskazują na treść.

Powiedzmy, że używasz repozytorium, aby porównać hosting swojej witryny na * nix z hostingiem na win. Przechowuj zawartość w swoim repozytorium ”, powiedzmy, /httpRepoContenta c:\httpRepoContentten folder jest synchronizowany przez GIT, SVN itp.

Następnie zastąp folder zawartości serwera WWW ( /var/wwwic:\program files\web server\www {nazwy nie mają tak naprawdę znaczenia, edytuj, jeśli musisz}) symbolicznym łączem do treści w repozytorium ”. Serwery WWW zobaczą zawartość jako „we właściwym” miejscu, ale możesz użyć kontroli źródła.

Jednakże, jeśli musisz użyć dowiązań symbolicznych w repo ', musisz spojrzeć na coś w rodzaju skryptu zatwierdzania przed / po zatwierdzeniu. Wiem, że możesz ich używać do robienia rzeczy, takich jak na przykład analizowanie plików kodu za pomocą formatera, więc powinna istnieć możliwość konwersji dowiązań symbolicznych między platformami.

jeśli ktoś zna dobre miejsce, aby dowiedzieć się, jak wykonywać te skrypty dla typowych kontrolek źródłowych, SVN GIT MG, to proszę dodać komentarz.

thecoshman
źródło
Na koniec wybrałem to podejście, aby utworzyć folder z dowiązaniem symbolicznym i utworzyć dowiązania symboliczne do miejsca, w którym kiedyś znajdował się oryginalny plik. Inne podejście nie zadziałało nawet po zmianie ustawienia .git / config core.symlinks = true. Tylko plik dowiązania symbolicznego został zapisany w repozytorium, a nie dane. Miał również problemy ze znacznikami czasu folderu w dowiązaniu symbolicznym, więc git bash nigdy nie widział, gdy plik zmienia się w folderze.
Jajka
@ Jajka, to, co mogłeś zobaczyć, to chyba to, że link był w repozytorium, więc git go zapisał. Problemem jest jednak to, że cel był poza repozytorium, a git nie podąża za linkiem do danych docelowych. W Linuksie masz typ linku, który by do tego zadziałał, w zasadzie masz dwie ścieżki do tych samych danych przechowywanych na dysku; Mam wrażenie, że nowe okna mogą to teraz zrobić. Tak czy inaczej, nadal nie sądzę, że zrobi to, co ludzie chcą.
thecoshman
@ thecoshman To nie jest rozwiązanie, ale obejście. Czasami jednak nie jest to opcja. Mam repozytorium z aneksem git i całą jego architekturą działa z powodu dowiązań symbolicznych.
marcelo.guedes
8

Dla tych, którzy używają CygWin na Vista, Win7 lub nowszym, natywne gitpolecenie może tworzyć „właściwe” dowiązania symboliczne rozpoznawane przez aplikacje Windows, takie jak Android Studio . Musisz tylko ustawić CYGWINzmienną środowiskową, aby zawierała winsymlinks:nativelub winsymlinks:nativestrictjako taka:

export CYGWIN="$CYGWIN winsymlinks:native"

Wadą tego (i istotną w tym przypadku) jest to, że powłoka CygWin musi być „Uruchomiona jako administrator”, aby mieć uprawnienia systemu operacyjnego wymagane do tworzenia tego rodzaju dowiązań symbolicznych. Jednak po ich utworzeniu nie są wymagane specjalne uprawnienia do korzystania z nich. O ile nie zostaną one zmienione w repozytorium przez innego programistę, od tej gitpory będzie działać poprawnie z normalnymi uprawnieniami użytkownika.

Osobiście używam tego tylko do dowiązań symbolicznych, które są nawigowane przez aplikacje Windows (tj. Nie-CygWin) z powodu tej dodatkowej trudności.

Aby uzyskać więcej informacji na temat tej opcji, zobacz to SO pytanie: Jak zrobić symboliczne łącze z cygwin w Windows 7

Brian White
źródło
6

Oto skrypt wsadowy do konwersji dowiązań symbolicznych w repozytorium, tylko dla plików, na podstawie odpowiedzi Josha Lee. Skrypt z dodatkowym sprawdzeniem uprawnień administratora znajduje się na stronie 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
źródło
Nieudokumentowana odpowiedź jest naprawdę mało przydatna, gdy istnieją już tak długie i pełne odpowiedzi.
Xennex81
4

Cały czas korzystam z łączy sym między katalogiem głównym dokumentu a katalogiem git repo. Lubię je rozdzielać. W systemie Windows używam opcji mklink / j. Wygląda na to, że skrzyżowanie pozwala gitowi zachowywać się normalnie:

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

na przykład:

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

mmv_sat
źródło
2
Bądź bardzo ostrożny z Eksploratorem Windows i połączeniami; nie rozróżnia skrzyżowań od lokalizacji bazowej, a usunięcie powróci do celu i usunie jego zawartość, natomiast usunięcie dowiązania symbolicznego po prostu usunie dowiązanie symboliczne. Tylko pułapka na nieostrożnych.
Lawrence Dol
5
Właściwie właśnie przetestowałem to na najnowszym Windows7 i już tego nie robi, więc obsługa skrzyżowań została poprawiona w ciągu ostatnich kilku lat.
Lawrence Dol
3

Szukałem łatwego rozwiązania problemu z unixowymi dowiązaniami symbolicznymi w systemie Windows. Dziękujemy bardzo za powyższe aliasy Git. Istnieje jedna drobna optymalizacja, którą można wykonać w linkach rm-symlink, aby nie usuwała plików w folderze docelowym w przypadku przypadkowego uruchomienia aliasu po raz drugi. Zwróć uwagę na nowy warunek if w pętli, aby upewnić się, że plik nie jest już linkiem do katalogu przed uruchomieniem logiki.

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
źródło
2

Jedną z prostych sztuczek, których używamy, jest po prostu połączenie git add --alldwa razy z rzędu.

Na przykład nasze wywołania skryptów zatwierdzania systemu Windows 7:

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

Pierwszy dodatek traktuje link jako tekst i dodaje foldery do usunięcia.

Drugi dodatek poprawnie przegląda link i cofa usunięcie poprzez przywrócenie plików.

Jest mniej elegancki niż niektóre inne proponowane rozwiązania, ale jest prostą poprawką do niektórych naszych starszych środowisk, w których dodano dowiązania symboliczne.

Mike Panoff
źródło