Liên kết Git trong Windows


246

Các nhà phát triển của chúng tôi sử dụng kết hợp các hệ điều hành dựa trên Windows và Unix. Do đó, các liên kết tượng trưng được tạo trên các máy Unix trở thành một vấn đề đối với các nhà phát triển Windows. Trong windows (msysgit), symlink được chuyển đổi thành tệp văn bản có đường dẫn đến tệp mà nó trỏ tới. Thay vào đó, tôi muốn chuyển đổi symlink thành symlink thực tế của Windows.

Giải pháp (đã cập nhật ) tôi có là:

  • Viết một kịch bản kiểm tra sau sẽ kiểm tra đệ quy các tệp văn bản "symlink".
  • Thay thế chúng bằng windows symlink (sử dụng mklink) có cùng tên và phần mở rộng là "symlink" giả
  • Bỏ qua các liên kết cửa sổ này bằng cách thêm mục vào .git / thông tin / loại trừ

Tôi đã không thực hiện điều này, nhưng tôi tin rằng đây là một cách tiếp cận vững chắc cho vấn đề này.

Câu hỏi:

  1. Điều gì, nếu có, nhược điểm bạn thấy đối với phương pháp này?
  2. Là kịch bản sau kiểm tra này thậm chí có thể thực hiện? tức là tôi có thể tìm đệ quy các tập tin "symlink" giả mà git tạo ra không?
  3. Có ai đã làm việc trên kịch bản như vậy?

3
Mặc dù Git hỗ trợ các liên kết tượng trưng, ​​tôi thực sự khuyên bạn không nên lưu trữ chúng dưới dạng liên kết trong kho lưu trữ của mình, đặc biệt nếu bạn cũng đang làm việc với mã đó trên Windows.
Greg Hewgill

2
@Greg Hewgill - Tôi hoàn toàn đồng ý với bạn. Thật không may, bản chất của cơ sở mã của chúng tôi yêu cầu các liên kết tượng trưng ... vì vậy loại bỏ chúng không phải là một lựa chọn cho chúng tôi.
Ken Hirakawa

12
Bạn cũng có thể hỏi trên danh sách gửi thư msysgit tại sao họ không thực hiện nó như thế ở nơi đầu tiên.
mưa phùn

8
@GregHewgill tại sao không? Windows hỗ trợ cả các liên kết và mối nối tượng trưng - đây thực sự có vẻ như là một tính năng bị thiếu trong các phiên bản windows của Git to me ...
BrainSlugs83

6
Với "Chế độ nhà phát triển" được bật trong Windows 10, việc tạo liên kết tượng trưng không yêu cầu quyền Quản trị viên! (Những người khác nhận xét nhiều về các câu trả lời ít được bình chọn hơn, nhưng tôi đã không nhìn thấy chúng. Hy vọng bình luận này sẽ dễ thấy hơn đối với các độc giả tương lai.)
Dave Pascua

Câu trả lời:


105

Bạn có thể tìm thấy các liên kết tượng trưng bằng cách tìm kiếm các tệp có chế độ 120000, có thể bằng lệnh này:

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

Khi bạn thay thế các liên kết, tôi khuyên bạn nên đánh dấu chúng là không thay đổi git update-index --assume-unchanged, thay vì liệt kê chúng vào .git/info/exclude.


2
Tôi đã phải thay thế awk bằng gawk cho msysgit, nhưng nếu không thì nó hoạt động hoàn hảo. Cảm ơn!
Ken Hirakawa

6
helo ken. bạn có phiền khi chia sẻ tập lệnh của mình để kiểm tra các tệp văn bản symlink và thay thế chúng bằng các liên kết tượng trưng trên windows bằng mklink. trong khi điều này thực sự hiệu quả với chúng ta - phần không thay đổi không. khi chuyển sang một nhánh khác, git nói rằng các tệp symlink đã được thay đổi và cần được cam kết trước, trong khi trạng thái git nói rằng không có thay đổi nào..có ý tưởng nào không?
joreg

6
Đây là một PowerShell mà tôi vừa kết hợp - gist.github.com/ferventcoder/7995025
ferventcoder 16/12/13

3
@flungo Có nhiều cách di động để in cột thứ tư hơn là sử dụng GNU awk. Ví dụ: git ls-files -s | grep '^12' | cut -f2(cột được phân định bằng tab thứ hai; các cột khác được phân cách bằng dấu cách)
Zenexer

