Git Symlinks di Windows

246

Pengembang kami menggunakan campuran OS berbasis Windows dan Unix. Oleh karena itu, symlink yang dibuat pada mesin Unix menjadi masalah bagi pengembang Windows. Di windows (msysgit), symlink dikonversi ke file teks dengan path ke file yang ditunjuknya. Sebaliknya, saya ingin mengubah symlink menjadi symlink Windows yang sebenarnya.

Solusi ( diperbarui ) yang harus saya lakukan adalah:

  • Tulis skrip pasca-checkout yang secara rekursif akan mencari file teks "symlink".
  • Ganti dengan windows symlink (menggunakan mklink) dengan nama dan ekstensi yang sama dengan dummy "symlink"
  • Abaikan symlink windows ini dengan menambahkan entri ke .git / info / exclude

Saya belum menerapkan ini, tetapi saya percaya ini adalah pendekatan yang solid untuk masalah ini.

Pertanyaan:

  1. Apa, jika ada, kerugian yang Anda lihat dari pendekatan ini?
  2. Apakah skrip pasca checkout ini bahkan dapat diterapkan? yaitu bisakah saya mencari file "symlink" dummy git secara rekursif?
  3. Adakah yang sudah mengerjakan skrip seperti itu?
Ken Hirakawa
sumber
3
Meskipun Git mendukung symlink, saya sangat merekomendasikan untuk tidak menyimpannya sebagai tautan di repositori Anda, terutama jika Anda juga bekerja dengan kode itu di Windows.
Greg Hewgill
2
@ Greg Hewgill - Saya sangat setuju dengan Anda. Sayangnya, sifat dasar kode kami memerlukan symlink ... jadi menghapusnya bukan pilihan bagi kami.
Ken Hirakawa
12
Anda juga bisa bertanya pada milis msysgit mengapa mereka tidak mengimplementasikannya seperti itu sejak awal.
drizzd
8
@GregHewgill kenapa tidak? Windows mendukung kedua tautan simbolik dan persimpangan - ini benar-benar tampak seperti fitur yang hilang di versi windows Git bagi saya ...
BrainSlugs83
6
Dengan "Mode Pengembang" diaktifkan di Windows 10, membuat symlink tidak memerlukan hak Administrator! (Yang lain berkomentar lebih banyak tentang jawaban yang kurang terpilih, tetapi saya tidak melihatnya. Berharap komentar ini lebih terlihat oleh pembaca masa depan.)
Dave Pascua

Jawaban:

105

Anda dapat menemukan symlink dengan mencari file yang memiliki mode 120000, mungkin dengan perintah ini:

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

Setelah Anda mengganti tautan, saya sarankan menandai mereka sebagai tidak berubah dengan git update-index --assume-unchanged, daripada mendaftar di .git/info/exclude.

Josh Lee
sumber
2
Saya harus mengganti awk dengan gawk untuk msysgit, tetapi jika tidak berfungsi dengan baik. Terima kasih!
Ken Hirakawa
6
helo ken. maukah Anda berbagi skrip yang memeriksa file teks symlink dan menggantinya dengan symlink di windows menggunakan mklink. sementara ini benar-benar bekerja untuk kita bagian --assume-tidak berubah tidak. pada beralih ke git cabang lain mengatakan file symlink diubah dan perlu dilakukan terlebih dahulu, sementara status git mengatakan tidak ada perubahan..setiap gagasan?
joreg
6
Ini adalah PowerShell yang baru saja saya kumpulkan - gist.github.com/ferventcoder/7995025
ferventcoder
3
@ flungo Ada lebih banyak cara portabel untuk mencetak kolom keempat daripada menggunakan GNU awk. Misalnya: git ls-files -s | grep '^12' | cut -f2(kolom pembatas-tab kedua; kolom lainnya dibatasi-ruang)
Zenexer
1
Satu liner untuk Cygwin / bash untuk menandai semua symlink tidak berubah:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden
187

Saya menanyakan pertanyaan yang persis sama beberapa waktu lalu (tidak di sini, secara umum) dan akhirnya menemukan solusi yang sangat mirip dengan proposisi OP. Pertama saya akan memberikan jawaban langsung untuk pertanyaan 1 2 & 3, dan kemudian saya akan memposting solusi yang akhirnya saya gunakan.

  1. Memang ada beberapa kelemahan pada solusi yang diusulkan, terutama mengenai peningkatan potensi polusi repositori, atau secara tidak sengaja menambahkan file duplikat saat mereka berada di negara "Windows symlink" mereka. (Lebih lanjut tentang ini di bawah "batasan" di bawah.)
  2. Ya, skrip pasca-checkout dapat diterapkan! Mungkin bukan sebagai postal literalgit checkout step , tetapi solusi di bawah ini telah cukup memenuhi kebutuhan saya sehingga script post-checkout literal tidak diperlukan.
  3. Iya!

