Git Symlinks ใน Windows


246

นักพัฒนาของเราใช้ทั้งระบบปฏิบัติการ Windows และ Unix ดังนั้น symlink ที่สร้างขึ้นบนเครื่อง Unix จึงเป็นปัญหาสำหรับนักพัฒนา Windows ใน windows (msysgit) symlink จะถูกแปลงเป็นไฟล์ข้อความที่มีพา ธ ไปยังไฟล์ที่ชี้ไป ฉันต้องการแปลง symlink ให้เป็น Windows symlink จริงแทน

โซลูชัน( อัปเดต ) ที่ฉันมีอยู่คือ:

  • เขียนสคริปต์หลังการชำระเงินซึ่งจะค้นหาไฟล์ข้อความ "symlink" ซ้ำ ๆ
  • แทนที่ด้วย windows symlink (โดยใช้ mklink) ด้วยชื่อและนามสกุลเดียวกันกับ dummy "symlink"
  • ละเว้นหน้าต่าง symlink โดยเพิ่มรายการใน. git / info / แยก

ฉันไม่ได้ใช้สิ่งนี้ แต่ฉันเชื่อว่านี่เป็นแนวทางที่ชัดเจนสำหรับปัญหานี้

คำถาม:

  1. คุณเห็นว่ามีข้อเสียอะไรหากมีวิธีการนี้
  2. สคริปต์หลังการชำระเงินนี้สามารถใช้งานได้หรือไม่ คือฉันจะวนซ้ำค้นหาไฟล์ "symlink" git ที่สร้างขึ้นได้หรือไม่
  3. มีใครทำงานกับสคริปต์นี้บ้างไหม?

3
ถึงแม้ว่า Git รองรับ symlink ฉันขอแนะนำอย่างยิ่งให้คุณไม่ควรเก็บไว้เป็นลิงก์ในที่เก็บของคุณโดยเฉพาะถ้าคุณทำงานกับรหัสนั้นบน Windows
Greg Hewgill

2
@ Greg Hewgill - ฉันเห็นด้วยกับคุณโดยสิ้นเชิง น่าเสียดายที่ลักษณะของฐานรหัสของเรานั้นต้องการ symlink ... ดังนั้นการลบออกจึงไม่ใช่ตัวเลือกสำหรับเรา
Ken Hirakawa

12
คุณสามารถถามรายชื่อส่งเมล msysgit ได้ว่าทำไมพวกเขาถึงไม่ใช้มันในตอนแรก
drizzd

8
@ GregHewgill ทำไมไม่? Windows รองรับทั้งการเชื่อมโยงสัญลักษณ์และทางแยก - นี่เป็นคุณสมบัติที่ขาดหายไปใน Git เวอร์ชัน windows สำหรับฉัน ...
BrainSlugs83

6
เมื่อเปิดใช้งาน "โหมดผู้พัฒนา" ใน Windows 10 การสร้าง symlink ไม่จำเป็นต้องมีสิทธิ์ผู้ดูแลระบบ! (คนอื่น ๆ ให้ความเห็นกับคำตอบที่ได้รับการโหวตน้อย แต่ฉันไม่เห็นพวกเขาหวังว่าความคิดเห็นนี้จะปรากฏต่อผู้อ่านในอนาคต)
Dave Pascua

คำตอบ:


105

คุณสามารถค้นหา symlink ได้โดยค้นหาไฟล์ที่มีโหมด120000อาจใช้คำสั่งนี้:

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

เมื่อคุณเปลี่ยนการเชื่อมโยงไปผมจะแนะนำให้พวกเขาเป็นเครื่องหมายการเปลี่ยนแปลงที่มีมากกว่ารายชื่อพวกเขาในgit update-index --assume-unchanged.git/info/exclude


2
ฉันต้องเปลี่ยน awk ด้วยเพ่งพิศเพื่อ msysgit แต่อย่างอื่นมันทำงานได้อย่างสมบูรณ์ ขอบคุณ!
Ken Hirakawa

6
เฮเลนเคน คุณต้องการแบ่งปันสคริปต์ของคุณที่จะตรวจสอบไฟล์ข้อความ symlink และแทนที่ด้วย symlink บน windows โดยใช้ mklink ในขณะนี้ใช้งานได้จริงสำหรับเรา - สมมติว่าส่วนที่ไม่เปลี่ยนแปลงไม่ได้ ในการเปลี่ยนไปใช้ git สาขาอื่นกล่าวว่าไฟล์ symlink มีการเปลี่ยนแปลงและจำเป็นต้องได้รับการยอมรับก่อนในขณะที่สถานะ git บอกว่าไม่มีการเปลี่ยนแปลง .. ความคิดใด ๆ
joreg