1
Một lớp lót cho Cygwin / bash để đánh dấu tất cả các liên kết tượng trưng không thay đổi:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden

187

Tôi đã hỏi chính xác câu hỏi này một lúc trước (không phải ở đây, chỉ nói chung) và cuối cùng đã đưa ra một giải pháp rất giống với đề xuất của OP. Đầu tiên tôi sẽ cung cấp câu trả lời trực tiếp cho các câu hỏi 1 2 & 3, và sau đó tôi sẽ đăng giải pháp mà tôi đã sử dụng.

  1. Thực tế, có một vài nhược điểm đối với giải pháp được đề xuất, chủ yếu liên quan đến việc tăng nguy cơ ô nhiễm kho lưu trữ hoặc vô tình thêm các tệp trùng lặp trong khi chúng ở trạng thái "Windows symlink". (Thông tin thêm về điều này dưới "giới hạn" bên dưới.)
  2. Có, một kịch bản sau kiểm tra là có thể thực hiện được! Có thể không phải là một git checkoutbước sau nghĩa đen , nhưng giải pháp dưới đây đã đáp ứng đủ nhu cầu của tôi đến mức không cần thiết phải có một kịch bản kiểm tra sau bằng chữ.
  3. Đúng!

Giải pháp:

Các nhà phát triển của chúng tôi có hoàn cảnh tương tự như OP: một hỗn hợp các máy chủ, kho lưu trữ và mô đun con giống Windows và Unix với nhiều liên kết git và không có hỗ trợ riêng (trong phiên bản phát hành của MsysGit để xử lý thông minh các liên kết này trên máy chủ Windows .

Cảm ơn Josh Lee đã chỉ ra thực tế rằng git cam kết các liên kết tượng trưng với tên tệp đặc biệt 120000. Với thông tin này, có thể thêm một vài bí danh git cho phép tạo và thao tác các liên kết git trên máy chủ Windows.

  1. Tạo liên kết git trên 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
    )"
    

    Cách sử dụng : git add-symlink <source_file_or_dir> <target_symlink>, trong đó đối số tương ứng với tệp nguồn hoặc thư mục phải có dạng đường dẫn liên quan đến liên kết đích. Bạn có thể sử dụng bí danh này giống như cách bạn thường sử dụng ln.

    Ví dụ, cây kho lưu trữ:

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

    Có thể được tạo trên Windows như sau:

    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. Thay thế các liên kết git bằng các liên kết cứng NTFS + các mối nối

    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.
    

    Sử dụng:

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

    Bí danh này có thể loại bỏ các liên kết git từng cái một hoặc tất cả cùng một lúc trong một cú trượt ngã. Symlinks sẽ được thay thế bằng liên kết cứng NTFS (trong trường hợp tệp) hoặc liên kết NTFS (trong trường hợp thư mục). Lợi ích của việc sử dụng các liên kết cứng + các mối nối so với các liên kết tượng trưng NTFS "thật" là không yêu cầu quyền UAC nâng cao để chúng được tạo.

    Để xóa liên kết tượng trưng khỏi các mô hình con, chỉ cần sử dụng hỗ trợ tích hợp của git để lặp lại chúng:

    git submodule foreach --recursive git rm-symlinks
    

    Nhưng, đối với mọi hành động quyết liệt như thế này, một sự đảo ngược là tốt để có ...

  3. Khôi phục liên kết git trên 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'
    

    Cách sử dụng git checkout-symlinks [symlink] [symlink] [...]:, hoàn tác git rm-symlinks, khôi phục hiệu quả kho lưu trữ về trạng thái tự nhiên (ngoại trừ các thay đổi của bạn, sẽ giữ nguyên).

    Và cho các mô hình con:

    git submodule foreach --recursive git checkout-symlinks
    
  4. Hạn chế:

    • Thư mục / tệp / liên kết tượng trưng với khoảng trắng trong đường dẫn của chúng sẽ hoạt động. Nhưng tab hay dòng mới? YMMV (Theo ý tôi là: đừng làm vậy, vì nó sẽ không hoạt động.)

    • Nếu bản thân hoặc người khác quên git checkout-symlinkstrước khi làm điều gì đó với những hậu quả có khả năng lan rộng như thế git add -A, thì kho lưu trữ cục bộ có thể rơi vào tình trạng ô nhiễm.

      Sử dụng "ví dụ repo" của chúng tôi từ trước:

      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
      #
      

      Rất tiếc ...

      Vì lý do này, thật tuyệt khi bao gồm các bí danh này như các bước để thực hiện cho người dùng Windows trước và sau khi xây dựng dự án, thay vì sau khi thanh toán hoặc trước khi đẩy. Nhưng mỗi tình huống là khác nhau. Những bí danh này đã đủ hữu ích cho tôi rằng một giải pháp hậu kiểm thực sự là không cần thiết.