Solusinya:

Pengembang kami berada dalam situasi yang sama dengan OP: campuran Windows dan host yang mirip Unix, repositori, dan submodula dengan banyak git symlink, dan belum ada dukungan asli (dalam versi) dari MsysGit versi rilis untuk menangani symlink ini dengan cerdas pada host Windows .

Terima kasih kepada Josh Lee karena menunjukkan fakta bahwa git melakukan symlink dengan filemode khusus 120000. Dengan informasi ini dimungkinkan untuk menambahkan beberapa alias git yang memungkinkan pembuatan dan manipulasi symlink git pada host Windows.

  1. Membuat symlink git di 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
    )"
    

    Penggunaan:, di git add-symlink <source_file_or_dir> <target_symlink>mana argumen yang terkait dengan file sumber atau direktori harus berupa path relatif ke symlink target. Anda dapat menggunakan alias ini dengan cara yang sama seperti yang biasa Anda gunakan ln.

    Misalnya, pohon repositori:

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

    Dapat dibuat di Windows sebagai berikut:

    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. Mengganti symlink git dengan sambungan hardlink NTFS +

    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.
    

    Pemakaian:

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

    Alias ​​ini dapat menghapus symlink git satu-per-satu atau sekaligus sekaligus. Symlinks akan diganti dengan hardlink NTFS (dalam hal file) atau persimpangan NTFS (dalam kasus direktori). Manfaat menggunakan hardlinks + junctions atas symlink NTFS "true" adalah bahwa izin UAC yang ditinggikan tidak diperlukan untuk membuatnya.

    Untuk menghapus symlink dari submodules, cukup gunakan dukungan bawaan git untuk mengulanginya:

    git submodule foreach --recursive git rm-symlinks
    

    Tapi, untuk setiap aksi drastis seperti ini, pembalikan bagus untuk dilakukan ...

  3. Mengembalikan git symlink pada 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'
    

    Penggunaan git checkout-symlinks [symlink] [symlink] [...]:, yang dibatalkan git rm-symlinks, secara efektif mengembalikan repositori ke keadaan aslinya (kecuali untuk perubahan Anda, yang seharusnya tetap utuh).

    Dan untuk submodula:

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

    • Direktori / file / symlink dengan spasi di jalurnya harus berfungsi. Tetapi tab atau baris baru? YMMV ... (Maksud saya: jangan lakukan itu, karena itu tidak akan berhasil.)

    • Jika Anda atau orang lain lupa git checkout-symlinkssebelum melakukan sesuatu dengan konsekuensi yang berpotensi meluas seperti git add -A, repositori lokal dapat berakhir dengan keadaan tercemar.

      Menggunakan "contoh repo" kami dari sebelumnya:

      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
      #
      

      Aduh ...

      Untuk alasan ini, senang untuk memasukkan alias ini sebagai langkah untuk melakukan untuk pengguna Windows sebelum dan sesudah membangun proyek, daripada setelah checkout atau sebelum mendorong. Tetapi setiap situasi berbeda. Alias ​​ini telah cukup berguna bagi saya sehingga solusi pasca-checkout yang sebenarnya belum diperlukan.

Semoga itu bisa membantu!

Referensi:

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

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

Pembaruan Terakhir: 2019-03-13

  • Kepatuhan POSIX (well, kecuali untuk mklinkpanggilan itu, tentu saja) - tidak ada lagi Bashism !
  • Direktori dan file dengan spasi di dalamnya didukung.
  • Kode status keluar nol dan tidak nol (masing-masing untuk mengkomunikasikan keberhasilan / kegagalan perintah yang diminta) sekarang disimpan / dikembalikan dengan benar.
  • The add-symlinkalias sekarang bekerja lebih seperti ln (1) dan dapat digunakan dari direktori dalam repositori, bukan hanya repositori direktori root.
  • The rm-symlinkalias (tunggal) telah digantikan oleh rm-symlinksalias (jamak), yang sekarang menerima beberapa argumen (atau tidak ada argumen sama sekali, yang menemukan semua symlink seluruh repositori, seperti sebelumnya) untuk selektif mengubah symlink git ke NTFS hardlinks + persimpangan .
  • The checkout-symlinksalias juga telah diperbarui untuk menerima beberapa argumen (atau tidak sama sekali, == semuanya) untuk pembalikan selektif dari transformasi tersebut.