6
นี่คือ PowerShell อันที่ฉันเพิ่งรวบรวมไว้ - gist.github.com/ferventcoder/7995025
ferventcoder

3
@flungo มีวิธีพกพาในการพิมพ์คอลัมน์ที่สี่มากกว่าการใช้ GNU awk ตัวอย่างเช่น: git ls-files -s | grep '^12' | cut -f2(คอลัมน์ที่คั่นด้วยแท็บที่สองคอลัมน์อื่น ๆ ที่มีการคั่นด้วยช่องว่าง)
Zenexer

1
หนึ่งซับสำหรับ Cygwin / bash เพื่อทำเครื่องหมาย symlinks ทั้งหมดไม่เปลี่ยนแปลง:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden

187

ฉันถามคำถามเดียวกันนี้สักครู่ (ไม่ใช่ที่นี่โดยทั่วไป) และจบลงด้วยการหาทางออกที่คล้ายกันกับข้อเสนอของ OP ก่อนอื่นฉันจะให้คำตอบสำหรับคำถามที่ 1 2 & 3 โดยตรงจากนั้นฉันจะโพสต์โซลูชันที่ฉันใช้

  1. มีข้อเสียอยู่เล็กน้อยเกี่ยวกับโซลูชันที่เสนอส่วนใหญ่เกี่ยวกับศักยภาพที่เพิ่มขึ้นสำหรับมลภาวะในที่เก็บหรือโดยบังเอิญเพิ่มไฟล์ที่ซ้ำกันในขณะที่อยู่ในสถานะ "Windows symlink" (เพิ่มเติมเกี่ยวกับสิ่งนี้ภายใต้ "ข้อ จำกัด " ด้านล่าง)
  2. ใช่สคริปต์โพสต์เช็คเอาต์สามารถใช้งานได้! อาจจะไม่เป็นโพสต์ตามตัวอักษร -git checkoutแต่วิธีการแก้ปัญหาด้านล่างตรงกับความต้องการของฉันดีพอที่สคริปต์การชำระเงินหลังแท้จริงไม่จำเป็น
  3. ใช่

การแก้ไขปัญหา:

นักพัฒนาของเราอยู่ในสถานการณ์เดียวกันกับ OP: การผสมผสานระหว่างโฮสต์ของ Windows และ Unix เช่นที่เก็บและ submodules ที่มี symlinks git จำนวนมากและยังไม่มีการสนับสนุนดั้งเดิมใน MsysGit รุ่นที่วางจำหน่ายสำหรับการจัดการ symlink เหล่านี้บนโฮสต์ของ Windows .

ขอบคุณ Josh Lee ที่ชี้ให้เห็นความจริงที่ว่าคอมไพล์ทำ symlink 120000ด้วยไฟล์โหมดพิเศษ ด้วยข้อมูลนี้จึงเป็นไปได้ที่จะเพิ่มนามแฝง git สองสามตัวที่อนุญาตให้สร้างและจัดการกับ symlink git บนโฮสต์ Windows

  1. การสร้าง git symlink บน 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
    )"
    

    การใช้งาน: git add-symlink <source_file_or_dir> <target_symlink>โดยที่อาร์กิวเมนต์ที่สอดคล้องกับไฟล์ต้นฉบับหรือไดเรกทอรีจะต้องอยู่ในรูปแบบของเส้นทางที่สัมพันธ์กับ symlink เป้าหมาย lnคุณสามารถใช้นามแฝงนี้แบบเดียวกับที่คุณตามปกติจะใช้

    เช่นต้นไม้ที่เก็บ:

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

    สามารถสร้างได้บน Windows ดังนี้:

    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. การแทนที่ symphony git ด้วยฮาร์ดลิงก์ NTFS + 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.
    

    การใช้งาน:

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

    นามแฝงนี้สามารถลบ git symlink ทีละตัวหรือทั้งหมดในคราวเดียวในบัดดล Symlinks จะถูกแทนที่ด้วยฮาร์ดลิงก์ NTFS (ในกรณีของไฟล์) หรือทางแยก NTFS (ในกรณีของไดเรกทอรี) ประโยชน์ของการใช้ hardlinks + junctions ผ่าน "จริง" ของ symbian NTFS ก็คือไม่ต้องมีการเพิ่มสิทธิ์ UAC เพื่อให้สามารถสร้างได้

    ในการลบ symlink ออกจาก submodules เพียงแค่ใช้การสนับสนุนในตัวของ git สำหรับการวนซ้ำมัน:

    git submodule foreach --recursive git rm-symlinks
    

    แต่สำหรับทุกการกระทำที่รุนแรงเช่นนี้การกลับรายการเป็นเรื่องดีที่มี ...

  3. การกู้คืนคอมไพล์ git บน 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'
    

    การใช้งาน: git checkout-symlinks [symlink] [symlink] [...]ซึ่งยกเลิกgit rm-symlinksการกู้คืนพื้นที่เก็บข้อมูลอย่างมีประสิทธิภาพสู่สภาวะปกติ (ยกเว้นการเปลี่ยนแปลงของคุณซึ่งควรทำคงสภาพเหมือนเดิม)

    และสำหรับ submodules:

    git submodule foreach --recursive git checkout-symlinks
    
  4. ข้อ จำกัด :

    • ไดเร็กทอรี / files / symlink ที่มีช่องว่างในพา ธ ควรทำงานได้ แต่แท็บหรือบรรทัดใหม่ YMMV … (โดยสิ่งนี้ฉันหมายถึง: อย่าทำอย่างนั้นเพราะมันจะไม่ทำงาน)

    • หากตัวคุณเองหรือคนอื่น ๆ ลืมgit checkout-symlinksก่อนที่จะทำอะไรบางอย่างที่อาจส่งผลกว้างเช่นgit add -Aที่เก็บข้อมูลในพื้นที่อาจจบลงด้วยการเสีย

      ใช้ "repo ตัวอย่าง" ของเราก่อนหน้านี้:

      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
      #
      

      อ๊ะ ...

      ด้วยเหตุนี้จึงเป็นการดีที่จะรวมชื่อแทนเหล่านี้เป็นขั้นตอนในการดำเนินการสำหรับผู้ใช้ Windows ก่อนและหลังการสร้างโครงการมากกว่าหลังจากเช็คเอาต์หรือก่อนผลักดัน แต่ในแต่ละสถานการณ์นั้นแตกต่างกัน นามแฝงเหล่านี้มีประโยชน์พอสำหรับฉันแล้วว่าโซลูชันการลงทะเบียนชำระเงินหลังจริงไม่จำเป็น