Mong rằng sẽ giúp!

Người giới thiệu:

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

http://technet.microsoft.com/en-us/l Library / cc753194

Cập nhật lần cuối: 2019-03-13

  • Tuân thủ POSIX (tốt, ngoại trừ những mklinkcuộc gọi đó, tất nhiên) - không còn Bashism nữa !
  • Thư mục và tập tin có không gian trong đó được hỗ trợ.
  • Mã trạng thái thoát không và không bằng 0 (để truyền đạt thành công / thất bại của lệnh được yêu cầu, tương ứng) hiện được bảo toàn / trả lại đúng cách.
  • Các add-symlinkbí danh hiện đang làm việc giống như ln (1) và có thể được sử dụng từ bất kỳ thư mục trong kho, không chỉ thư mục gốc của kho.
  • Các rm-symlinkbí danh (số ít) đã được thay thế bởi các rm-symlinksbí danh (số nhiều), mà bây giờ chấp nhận nhiều đối số (hoặc không có đối số ở tất cả, mà tìm thấy tất cả các liên kết tượng trưng trong suốt kho, như trước đây) cho các lựa chọn chuyển symlink git vào NTFS hardlinks + nút giao thông .
  • Các checkout-symlinksbí danh cũng đã được cập nhật để chấp nhận nhiều đối số (hoặc không có gì cả, tất cả mọi thứ ==) cho sự đảo ngược có chọn lọc các biến đổi nói trên.

Lưu ý cuối cùng: Mặc dù tôi đã kiểm tra tải và chạy các bí danh này bằng Bash 3.2 (và thậm chí 3.1) cho những người vẫn có thể bị mắc kẹt trên các phiên bản cổ như vậy vì bất kỳ lý do nào, hãy lưu ý rằng các phiên bản cũ như thế này đều nổi tiếng với trình phân tích cú pháp của họ lỗi. Nếu bạn gặp sự cố trong khi cố gắng cài đặt bất kỳ bí danh nào, điều đầu tiên bạn nên xem xét là nâng cấp trình bao của mình (đối với Bash, hãy kiểm tra phiên bản với CTRL + X, CTRL + V). Ngoài ra, nếu bạn đang cố gắng cài đặt chúng bằng cách dán chúng vào trình giả lập thiết bị đầu cuối của mình, bạn có thể gặp nhiều may mắn hơn khi dán chúng vào một tệp và tìm nguồn cung ứng thay thế, ví dụ như

. ./git-win-symlinks.sh

Chúc may mắn!


bạn có thể vui lòng xem nó ở đây không? stackoverflow.com/questions/21403772/ Mạnh
Goofy

Đây là một kịch bản tuyệt vời và tuyệt vời, nhưng có lý do nào khiến nó phải gắn ngẫu nhiên từ "git" vào cuối một số tệp mà tôi tạo bằng git add-symlink không?
Peter Turner

Ngoài ra, nếu tên tệp của bạn chứa "-h", bạn sẽ sử dụng. Vẫn là một kịch bản hữu ích!
Peter Turner

git add-symlinkCông thức của bạn đã rất có giá trị đối với tôi. Cảm ơn nhiều.
Dan Lenski

1
Có cách nào để tự động thực thi các tập lệnh này bằng hook không?
ARF

74

Phiên bản mới nhất của git scm (testet 2.11.1) cho phép kích hoạt các liên kết tượng trưng. Nhưng bạn phải sao chép kho lưu trữ với các liên kết tượng trưng một lần nữa git clone -c core.symlinks=true <URL>. Bạn cần chạy lệnh này với quyền quản trị viên. Cũng có thể tạo symlink trên Windows bằng mklink. Kiểm tra wiki .

nhập mô tả hình ảnh ở đây