Catatan Akhir: Sementara saya menguji pemuatan dan menjalankan alias ini menggunakan Bash 3.2 (dan bahkan 3.1) bagi mereka yang mungkin masih terjebak pada versi kuno untuk sejumlah alasan, perlu diketahui bahwa versi yang sudah tua ini terkenal karena parsernya bug. Jika Anda mengalami masalah saat mencoba memasang alias ini, hal pertama yang harus Anda perhatikan adalah memutakhirkan shell Anda (untuk Bash, periksa versinya dengan CTRL + X, CTRL + V). Atau, jika Anda mencoba menginstalnya dengan menempelkannya ke emulator terminal Anda, Anda mungkin lebih beruntung menyisipkannya ke dalam file dan sumbernya, misalnya sebagai

. ./git-win-symlinks.sh

Semoga berhasil!

Mark G.
sumber
dapatkah Anda melihatnya di sini? stackoverflow.com/questions/21403772/…
Goofy
ini adalah skrip yang hebat dan luar biasa, tetapi adakah alasan mengapa ini harus membubuhkan kata "git" secara acak di akhir beberapa file saya yang saya buat dengan git add-symlink?
Peter Turner
Juga, jika nama file Anda mengandung "-h" Anda mendapatkan penggunaannya. Masih sangat bermanfaat!
Peter Turner
git add-symlinkResep Anda sangat berharga bagi saya. Terimakasih banyak.
Dan Lenski
1
Apakah ada cara untuk secara otomatis menjalankan skrip ini menggunakan kait?
ARF
74

Versi terbaru dari git scm (testet 2.11.1) memungkinkan untuk mengaktifkan tautan simbolik. Tetapi Anda harus mengkloning repositori dengan symlink lagi git clone -c core.symlinks=true <URL>. Anda perlu menjalankan perintah ini dengan hak administrator. Dimungkinkan juga untuk membuat symlink di Windows dengan mklink. Lihatlah wiki .

masukkan deskripsi gambar di sini

sirlunchalot
sumber
1
Ini tidak berhasil untuk saya. Saya menginstal ulang git untuk Windows, ingat untuk memeriksa kotak centang symlink dan mengkloning proyek saya lagi. tslint.jsonFile saya yang mereferensikan file dalam direktori induk masih berisi ../tslint.json. Sayang sekali, karena ini benar-benar tampak seperti yang termudah dari semua solusi yang diusulkan di sana.
Jan Aagaard
8
@JanAagaard Anda harus mengkloningnya seperti ini: git clone -c core.symlinks=true <URL> Dan pada Windows Anda harus menjalankannya dengan hak administrator.
sirlunchalot
6
@ARF "Luncurkan gpedit.msc (yaitu editor kebijakan grup) dan tambahkan akun ke konfigurasi Komputer \ Pengaturan Windows \ Pengaturan Keamanan \ Kebijakan Lokal \ Penugasan Hak Pengguna \ Buat tautan simbolik."
sirlunchalot
2
@sirlunchalot Terima kasih atas bantuannya. Sejak itu saya menyadari bahwa masalah saya adalah bahwa pengguna saya adalah bagian dari grup Administrator dan bahwa properti ini tidak berpengaruh bagi pengguna ini. Mereka membutuhkan ketinggian UAC yang tidak dilakukan git.
ARF
9
Hak admin tidak diperlukan dalam "Mode Pengembang" di Pembaruan Creator Windows 10. Terima kasih @dennis dalam komentarnya .
Dominik
16

Seharusnya diimplementasikan dalam msysgit, tetapi ada dua kelemahan:

  • Tautan simbolis hanya tersedia di Windows Vista dan yang lebih baru (seharusnya tidak menjadi masalah pada 2011, namun itu adalah ...), karena versi yang lebih lama hanya mendukung persimpangan direktori.
  • (yang besar) Microsoft menganggap tautan simbolis sebagai risiko keamanan dan hanya administrator yang dapat membuatnya secara default. Anda harus meningkatkan hak istimewa proses git atau menggunakan fstool untuk mengubah perilaku ini pada setiap mesin yang Anda garap.