หวังว่าจะช่วย!

อ้างอิง:

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

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

ปรับปรุงล่าสุด: 2019-03-13

  • การปฏิบัติตาม POSIX (ดียกเว้นการmklinkโทรเหล่านั้นแน่นอน) - ไม่มีBashismsอีกต่อไป !
  • สนับสนุนไดเรกทอรีและไฟล์ที่มีช่องว่างในนั้น
  • รหัสสถานะการออกเป็นศูนย์และไม่เป็นศูนย์ (สำหรับการสื่อสารความสำเร็จ / ความล้มเหลวของคำสั่งที่ร้องขอตามลำดับ) จะถูกสงวนไว้ / คืนอย่างถูกต้อง
  • add-symlinkนามแฝงตอนนี้ทำงานมากขึ้นเช่นLN (1)และสามารถนำมาใช้จากไดเรกทอรีใด ๆ ในพื้นที่เก็บข้อมูลที่ไม่เพียง แต่ไดเรกทอรีรากที่เก็บของ
  • rm-symlinkนามแฝง (เอกพจน์) ได้รับการแทนที่โดยrm-symlinksนามแฝง (พหูพจน์) ซึ่งขณะนี้ยอมรับข้อโต้แย้งหลาย (หรือข้อโต้แย้งที่ไม่ทั้งหมดซึ่งพบว่าทั้งหมดของ symlinks ทั่วพื้นที่เก็บข้อมูลเป็นมาก่อน) เพื่อคัดเลือกเปลี่ยน symlinks คอมไพล์ลงใน NTFS hardlinks + ทางแยก .
  • checkout-symlinksนามแฝงยังได้รับการปรับปรุงเพื่อยอมรับข้อโต้แย้งหลาย (หรือไม่มีเลย == ทุกอย่าง) สำหรับการกลับรายการที่เลือกของการเปลี่ยนแปลงดังกล่าว

หมายเหตุสุดท้าย:ในขณะที่ฉันทำการทดสอบการโหลดและการใช้นามแฝงเหล่านี้โดยใช้ Bash 3.2 (และแม้กระทั่ง 3.1) สำหรับผู้ที่อาจยังติดอยู่กับรุ่นโบราณเช่นนี้ด้วยเหตุผลหลายประการ เป็นโรคจิต หากคุณประสบปัญหาในขณะที่พยายามติดตั้งชื่อแทนเหล่านี้สิ่งแรกที่คุณควรพิจารณาคืออัพเกรดเชลล์ของคุณ (สำหรับ Bash ให้ตรวจสอบเวอร์ชั่นด้วย CTRL + X, CTRL + V) อีกวิธีหนึ่งถ้าคุณกำลังพยายามติดตั้งโดยการวางลงในเทอร์มินัลอีมูเลเตอร์คุณอาจมีโชคมากขึ้นที่จะวางมันลงในไฟล์และจัดหามันแทนเช่น

. ./git-win-symlinks.sh

โชคดี!