1
Điều này đã không làm việc cho tôi. Tôi đã cài đặt lại git cho Windows, nhớ kiểm tra hộp kiểm symlink và sao chép lại dự án của tôi. tslint.jsonTệp của tôi tham chiếu tệp trong thư mục cha vẫn chứa ../tslint.json. Đáng tiếc, bởi vì điều này thực sự trông giống như dễ dàng nhất trong tất cả các giải pháp được đề xuất trong đó.
Jan Aagaard

8
@JanAagaard Bạn phải sao chép nó như thế này: git clone -c core.symlinks=true <URL> Và trên Windows, bạn phải chạy nó với quyền quản trị viên.
sirlunchalot

6
@ARF "Khởi chạy gpedit.msc (tức là trình chỉnh sửa chính sách nhóm) và thêm (các) tài khoản vào Cấu hình máy tính \ Cài đặt Windows \ Cài đặt bảo mật \ Chính sách cục bộ \ Phân quyền quyền người dùng \ Tạo liên kết tượng trưng."
sirlunchalot

2
@sirlunchalot Cảm ơn sự giúp đỡ. Kể từ đó tôi nhận ra rằng vấn đề của tôi là người dùng của tôi là một phần của nhóm Quản trị viên và tài sản này không có tác dụng đối với những người dùng này. Họ yêu cầu độ cao UAC mà git không làm được.
ARF

9
Quyền quản trị viên không cần thiết trong "Chế độ nhà phát triển" trong Cập nhật người tạo Windows 10. Cảm ơn @dennis trong bình luận của anh ấy .
Dominik

16

Nó nên được thực hiện trong msysgit, nhưng có hai nhược điểm:

  • Các liên kết tượng trưng chỉ có sẵn trong Windows Vista trở lên (không phải là vấn đề trong năm 2011, nhưng nó là ...), vì các phiên bản cũ hơn chỉ hỗ trợ các nút nối thư mục.
  • (cái lớn) Microsoft coi các liên kết tượng trưng là rủi ro bảo mật và do đó, chỉ quản trị viên mới có thể tạo chúng theo mặc định. Bạn sẽ cần nâng cao các đặc quyền của quy trình git hoặc sử dụng fstool để thay đổi hành vi này trên mọi máy bạn làm việc.

Tôi đã thực hiện một tìm kiếm nhanh và có công việc đang được thực hiện tích cực về vấn đề này, xem vấn đề 224 .


2
Cập nhật: vì những lý do trên, vấn đề đã được đóng lại dưới dạng wontfix. Các cuộc thảo luận chỉ ra rằng một bản sửa lỗi có thể được chấp nhận với một số công việc khác trên bản vá (giả sử, chỉ sử dụng liên kết tượng trưng nếu chúng hoạt động).
Blaisorblade

2
A.) hiện tại msysgit hoàn toàn không hỗ trợ symlink - vậy tại sao bạn không phát hiện ra "oh you on vista with NTFS hãy để tôi sử dụng symlink" hoặc "oh, bạn đang dùng HĐH hỗ trợ các mối nối với NTFS, hãy để tôi sử dụng chúng "hoặc" oh, bạn đang sử dụng windows 98 / fat32, hãy để tôi dự phòng khi không có tính năng này và đưa ra cảnh báo cho bạn! " và sau đó B.) Khá nhiều tất cả các nhà phát triển của microsoft. các công cụ không hoạt động đúng (ít nhất là không phải cho tất cả các tính năng của chúng) nếu bạn không chạy chúng với tư cách quản trị viên - mọi người trong CNTT đều biết rằng các nhà phát triển cần phải là quản trị viên trên các hộp riêng của họ.
BrainSlugs83

1
Trong khi tôi chạy một số máy nhất định trong tài khoản Quản trị viên, tôi không tuân theo triết lý đó trên máy phát triển của mình. Tôi luôn chạy như một người dùng thông thường có hỗ trợ UAC. Tôi giữ một giao diện điều khiển riêng mở cho các hoạt động yêu cầu đặc quyền nâng cao. Đối với việc này được thực hiện, nó thuộc về một người nào đó (như bạn) tình nguyện thực hiện nó. Các nhà phát triển msysgit không được biết đến với mục đích từ thiện ...
djs