Saya melakukan pencarian cepat dan ada pekerjaan yang dilakukan secara aktif mengenai hal ini, lihat edisi 224 .

djs
sumber
2
Pembaruan: karena alasan di atas, masalah ditutup sebagai wontfix. Diskusi menunjukkan bahwa perbaikan dapat diterima dengan beberapa pekerjaan lain di tambalan (katakanlah, menggunakan symlink hanya jika mereka bekerja).
Blaisorblade
2
A.) saat ini msysgit tidak mendukung symlinks sama sekali - jadi mengapa tidak ada yang mendeteksi "oh Anda berada di vista dengan NTFS, izinkan saya menggunakan symlink" atau "oh, Anda menggunakan OS yang mendukung persimpangan dengan NTFS, biarkan saya menggunakan itu ", atau" oh, Anda di windows 98 / fat32, biarkan saya mundur untuk tidak memiliki fitur ini dan memberi Anda peringatan sebagai gantinya! " dan kemudian B.) Hampir semua dev microsoft. alat tidak berfungsi dengan benar (setidaknya tidak untuk semua fitur mereka) jika Anda tidak menjalankannya sebagai administrator - semua orang di IT tahu bahwa pengembang harus admin di kotak mereka sendiri.
BrainSlugs83
1
Meskipun saya menjalankan mesin tertentu di akun Admin, saya tidak mengikuti filosofi itu di mesin pengembangan saya. Saya selalu menjalankan sebagai pengguna biasa dengan UAC-enabled. Saya membuat konsol terpisah tetap terbuka untuk operasi yang membutuhkan hak istimewa yang tinggi. Adapun untuk menerapkan ini, itu turun ke seseorang (seperti Anda) yang secara sukarela menerapkannya. Pengembang msysgit tidak dikenal untuk amal ...
DJ
@ djs Pengguna harus membuka prompt perintah dengan "Jalankan sebagai Administrator." Ini hampir secara harfiah berjalan sebagai Pengguna Administrator yang benar-benar mengubah Lingkungan. Tidak ada cara untuk menjalankan 'mklink / d' sebagai Pengguna yang juga ada di grup Admin. Itu tidak akan meminta UAC. Itu akan selalu gagal. Hanya dua cara kerjanya: Secara harfiah sebagai pengguna Administrator (RunAs Verb), atau Pengguna non-admin dengan perubahan kebijakan grup. Persimpangan harus menjadi default dan harus dikenali oleh semua alat. 'Risiko keamanan' adalah bahwa symlinks di Windows dapat 'mengalihkan' saham SMB. Ini menyakitkan dan kejam.
Andrew T Finnell
8
Diumumkan pada Desember 2016, Symlinks di Windows 10 bukan lagi tindakan Administrator. blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/…
Dennis
16

sehingga hal-hal telah berubah dengan GIT karena banyak jawaban ini diposting di sini adalah instruksi yang benar untuk membuat symlinks bekerja dengan benar di windows pada

AGUSTUS 2018


1. Pastikan git diinstal dengan dukungan symlink

Selama instalasi git di windows

2. Beri tahu Bash untuk membuat hardlink, bukan symlink

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

ADD TO BOTTOM - MSYS=winsymlinks:nativestrict

3. Set git config untuk menggunakan symlink

git config core.symlinks true

atau

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

CATATAN: Saya telah mencoba menambahkan ini ke konfigurasi global git dan saat ini tidak berfungsi untuk saya, jadi saya sarankan menambahkan ini ke setiap repo ...

4. tarik repo

CATATAN: Kecuali jika Anda telah mengaktifkan mode pengembang di versi terbaru Windows 10, Anda harus menjalankan bash sebagai administrator untuk membuat symlink

5. Reset semua Symlinks (opsional) Jika Anda memiliki repo yang ada, atau menggunakan submodul, Anda mungkin menemukan bahwa symlink tidak dibuat dengan benar sehingga untuk menyegarkan semua symlink di repo Anda dapat menjalankan perintah ini.

find -type l -delete
git reset --hard

CATATAN: ini akan mengatur ulang setiap perubahan sejak komit terakhir jadi pastikan Anda telah melakukan komit terlebih dahulu

Simon
sumber
15

Jawaban singkat: Mereka sekarang didukung dengan baik, jika Anda dapat mengaktifkan mode pengembang.

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