คุณช่วยดูที่นี่ได้ไหม stackoverflow.com/questions/21403772/…
Goofy

นี่เป็นสคริปต์ที่ยอดเยี่ยมและยอดเยี่ยม แต่มีเหตุผลใดที่ควรติดคำว่า "git" แบบสุ่มในตอนท้ายของไฟล์บางไฟล์ที่ฉันสร้างด้วย git add-symlink
Peter Turner

นอกจากนี้หากชื่อไฟล์ของคุณมี "-h" คุณจะได้รับการใช้งาน ยังคงเป็นสคริปต์ที่มีประโยชน์มาก!
Peter Turner

ของคุณ git add-symlinkสูตรมีค่าอย่างน่าอัศจรรย์สำหรับฉัน ขอบคุณมาก.
Dan Lenski

1
มีวิธีการรันสคริปต์เหล่านี้โดยใช้ตะขอ?
ARF

74

เวอร์ชันล่าสุดของgit scm (testet 2.11.1) อนุญาตให้เปิดใช้งานลิงก์สัญลักษณ์ แต่คุณต้องโคลนพื้นที่เก็บข้อมูลด้วย symlinks อีกครั้งgit clone -c core.symlinks=true <URL>อีกครั้ง คุณต้องเรียกใช้คำสั่งนี้ด้วยสิทธิ์ของผู้ดูแลระบบ นอกจากนี้ยังสามารถสร้าง symlink บน Windows ด้วย mklink ตรวจสอบวิกิพีเดีย

ป้อนคำอธิบายรูปภาพที่นี่


1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันติดตั้ง git ใหม่สำหรับ Windows อย่าลืมตรวจสอบช่องทำเครื่องหมาย symlink และโคลนโครงการของฉันอีกครั้ง tslint.jsonไฟล์ของฉันที่อ้างถึงไฟล์ในไดเรกทอรีหลักยังคงมี../tslint.jsonอยู่ น่าเสียดายเพราะนี่เป็นวิธีที่ง่ายที่สุดในการแก้ปัญหาทั้งหมดที่เสนอในนั้น
Jan Aagaard

8
@JanAagaard คุณต้องโคลนแบบนี้: git clone -c core.symlinks=true <URL> และบน Windows คุณต้องใช้มันด้วยสิทธิ์ผู้ดูแลระบบ
sirlunchalot

6
@ARF "เรียกใช้ gpedit.msc (เช่นตัวแก้ไขนโยบายกลุ่ม) และเพิ่มบัญชีลงในคอมพิวเตอร์ configuration \ Windows Setting \ Security Settings \ Local Policies \ Local Policies \ User Rights Assignment \ Create เชื่อมโยงสัญลักษณ์"
sirlunchalot

2
@sunchunchalot ขอบคุณสำหรับความช่วยเหลือ ฉันได้ตระหนักว่าปัญหาของฉันคือผู้ใช้ของฉันเป็นส่วนหนึ่งของกลุ่มผู้ดูแลระบบและคุณสมบัตินี้ไม่มีผลกับผู้ใช้เหล่านี้ พวกเขาต้องการระดับความสูงของ UAC ซึ่งคอมไพล์ไม่ได้ทำ
ARF

9
สิทธิ์ผู้ดูแลระบบไม่จำเป็นใน "โหมดนักพัฒนาซอฟต์แวร์" ในการอัปเดต Windows 10 ผู้สร้าง ขอบคุณ @dennis ในความคิดเห็นของเขา
Dominik

16

มันควรจะดำเนินการใน msysgit แต่มีข้อเสียสอง:

  • ลิงก์สัญลักษณ์มีให้บริการเฉพาะใน Windows Vista และใหม่กว่า (ไม่ควรมีปัญหาในปี 2011 และยังเป็น ... ) เนื่องจากรุ่นที่เก่ากว่ารองรับการแยกไดเรกทอรีเท่านั้น
  • (ตัวใหญ่) Microsoft ถือว่าการเชื่อมโยงสัญลักษณ์มีความเสี่ยงด้านความปลอดภัยดังนั้นผู้ดูแลระบบเท่านั้นจึงสามารถสร้างได้โดยค่าเริ่มต้น คุณจะต้องยกระดับสิทธิ์ของกระบวนการ git หรือใช้ fstool เพื่อเปลี่ยนพฤติกรรมนี้ในทุกเครื่องที่คุณทำงาน

ผมค้นหาได้อย่างรวดเร็วและมีการทำงานจะถูกดำเนินการอย่างแข็งขันในนี้เห็นปัญหา224


2
อัปเดต: ด้วยเหตุผลด้านบนปัญหาถูกปิดเป็น wontfix การสนทนาแสดงให้เห็นว่าสามารถแก้ไขได้ด้วยการทำงานเพิ่มเติมบนแพทช์ (พูดโดยใช้ symlink เฉพาะเมื่อใช้งานได้)
Blaisorblade

