从git克隆后,Windows符号链接变得无效。
从git克隆后,Windows符号链接变得无效。
我们的开发人员使用混合的Windows和基于Unix的操作系统。因此,在Unix机器上创建的符号链接对Windows开发人员来说成为一个问题。在Windows中(MSysGit),符号链接被转换为一个包含指向文件路径的文本文件。相反,我希望将符号链接转换为实际的Windows符号链接。
我对此问题的(更新后的)解决方案是:
- 编写一个后检出脚本,递归查找“符号链接”文本文件。
- 用与虚拟“符号链接”相同的名称和扩展名的Windows符号链接替换它们(使用mklink)。
- 通过在文件.git/info/exclude中添加条目来忽略这些Windows符号链接。
我尚未实施此解决方案,但我相信这是一个解决这个问题的可靠方法。
- 您认为这种方法有哪些缺点(如果有的话)?
- 这个后检出脚本是否可行?即,我能否递归查找Git创建的虚拟“symlink”文件?
Windows symbolic link become invalid after clone from git
在使用git克隆项目时,Windows系统中的符号链接可能会变得无效。解决方法是找到这些无效的符号链接,并替换它们。
可以使用以下命令查找具有模式120000
的文件,可能是这样的命令:
git ls-files -s | awk '/120000/{print $4}'
一旦替换了这些链接,建议使用git update-index --assume-unchanged
将它们标记为未更改,而不是将它们列在.git/info/exclude
文件中。
如果您在msysgit中使用awk命令时遇到问题,可以将awk替换为gawk,其他情况下应该可以正常工作。
有人要求分享使用mklink在Windows上检查符号链接文本文件并将其替换为符号链接的脚本,但是--assume-unchanged
部分似乎无效。切换到另一个分支时,git会说符号链接文件已更改,需要先提交,但是git status命令却显示没有更改。对此有什么想法吗?
有人提供了一个PowerShell脚本,可以使用mklink来检查并替换符号链接:gist.github.com/ferventcoder/7995025。
有人指出上述脚本只是忽略了文件,而没有将其解析为应有的符号链接。
另外,这是两年前的评论,可能不适用于当前情况。
还有一种更可移植和技术上更准确的方法:git ls-files -s | grep '^12'
,但是对于脚本来说不太好用,因为它没有去除前三列数据,只留下了要操作的文件名列表。
还有更可移植的方法可以打印第四列,而不是使用GNU awk。例如:git ls-files -s | grep '^12' | cut -f2
(第二个以制表符分隔的列;其他列以空格分隔)。
对于Cygwin/bash的一行命令,可以将所有符号链接标记为未更改:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
。
在Windows上,符号链接存储了完整路径,因此每次检出项目时都需要创建自己的符号链接,已经在存储库中存在的版本是无用的。因此,与其将其标记为未更改,不如将其添加到.gitignore文件中更好,尽管我没有进行比较测试。
总结提出的一行代码的问题:如果文件名包含"120000",则失败(正则表达式需要一个^),如果符号链接文件名包含空格,则失败。Zenexer提供的使用grep和cut的解决方案没有这些问题。
Windows symbolic link become invalid after clone from git的问题出现的原因是:
1. Windows系统未启用开发人员模式,导致没有权限使用mklink命令创建符号链接。
2. 在git中未启用符号链接功能。
解决方法如下:
1. 在Windows 10/11中启用“开发人员模式”以获得mklink权限。
2. 在git中启用符号链接功能,可以选择以下任一方法:
- 在安装msysgit时勾选“使用符号链接”选项。
- 使用全局设置命令git config --global core.symlinks true
启用符号链接。
- 使用本地设置命令git config core.symlinks true
启用符号链接。
需要注意的是,由于Windows上对git的符号链接支持相对较新,一些git客户端仍然存在一些问题。特别是,由于libgit2中的回归问题,使用相对路径(..)的符号链接在某些程序中可能会损坏。例如,GitKraken受到此问题的影响,因为他们正在等待nodegit将libgit2从v0.x(存在回归问题)更新到v1.x(已修复)。
如果遇到符号链接丢失或损坏的情况,可以尝试以下方法进行修复:
- 使用git checkout -- path/to/symlink
命令进行checkout。
- 使用git restore -- path/to/symlink
命令进行恢复(适用于git v2.23.0及以上版本)。
- 切换分支(切换到其他分支再切回来)。
- 使用git reset --hard
命令进行硬重置。
- 删除本地仓库并重新克隆。
如果遇到问题,可以通过git config --show-scope --show-origin core.symlinks
命令查看符号链接配置的级别、配置文件和当前值。可能存在本地配置覆盖全局或系统设置的情况,可以使用git config --unset core.symlinks
命令清除本地设置,以使更高级别的设置生效。
另外,有用户反馈需要重新克隆仓库才能使符号链接正常工作。如果不想重新克隆,修复仓库的配置可能已足够。可以运行git config --unset core.symlinks
命令来清除仓库中的core.symlinks配置(注意没有--global选项)。
如果不想启用开发人员模式,也可以通过按下Win + R,输入gpedit.msc,打开本地组策略编辑器,在“本地策略”->“用户权限分配”->“创建符号链接”中添加用户账号来设置符号链接权限。
以上就是解决Windows从git克隆后符号链接失效的问题的方法。
在克隆git存储库后,Windows符号链接无效的问题可能是由于以下原因引起的:
1. Windows系统对符号链接的支持有限,无法正确处理git存储库中的符号链接。
2. 克隆git存储库时,符号链接的元数据可能没有正确地传输到Windows系统上。
针对这个问题,可以尝试以下解决方法:
1. 在Windows系统上更新mklink
命令的理解,并打开开发者模式。这可以通过在命令提示符中运行以下命令来实现:git config --global core.symlinks true
。
2. 创建一个git别名来处理符号链接。可以在git的全局配置中添加以下别名:
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>
命令来创建符号链接。其中,source_file_or_dir是相对于目标符号链接位置的路径。
3. 创建一个git别名来替换git符号链接为NTFS硬链接或junctions。可以在git的全局配置中添加以下别名:
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 rm-symlinks [symlink] [symlink] [...]
命令来替换git符号链接为NTFS硬链接或junctions。
4. 创建一个git别名来恢复git符号链接。可以在git的全局配置中添加以下别名:
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 checkout-symlinks [symlink] [symlink] [...]
命令来恢复git符号链接。
需要注意的是,使用这些解决方法可能存在一些限制:
1. 路径中含有空格的目录/文件/符号链接可能无法正常工作。
2. 如果在执行像git add -A
这样可能有广泛影响的操作之前忘记执行git checkout-symlinks
,本地存储库可能会处于污染状态。
为了避免这些限制,可以在Windows用户构建项目之前和之后,将这些别名作为步骤包含在内。