Sekarang di Windows 10 Creators Update, pengguna (dengan hak admin) pertama dapat mengaktifkan Mode Pengembang, dan kemudian setiap pengguna pada mesin dapat menjalankan perintah mklink tanpa meninggikan konsol baris perintah.

Apa yang mendorong perubahan ini? Ketersediaan dan penggunaan symlink adalah masalah besar bagi pengembang modern:

Banyak alat pengembangan populer seperti git dan manajer paket seperti npm mengenali dan mempertahankan symlink ketika masing-masing membuat repo atau paket. Ketika repo atau paket tersebut kemudian dipulihkan di tempat lain, symlink juga dipulihkan, memastikan ruang disk (dan waktu pengguna) tidak terbuang.

Mudah diabaikan dengan semua pengumuman lain dari "Pembaruan pencipta", tetapi jika Anda mengaktifkan Mode Pengembang, Anda dapat membuat symlink tanpa hak istimewa yang ditingkatkan. Anda mungkin harus menginstal ulang git dan memastikan dukungan symlink diaktifkan, karena tidak secara default.

Tautan Simbolik tidak diaktifkan secara default

Orangutech
sumber
1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmenttelah menjadi cara kanonik untuk menetapkan hak pengguna seperti SeCreateSymbolicLinkdan teman sejak lama. Selain ntrights.exedari Resource Kit atau PowerShell ...
0xC0000022L
11

Jawaban 2020

  1. Aktifkan "mode Pengembang" di Windows 10 - berikan mklinkizin
  2. Pastikan symlink diaktifkan di git
    • git config --global core.symlinks true
    • atau centang kotak centang ketika menginstal msysgit

Beralih cabang akan memaksa rekreasi symlink yang hilang.

Hati-hati, dukungan untuk Symlinks di Windows dengan beberapa klien Git lainnya tidak lengkap. Khususnya GitKraken.

Cameron Tacklind
sumber
Semua repositori lokal saya memiliki core.symlinks = false yang akan menimpa solusi Anda. Adakah yang tahu apa yang menghasilkan konfigurasi lokal ini secara otomatis? Mungkin menginstal Git untuk Windows tanpa memeriksa kotak centang?
gravidThoughts
@gravidThoughts klien git mana yang telah Anda instal? Mungkin beberapa alat melakukan ini? Apakah ini benar pada klon baru?
Cameron Tacklind
10

Saya sarankan Anda tidak menggunakan symlink di dalam repo '. Simpan konten aktual di dalam repo 'dan kemudian letakkan symlink di luar repo' yang mengarah ke konten.

Jadi katakanlah Anda menggunakan repo 'untuk membandingkan hosting situs Anda di * nix dengan hosting saat menang. Simpan konten dalam repo Anda, katakanlah /httpRepoContentdan c:\httpRepoContentdengan ini menjadi folder yang disinkronkan melalui GIT, SVN dll.

Kemudian, ganti folder konten server web Anda ( /var/wwwdan c:\program files\web server\www{nama tidak terlalu penting, edit jika Anda harus}) dengan tautan simbolis ke konten dalam repo Anda. Server web akan melihat konten yang sebenarnya di tempat yang 'tepat', tetapi Anda bisa menggunakan kontrol sumber Anda.

Namun, jika Anda perlu menggunakan symlinks dalam repo ', Anda perlu melihat sesuatu seperti semacam skrip komit pre / post. Saya tahu Anda dapat menggunakannya untuk melakukan hal-hal, seperti file kode parse melalui formatter misalnya, jadi mungkin untuk mengkonversi symlink antara platform.

jika ada yang tahu tempat yang baik untuk belajar bagaimana melakukan skrip ini untuk kontrol sumber umum, SVN GIT MG, maka silakan tambahkan komentar.