2
A. ) msysgit ในปัจจุบันไม่รองรับ symlinks เลย - ทำไมไม่มีมันตรวจพบ "โอ้คุณอยู่ใน Vista ด้วย NTFS ให้ฉันใช้ symlinks" หรือ "โอ้คุณอยู่บน OS ที่รองรับ junctions ด้วย NTFS ให้ฉันใช้สิ่งเหล่านั้น "หรือ" โอ้คุณอยู่บน windows 98 / fat32 ให้ฉันเลือกที่จะไม่มีคุณสมบัตินี้และให้คำเตือนแทนคุณ! " และจากนั้น B. ) dev ทั้งหมดของ microsoft เครื่องมือทำงานไม่ถูกต้อง (อย่างน้อยก็ไม่ใช่สำหรับคุณสมบัติทั้งหมดของพวกเขา) หากคุณไม่เรียกใช้พวกเขาในฐานะผู้ดูแลระบบ - ทุกคนใน IT รู้ดีว่านักพัฒนาจำเป็นต้องเป็นผู้ดูแลระบบในกล่องของตัวเอง
BrainSlugs83

1
ในขณะที่ฉันรันเครื่องบางอย่างในบัญชีผู้ดูแลระบบฉันไม่ปฏิบัติตามปรัชญานั้นในเครื่องพัฒนาของฉัน ฉันมักจะทำงานเป็นผู้ใช้ปกติที่เปิดใช้งาน UAC ฉันเปิดคอนโซลแยกต่างหากสำหรับการดำเนินการที่ต้องใช้สิทธิ์ระดับสูง ในส่วนของการนำสิ่งนี้ไปใช้นั้นจะเกิดขึ้นกับใครบางคน (เช่นคุณ) อาสาสมัครที่จะนำไปใช้ นักพัฒนา msysgit ไม่เป็นที่รู้จักเพื่อการกุศล ...
djs

@djs ผู้ใช้ต้องเปิดพรอมต์คำสั่งด้วย "Run as Administrator" มันเกือบจะทำงานอย่างแท้จริงในฐานะผู้ใช้ผู้ดูแลระบบซึ่งเปลี่ยนแปลงสภาพแวดล้อมได้อย่างสมบูรณ์ ไม่มีวิธีเรียกใช้ 'mklink / d' ในฐานะผู้ใช้ที่อยู่ในกลุ่มผู้ดูแลระบบ มันจะไม่แจ้งให้ UAC มันจะล้มเหลวเสมอ วิธีการทำงานสองวิธีเท่านั้น: แท้จริงในฐานะผู้ใช้ผู้ดูแลระบบ (RunAs Verb) หรือผู้ใช้ที่ไม่ใช่ผู้ดูแลระบบที่มีการเปลี่ยนแปลงนโยบายกลุ่ม การแยกควรเป็นค่าเริ่มต้นและควรได้รับการยอมรับจากเครื่องมือทั้งหมด 'ความเสี่ยงด้านความปลอดภัย' คือ symlink บน Windows สามารถ 'เปลี่ยนเส้นทาง' แชร์ SMB นี่คือความเจ็บปวดและโหดร้าย
Andrew T Finnell

8
ประกาศเมื่อเดือนธันวาคม 2559 Symlinks ใน Windows 10 ไม่ใช่การกระทำของผู้ดูแลระบบอีกต่อไป blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/…
Dennis

16

ดังนั้นเมื่อสิ่งต่าง ๆ เปลี่ยนไปด้วย GIT เนื่องจากคำตอบเหล่านี้ถูกโพสต์ไว้ที่นี่เป็นคำแนะนำที่ถูกต้องในการทำให้ symlink ทำงานอย่างถูกต้องใน windows ตั้งแต่

สิงหาคม 2561


1. ตรวจสอบให้แน่ใจว่าติดตั้ง git ด้วยการสนับสนุน symlink

ระหว่างการติดตั้ง git บน windows

2. บอก Bash เพื่อสร้าง hardlinks แทนที่จะเป็น symlinks

แก้ไข - (โฟลเดอร์คอมไพล์) /etc/bash.bashrc

เพิ่มที่ด้านล่าง - MSYS=winsymlinks:nativestrict

3. ตั้งค่า git ให้ใช้ symlink

git config core.symlinks true

หรือ

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

หมายเหตุ: ฉันได้ลองเพิ่มสิ่งนี้ไปยังการตั้งค่า git ทั่วโลกและในขณะนี้มันไม่ทำงานสำหรับฉันดังนั้นฉันขอแนะนำให้เพิ่มสิ่งนี้ในแต่ละ repo ...

4. ดึง repo