@djs Người dùng phải mở dấu nhắc lệnh với "Chạy với tư cách Quản trị viên". Nó gần như hoàn toàn hoạt động với tư cách là Người dùng Quản trị viên thay đổi hoàn toàn Môi trường. Không có cách nào để chạy 'mklink / d' với tư cách là Người dùng cũng thuộc nhóm Quản trị viên. Nó sẽ không nhắc UAC. Nó sẽ thất bại, luôn luôn. Chỉ có hai cách nó hoạt động: Theo nghĩa đen là người dùng Quản trị viên (RunAs Verb) hoặc Người dùng không phải là quản trị viên với thay đổi chính sách nhóm. Các mối nối phải là mặc định và phải được công nhận bởi tất cả các công cụ. 'Rủi ro bảo mật' là các liên kết tượng trưng trên Windows có thể 'chuyển hướng' cổ phiếu SMB. Đây là một nỗi đau và tàn nhẫn.
Andrew T Finnell

8
Được công bố vào tháng 12 năm 2016, Symlinks trong Windows 10 không còn là hành động của Quản trị viên. blog.windows.com/buildingapps/2016/12/02/symlinks-windows-10/ trên
Dennis

16

vì vậy mọi thứ đã thay đổi với GIT vì rất nhiều câu trả lời đã được đăng ở đây là hướng dẫn chính xác để các liên kết tượng trưng hoạt động chính xác trong windows kể từ

THÁNG 8 NĂM 2018


1. Đảm bảo git được cài đặt với hỗ trợ symlink

Trong quá trình cài đặt git trên windows

2. Nói với Bash để tạo liên kết cứng thay vì liên kết tượng trưng

EDIT - (thư mục git) /etc/bash.bashrc

THÊM VÀO BOTTOM - MSYS=winsymlinks:nativestrict

3. Đặt cấu hình git để sử dụng liên kết tượng trưng

git config core.symlinks true

hoặc là

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

LƯU Ý: Tôi đã thử thêm phần này vào cấu hình git toàn cầu và hiện tại nó không hoạt động với tôi nên tôi khuyên bạn nên thêm phần này vào mỗi repo ...

4. kéo repo

LƯU Ý: Trừ khi bạn đã bật chế độ nhà phát triển trong phiên bản Windows 10 mới nhất, bạn cần chạy bash với tư cách quản trị viên để tạo liên kết tượng trưng

5. Đặt lại tất cả các Liên kết (tùy chọn) Nếu bạn có một repo hiện có hoặc đang sử dụng các mô hình con, bạn có thể thấy rằng các liên kết tượng trưng không được tạo chính xác để làm mới tất cả các liên kết tượng trưng trong repo bạn có thể chạy các lệnh này.

find -type l -delete
git reset --hard

LƯU Ý: điều này sẽ đặt lại bất kỳ thay đổi nào kể từ lần xác nhận cuối cùng, vì vậy hãy chắc chắn rằng bạn đã cam kết trước


15

Câu trả lời ngắn: Hiện tại chúng được hỗ trợ độc đáo, nếu bạn có thể bật chế độ nhà phát triển.

Từ https://bloss.windows.com/buildingapps/2016/12/02/symlinks-windows-10/

Giờ đây, trong Windows 10 Creators Update, người dùng (có quyền quản trị viên) trước tiên có thể bật Chế độ nhà phát triển và sau đó bất kỳ người dùng nào trên máy có thể chạy lệnh mklink mà không cần nâng bảng điều khiển dòng lệnh.

Điều gì đã thúc đẩy sự thay đổi này? Tính khả dụng và sử dụng của các liên kết tượng trưng là một vấn đề lớn đối với các nhà phát triển hiện đại:

Nhiều công cụ phát triển phổ biến như git và trình quản lý gói như npm nhận ra và duy trì liên kết tượng trưng khi tạo repos hoặc gói tương ứng. Khi các repos hoặc gói đó sau đó được khôi phục ở nơi khác, các liên kết tượng trưng cũng được khôi phục, đảm bảo không gian đĩa (và thời gian của người dùng) sẽ không bị lãng phí.

Dễ dàng bỏ qua với tất cả các thông báo khác về "Cập nhật của người tạo", nhưng nếu bạn bật Chế độ nhà phát triển, bạn có thể tạo liên kết tượng trưng mà không cần đặc quyền nâng cao. Bạn có thể phải cài đặt lại git và đảm bảo hỗ trợ symlink được bật, vì nó không phải theo mặc định.

Liên kết tượng trưng không được bật theo mặc định