terima kasih
sumber
Pada akhirnya, saya memilih pendekatan ini untuk membuat folder symlink-out dan membuat tautan simbolis ke tempat file asli dulu. Pendekatan lain tidak bekerja bahkan setelah saya mengubah pengaturan .git / config core.symlinks = true. Hanya file tautan simbolis yang disimpan ke repo dan bukan data. Juga memiliki masalah dengan cap waktu folder pada tautan simbolik sehingga git bash tidak pernah melihat ketika file berubah di dalam folder.
Telur
@Eggs apa yang Anda mungkin telah melihat, saya kira, adalah bahwa tautan itu dalam repo, dan git menyimpannya, sederhana. Masalahnya adalah bahwa target berada di luar repo, dan git tidak mengikuti tautan ke data target. Di linux Anda memiliki jenis tautan yang akan berfungsi untuk ini, pada dasarnya mari Anda memiliki dua jalur ke data yang sama yang disimpan di disk; Saya merasa windows yang baru bisa melakukannya sekarang. Bagaimanapun, saya masih tidak berpikir itu akan melakukan apa yang orang inginkan.
thecoshman
@ thecoshman Ini bukan solusi, tetapi solusi. Namun, terkadang ini bukan opsi. Saya memiliki repositori dengan git-annex dan semua arsitekturnya bekerja karena tautan simbolik.
marcelo.guedes
8

Bagi mereka yang menggunakan CygWin di Vista, Win7, atau di atas, gitperintah asli dapat membuat symlink "tepat" yang dikenali oleh aplikasi Windows seperti Android Studio . Anda hanya perlu mengatur CYGWINvariabel lingkungan untuk menyertakan winsymlinks:nativeatau winsymlinks:nativestrictseperti itu:

export CYGWIN="$CYGWIN winsymlinks:native"

Kelemahan dari ini (dan yang penting pada saat itu) adalah bahwa shell CygWin harus "Run as Administrator" agar dapat memiliki izin OS yang diperlukan untuk membuat symlink semacam itu. Namun begitu mereka dibuat, tidak ada izin khusus yang diperlukan untuk menggunakannya . Selama mereka tidak diubah dalam repositori oleh pengembang lain, gitsetelah itu berjalan dengan baik dengan izin pengguna normal.

Secara pribadi, saya menggunakan ini hanya untuk symlink yang dinavigasi oleh aplikasi Windows (yaitu non-CygWin) karena kesulitan tambahan ini.

Untuk informasi lebih lanjut tentang opsi ini, lihat pertanyaan SO ini: Cara membuat tautan simbolis dengan cygwin di Windows 7

Brian White
sumber
6

Berikut ini adalah kumpulan skrip untuk mengonversi symlink di repositori, hanya untuk file, berdasarkan jawaban Josh Lee. Skrip dengan beberapa pemeriksaan tambahan untuk hak administrator ada di 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
sumber
Sebuah jawaban yang tidak berdokumen benar-benar tidak banyak digunakan ketika sudah ada jawaban yang panjang dan verbal.
Xennex81
4

Saya menggunakan tautan sym sepanjang waktu antara direktori root dan direktori git repo saya. Saya suka memisahkan mereka. Di windows saya menggunakan opsi mklink / j. Persimpangan tampaknya membiarkan git berperilaku normal:

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

sebagai contoh:

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

mmv_sat
sumber
2
Berhati-hatilah dengan Windows Explorer dan persimpangan; itu tidak membedakan persimpangan dari lokasi dasar dan penghapusan akan berulang ke target dan menghapus isinya, sedangkan penghapusan symlink hanya akan menghapus symlink. Hanya jebakan bagi yang tidak waspada.
Lawrence Dol
5
Sebenarnya, baru saja menguji ini pada Windows7 terbaru, dan tidak lagi melakukannya, sehingga penanganan persimpangan telah ditingkatkan dalam beberapa tahun terakhir.
Lawrence Dol
3

Saya mencari solusi mudah untuk berurusan dengan tautan simbolik unix di windows. Terima kasih banyak untuk alias Git di atas. Ada satu optimasi kecil yang dapat dilakukan untuk rm-symlinks sehingga tidak menghapus file di folder tujuan seandainya alias dijalankan untuk kedua kalinya secara tidak sengaja. Harap perhatikan kondisi baru jika dalam loop untuk memastikan file belum menjadi tautan ke direktori sebelum logika dijalankan.

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
sumber
2

Salah satu trik sederhana yang kita gunakan adalah menelepon git add --alldua kali berturut-turut.

Misalnya, Windows 7 kami melakukan panggilan skrip:

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

Tambah pertama memperlakukan tautan sebagai teks dan menambahkan folder untuk dihapus.

Penambahan kedua melintasi tautan dengan benar dan membatalkan penghapusan dengan mengembalikan file.

Ini kurang elegan daripada beberapa solusi lain yang diusulkan, tetapi ini adalah perbaikan sederhana untuk beberapa lingkungan lama kami yang ditambahkan symlink.

Mike Panoff
sumber