หมายเหตุ: หากคุณไม่ได้เปิดใช้งานโหมดผู้พัฒนาใน Windows 10 เวอร์ชันล่าสุดคุณจะต้องรัน bash ในฐานะผู้ดูแลระบบเพื่อสร้าง symlink

5. รีเซ็ต Symlinks ทั้งหมด (เป็นทางเลือก) หากคุณมี repo ที่มีอยู่หรือใช้ submodules คุณอาจพบว่า symlink นั้นไม่ได้ถูกสร้างขึ้นอย่างถูกต้องดังนั้นเพื่อรีเฟรช symlink ทั้งหมดใน repo คุณสามารถเรียกใช้คำสั่งเหล่านี้ได้

find -type l -delete
git reset --hard

หมายเหตุ: สิ่งนี้จะรีเซ็ตการเปลี่ยนแปลงใด ๆ ตั้งแต่การส่งครั้งล่าสุดดังนั้นให้แน่ใจว่าคุณได้ทำข้อตกลงไว้ก่อน


15

คำตอบสั้น ๆ : ตอนนี้ได้รับการสนับสนุนเป็นอย่างดีหากคุณสามารถเปิดใช้งานโหมดผู้พัฒนาได้

จากhttps://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/

ขณะนี้อยู่ในการอัปเดตผู้สร้าง Windows 10 ผู้ใช้ (ที่มีสิทธิ์ของผู้ดูแลระบบ) สามารถเปิดใช้งานโหมดนักพัฒนาได้ก่อนจากนั้นผู้ใช้ในเครื่องสามารถเรียกใช้คำสั่ง mklink ได้โดยไม่ต้องยกคอนโซลบรรทัดคำสั่งขึ้น

อะไรทำให้เกิดการเปลี่ยนแปลงนี้ ความพร้อมใช้งานและการใช้ symlink เป็นเรื่องใหญ่สำหรับนักพัฒนาสมัยใหม่:

เครื่องมือการพัฒนาที่ได้รับความนิยมมากมายเช่น git และตัวจัดการแพ็คเกจเช่น npm รู้จักและยังคงมี symlink อยู่เมื่อสร้าง repos หรือแพ็คเกจตามลำดับ เมื่อ repos หรือแพ็กเกจเหล่านั้นได้รับการกู้คืนที่อื่น symlink จะถูกกู้คืนเพื่อให้แน่ใจว่าพื้นที่ดิสก์ (และเวลาของผู้ใช้) จะไม่สูญเปล่า

มองข้ามได้ง่ายด้วยการประกาศอื่น ๆ ทั้งหมดของ "การอัปเดตของผู้สร้าง" แต่ถ้าคุณเปิดใช้งานโหมดนักพัฒนาซอฟต์แวร์คุณสามารถสร้าง symlink โดยไม่ต้องยกระดับสิทธิ์ คุณอาจต้องติดตั้งคอมไพล์อีกครั้งและให้แน่ใจว่าเปิดใช้งานการสนับสนุน symlink เนื่องจากไม่ใช่ค่าเริ่มต้น

ลิงก์สัญลักษณ์ไม่ได้เปิดใช้งานตามค่าเริ่มต้น


1
gpedit.msc-> -> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmentเป็นวิธีที่ได้รับการยอมรับในการกำหนดสิทธิ์ของผู้ใช้เช่นSeCreateSymbolicLinkและเพื่อน ๆ ทุกเพศทุกวัย นอกเหนือntrights.exeจาก Resource Kit หรือ PowerShell ...
0xC0000022L

11

2563 คำตอบ

  1. เปิดใช้งาน "โหมดนักพัฒนาซอฟต์แวร์" ใน Windows 10 - ให้การmklinkอนุญาต
  2. ตรวจสอบให้แน่ใจว่าเปิดใช้งาน symlink ในคอมไพล์แล้ว
    • git config --global core.symlinks true
    • หรือทำเครื่องหมายที่ช่องเมื่อทำการติดตั้ง msysgit

การสลับสาขาจะบังคับให้มีการสันทนาการของ symlink ที่ขาดหายไป

โปรดระวังการสนับสนุน Symlinks บน Windows กับไคลเอนต์ Git อื่น ๆ นั้นยังไม่เสร็จสมบูรณ์ GitKraken สะดุดตา


ที่เก็บข้อมูลในเครื่องทั้งหมดของฉันมี core.symlinks = false ซึ่งจะแทนที่โซลูชันของคุณ มีความคิดใดที่จะสร้างการกำหนดค่าท้องถิ่นนี้โดยอัตโนมัติ อาจติดตั้ง Git สำหรับ Windows โดยไม่ทำเครื่องหมายในช่องทำเครื่องหมายใช่หรือไม่
gravidThoughts