1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmentlà cách hợp quy để gán quyền người dùng như SeCreateSymbolicLinkbạn bè và lứa tuổi. Khác với ntrights.exeBộ tài nguyên hoặc PowerShell ...
0xC0000022L

11

2020 Trả lời

  1. Bật "Chế độ nhà phát triển" trong Windows 10 - cấp mklinkquyền
  2. Đảm bảo symlink được kích hoạt trong git
    • git config --global core.symlinks true
    • hoặc chọn hộp kiểm khi cài đặt msysgit

Chuyển đổi chi nhánh sẽ buộc giải trí của các liên kết thiếu.

Hãy cẩn thận, hỗ trợ Symlinks trên Windows với một số ứng dụng khách Git khác chưa hoàn tất. Đáng chú ý là GitKraken.


Tất cả các kho lưu trữ cục bộ của tôi đều có core.symlinks = false sẽ ghi đè lên giải pháp của bạn. Bất kỳ ý tưởng những gì đang sản xuất cấu hình cục bộ này tự động? Có thể cài đặt Git cho Windows mà không cần chọn hộp kiểm?
gravidThoughts

@gravidThoughts bạn đã cài đặt ứng dụng khách git nào? Có lẽ một số dụng cụ đang làm điều này? Điều này có đúng trên một bản sao mới?
Cameron Tacklind

10

Tôi sẽ đề nghị bạn không sử dụng symlink trong repo '. Lưu trữ nội dung thực tế bên trong repo 'và sau đó đặt symlink ra bên cạnh repo' trỏ đến nội dung đó.

Vì vậy, giả sử bạn đang sử dụng repo 'để so sánh việc lưu trữ trang web của bạn trên * nix với lưu trữ trên win. Lưu trữ nội dung trong repo của bạn ', giả sử /httpRepoContentc:\httpRepoContentđây là thư mục được đồng bộ hóa qua GIT, SVN, v.v.

Sau đó, thay thế thư mục nội dung của máy chủ web của bạn ( /var/wwwc:\program files\web server\www{tên không thực sự quan trọng, hãy chỉnh sửa nếu bạn phải}) bằng một liên kết tượng trưng đến nội dung trong repo của bạn '. Các máy chủ web sẽ thấy nội dung thực sự ở vị trí 'bên phải', nhưng bạn có thể sử dụng kiểm soát nguồn của mình.

Tuy nhiên, nếu bạn cần sử dụng các liên kết tượng trưng trong repo ', bạn sẽ cần xem xét một cái gì đó giống như một số tập lệnh cam kết trước / sau. Tôi biết bạn có thể sử dụng chúng để thực hiện mọi việc, chẳng hạn như các tệp mã phân tích cú pháp thông qua một trình định dạng chẳng hạn, vì vậy có thể chuyển đổi các liên kết tượng trưng giữa các nền tảng.

nếu bất kỳ ai biết một nơi tốt để tìm hiểu cách thực hiện các tập lệnh này cho các điều khiển nguồn chung, SVN GIT MG, thì vui lòng thêm nhận xét.


Cuối cùng, tôi đã chọn cách tiếp cận này để tạo thư mục symlink-out và tạo các liên kết tượng trưng đến nơi tệp gốc được sử dụng. Cách tiếp cận khác không hoạt động ngay cả sau khi tôi thay đổi cài đặt .git / config core.symlinks = true. Chỉ tệp liên kết tượng trưng được lưu vào repo chứ không phải dữ liệu. Cũng có vấn đề với dấu thời gian của thư mục trên liên kết tượng trưng để git bash không bao giờ nhìn thấy khi một tệp thay đổi trong thư mục.
Trứng

@Eggs những gì bạn có thể đã nhìn thấy, tôi đoán, đó là liên kết nằm trong repo, và vì vậy git đã lưu nó, mô phỏng. Tuy nhiên, vấn đề là mục tiêu nằm ngoài repo và git không theo liên kết đến dữ liệu đích. Trên linux bạn có một loại liên kết sẽ hoạt động cho việc này, về cơ bản, đó là cho phép bạn có hai đường dẫn đến cùng một dữ liệu được lưu trữ trên đĩa; Tôi có một cảm giác cửa sổ mới có thể làm điều này bây giờ. Dù bằng cách nào, tôi vẫn không nghĩ rằng nó sẽ làm những gì mọi người muốn.
thecoshman

@thecoshman Đây không phải là một giải pháp, mà là một cách giải quyết. Tuy nhiên, đôi khi đây không phải là một lựa chọn. Tôi có một kho lưu trữ với git-annex tất cả các kiến ​​trúc của nó hoạt động vì các liên kết tượng trưng.
marcelo.guedes

8

Đối với những người sử dụng CygWin trên Vista, Win7 hoặc cao hơn, gitlệnh gốc có thể tạo các liên kết tượng trưng "phù hợp" được các ứng dụng Windows như Android Studio nhận ra . Bạn chỉ cần đặt CYGWINbiến môi trường để bao gồm winsymlinks:nativehoặc winsymlinks:nativestrictnhư vậy:

export CYGWIN="$CYGWIN winsymlinks:native"

Nhược điểm của điều này (và một điều quan trọng ở đó) là trình bao CygWin phải là "Chạy với tư cách Quản trị viên" để nó có các quyền hệ điều hành cần thiết để tạo các loại liên kết tượng trưng đó. Tuy nhiên, khi chúng được tạo, không có quyền đặc biệt nào được yêu cầu để sử dụng chúng. Miễn là họ không thay đổi trong kho lưu trữ bởi nhà phát triển khác, gitsau đó sẽ chạy tốt với quyền người dùng bình thường.

Cá nhân, tôi sử dụng này chỉ cho symlink được lèo lái bởi các ứng dụng Windows (tức là phi Cygwin) vì khó khăn thêm này.

Để biết thêm thông tin về tùy chọn này, hãy xem câu hỏi SO này: Cách tạo liên kết tượng trưng với cygwin trong Windows 7


6

Đây là một tập lệnh bó để chuyển đổi các liên kết tượng trưng trong kho lưu trữ, chỉ dành cho các tệp, dựa trên câu trả lời của Josh Lee. Tập lệnh với một số kiểm tra bổ sung cho quyền quản trị viên là tại 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

Một câu trả lời không có giấy tờ thực sự không được sử dụng nhiều khi đã có những câu trả lời dài dòng và dài dòng như vậy.
Xennex81

4

Tôi sử dụng liên kết sym mọi lúc giữa thư mục gốc của tài liệu và thư mục git repo. Tôi thích giữ chúng riêng biệt. Trên windows tôi sử dụng tùy chọn mklink / j. Ngã ba dường như để cho git cư xử bình thường:

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

ví dụ:

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


2
Hãy cẩn thận với Windows Explorer và các mối nối; nó không phân biệt các điểm nối với vị trí cơ sở và việc xóa sẽ tái diễn vào mục tiêu và xóa nội dung của nó, trong khi việc xóa một liên kết tượng trưng sẽ chỉ xóa liên kết tượng trưng. Chỉ là một cái bẫy cho người không sẵn sàng.
Lawrence Dol

5
Trên thực tế, chỉ thử nghiệm điều này trên Windows7 mới nhất và nó không còn thực hiện được nữa, vì vậy việc xử lý các mối nối đã được cải thiện đôi khi trong vài năm qua.
Lawrence Dol

3

Tôi đang tìm kiếm một giải pháp dễ dàng để đối phó với các liên kết tượng trưng unix trên windows. Cảm ơn bạn rất nhiều vì các bí danh Git ở trên. Có một tối ưu hóa nhỏ có thể được thực hiện đối với các liên kết rm để nó không xóa các tệp trong thư mục đích trong trường hợp bí danh được chạy lần thứ hai một cách tình cờ. Vui lòng quan sát điều kiện if mới trong vòng lặp để đảm bảo tệp chưa phải là liên kết đến thư mục trước khi logic được chạy.

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

Một mẹo đơn giản chúng tôi sử dụng là chỉ gọi git add --allhai lần liên tiếp.

Ví dụ: các lệnh gọi cam kết Windows 7 của chúng tôi:

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

Việc thêm đầu tiên coi liên kết là văn bản và thêm các thư mục để xóa.

Phần bổ sung thứ hai đi qua liên kết một cách chính xác và hoàn tác xóa bằng cách khôi phục các tệp.

Nó kém thanh lịch hơn một số giải pháp được đề xuất khác nhưng nó là một sửa chữa đơn giản cho một số môi trường kế thừa của chúng tôi có thêm các liên kết tượng trưng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.