@ gravidThoughts คุณได้ติดตั้งไคลเอนต์ git ใด? อาจมีเครื่องมือบางอย่างกำลังทำสิ่งนี้อยู่ใช่ไหม สิ่งนี้เป็นจริงหรือไม่ในการโคลนนิ่งสดใหม่?
Cameron Tacklind

10

ฉันขอแนะนำให้คุณไม่ใช้ symlink ภายใน repo ' จัดเก็บเนื้อหาจริงภายใน repo 'และวาง symlink ไว้ด้านข้าง repo' ซึ่งชี้ไปที่เนื้อหา

ดังนั้นสมมติว่าคุณใช้ repo 'เพื่อเปรียบเทียบการโฮสต์เว็บไซต์ของคุณใน * nix กับการโฮสต์บน win จัดเก็บเนื้อหาไว้ใน repo ของคุณให้พูด/httpRepoContentและc:\httpRepoContentด้วยการเป็นโฟลเดอร์ที่ซิงค์ผ่าน GIT, SVN และอื่น ๆ

จากนั้นแทนที่โฟลเดอร์เนื้อหาของเว็บเซิร์ฟเวอร์ของคุณ ( /var/wwwและc:\program files\web server\www{ชื่อไม่สำคัญเลยแก้ไขหากคุณต้อง}) ด้วยลิงก์สัญลักษณ์ไปยังเนื้อหาใน repo ของคุณ ' เว็บเซิร์ฟเวอร์จะเห็นเนื้อหาเหมือนอยู่ในสถานที่ 'ถูกต้อง' แต่คุณจะต้องใช้แหล่งควบคุมของคุณ

อย่างไรก็ตามหากคุณจำเป็นต้องใช้ symlink ด้วยใน repo 'คุณจะต้องค้นหาบางอย่างเช่นสคริปต์การคอมมิทล่วงหน้า / โพสต์ ฉันรู้ว่าคุณสามารถใช้พวกเขาเพื่อทำสิ่งต่าง ๆ เช่นไฟล์แยกวิเคราะห์รหัสผ่านตัวจัดรูปแบบตัวอย่างเช่นดังนั้นจึงควรแปลง symlink ระหว่างแพลตฟอร์ม

ถ้ามีใครรู้ที่ดีในการเรียนรู้วิธีการทำสคริปต์เหล่านี้สำหรับการควบคุมแหล่งที่มาทั่วไป SVN GIT MG โปรดเพิ่มความคิดเห็น


ในท้ายที่สุดฉันเลือกวิธีนี้เพื่อสร้างโฟลเดอร์ symlink-out และสร้างลิงก์สัญลักษณ์ไปยังตำแหน่งที่ไฟล์ต้นฉบับเคยเป็น วิธีอื่นไม่ทำงานแม้ว่าฉันจะเปลี่ยนการตั้งค่า. git / config core.symlinks = true ไฟล์ลิงก์สัญลักษณ์เท่านั้นที่ถูกบันทึกลงใน repo และไม่ใช่ข้อมูล นอกจากนี้ยังมีปัญหากับการประทับเวลาของโฟลเดอร์บนลิงก์สัญลักษณ์เพื่อให้ทุบตี Git ไม่เคยเห็นเมื่อไฟล์มีการเปลี่ยนแปลงภายในโฟลเดอร์
ไข่

@Eggs สิ่งที่คุณอาจได้เห็นฉันเดาว่าลิงก์นั้นอยู่ใน repo และคอมไพล์ก็บันทึกมัน simples แม้ว่าปัญหาคือเป้าหมายอยู่นอก repo และ git ไม่ได้ติดตามลิงก์ไปยังข้อมูลเป้าหมาย บน linux คุณมีลิงค์ประเภทหนึ่งที่ใช้งานได้โดยพื้นฐานแล้วคุณจะมีสองเส้นทางไปยังข้อมูลเดียวกันที่เก็บไว้ในดิสก์ ฉันรู้สึกว่าหน้าต่างใหม่สามารถทำได้ตอนนี้ ฉันก็ยังไม่คิดว่ามันจะทำในสิ่งที่คนต้องการ
thecoshman

@thecoshman นี่ไม่ใช่ทางออก แต่เป็นวิธีแก้ปัญหา อย่างไรก็ตามบางครั้งนี่ไม่ใช่ตัวเลือก ฉันมีพื้นที่เก็บข้อมูลที่มี git-annex และสถาปัตยกรรมทั้งหมดทำงานได้เนื่องจากลิงก์สัญลักษณ์
marcelo.guedes

8

สำหรับผู้ที่ใช้Cygwinบน Vista, Win7, หรือสูงกว่าพื้นเมืองgitคำสั่งสามารถสร้าง symlinks "เหมาะสม" ที่เป็นที่ยอมรับโดย Windows ปพลิเคชันเช่นAndroid สตูดิโอ คุณเพียงแค่ต้องตั้งค่าCYGWINตัวแปรสภาพแวดล้อมเพื่อรวมwinsymlinks:nativeหรือwinsymlinks:nativestrictเป็นเช่นนี้:

export CYGWIN="$CYGWIN winsymlinks:native"

ข้อเสียของสิ่งนี้ (และสิ่งสำคัญอย่างหนึ่งคือ) ว่า CygWin shell นั้นต้องเป็น "Run as Administrator" เพื่อให้มันมีสิทธิ์ระบบปฏิบัติการที่จำเป็นในการสร้าง symlink แบบนั้น เมื่อพวกเขากำลังสร้าง แต่ไม่มีสิทธิ์พิเศษที่จะต้องใช้พวกเขา ตราบใดที่พวกเขาไม่ได้ถูกเปลี่ยนในที่เก็บข้อมูลโดยผู้พัฒนารายอื่นgitหลังจากนั้นก็สามารถทำงานได้ตามปกติด้วยสิทธิ์ผู้ใช้ปกติ

โดยส่วนตัวแล้วฉันใช้สิ่งนี้เฉพาะกับ symlink ที่ใช้งานแอพ Windows (เช่นไม่ใช่ CygWin) เนื่องจากความยากลำบากที่เพิ่มเข้ามา

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกนี้ให้ดูคำถาม SO นี้: วิธีสร้างลิงก์สัญลักษณ์ด้วย cygwin ใน Windows 7


6

นี่คือแบทช์สคริปต์สำหรับการแปลง symlink ในที่เก็บสำหรับไฟล์เท่านั้นตามคำตอบของ Josh Lee สคริปต์ที่มีบางส่วนตรวจสอบเพิ่มเติมสำหรับสิทธิผู้ดูแลระบบที่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

คำตอบที่ไม่มีเอกสารนั้นไม่ค่อยได้ใช้จริง ๆ เมื่อมีคำตอบที่ยาวและละเอียดมากอยู่แล้ว
Xennex81

4

ฉันใช้ลิงค์ sym ตลอดเวลาระหว่างรูทเอกสารและไดเรกทอรี git repo ของฉัน ฉันชอบแยกพวกมันออก บน windows ฉันใช้ตัวเลือก mklink / j ดูเหมือนว่าทางแยกให้คอมไพล์ทำงานตามปกติ:

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

ตัวอย่างเช่น:

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


2
ใช้ความระมัดระวังกับ Windows Explorer และทางแยก มันไม่แยกความแตกต่างจากที่ตั้งฐานและการลบจะถูกคืนค่าไปยังเป้าหมายและลบเนื้อหาในขณะที่การลบ symlink จะลบ symlink ออก เพียงกับดักสำหรับเลินเล่อ
Lawrence Dol

5
ที่จริงแล้วเพิ่งทดสอบสิ่งนี้กับ Windows7 ล่าสุดและไม่ทำอีกต่อไปดังนั้นการจัดการจุดแยกได้รับการปรับปรุงในช่วงไม่กี่ปีที่ผ่านมา
Lawrence Dol

3

ฉันกำลังมองหาทางออกที่ง่ายในการจัดการลิงค์สัญลักษณ์ unix บน windows ขอบคุณมากสำหรับนามแฝง Git ข้างต้น มีการปรับให้เหมาะสมเพียงเล็กน้อยเพียงอย่างเดียวที่สามารถทำได้กับ rm-symlinks เพื่อที่จะไม่ลบไฟล์ในโฟลเดอร์ปลายทางในกรณีที่นามแฝงรันครั้งที่สองโดยไม่ตั้งใจ โปรดสังเกตใหม่หากเงื่อนไขในลูปเพื่อให้แน่ใจว่าไฟล์นั้นไม่ได้เป็นลิงค์ไปยังไดเรกทอรีก่อนที่จะรันตรรกะ

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

เคล็ดลับง่ายๆอย่างหนึ่งที่เราใช้คือเพียงโทรหาgit add --allสองครั้งติดต่อกัน

ตัวอย่างเช่นการโทรสคริปต์ Windows 7 ของเรา:

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

การเพิ่มครั้งแรกถือว่าการเชื่อมโยงเป็นข้อความและเพิ่มโฟลเดอร์สำหรับการลบ

เพิ่มที่สองสำรวจลิงค์อย่างถูกต้องและยกเลิกการลบโดยการกู้คืนไฟล์

มันมีความหรูหราน้อยกว่าโซลูชันที่นำเสนออื่น ๆ แต่มันเป็นวิธีการแก้ไขที่ง่ายสำหรับสภาพแวดล้อมระบบเดิมของเราที่มีการเพิ่ม symlink

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.