Ken*_*awa 227 windows git symlink
我们的开发人员使用基于Windows和Unix的操作系统.因此,在Unix机器上创建的符号链接成为Windows开发人员的问题.在windows(msysgit)中,符号链接将转换为文本文件,其中包含指向其所指向文件的路径.相反,我想将符号链接转换为实际的Windows符号链接.
我需要的(更新的)解决方案是:
我没有实现这个,但我相信这是解决这个问题的可靠方法.
问题:
Mar*_* G. 182
我曾经问过这个完全相同的问题(不是在这里,只是一般),最终提出了一个非常类似于OP的主张的解决方案.首先,我将提供问题1 2和3的直接答案,然后我将发布我最终使用的解决方案.
git checkout
步骤,但下面的解决方案已经很好地满足了我的需求,因此不需要文字的结账后脚本.我们的开发人员与OP的情况大致相同:Windows和基于Unix的主机,具有许多git符号链接的存储库和子模块的混合,并且在MsysGit的发行版本中没有本机支持(用于在Windows主机上智能地处理这些符号链接) .
感谢Josh Lee指出git使用特殊的filemode提交符号链接的事实120000
.有了这些信息,就可以添加一些git别名,允许在Windows主机上创建和操作git符号链接.
在Windows上创建git符号链接
更新2014-11-12(见下文)
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
)"
Run Code Online (Sandbox Code Playgroud)
使用方法:git add-symlink <source_file_or_dir> <target_symlink>
,其中ln
是相对于参考(相对于git checkout-symlinks [symlink] [symlink] [...]
)的文件或目录的当前位置链接到,并且git rm-symlinks
是一个相对参考(相对于库的根),以链接的期望的目的地.
例如,存储库树:
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/)
Run Code Online (Sandbox Code Playgroud)
可以在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"
Run Code Online (Sandbox Code Playgroud)用NTFS hardlinks + 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 config --global alias.rm-symlink '!git rm-symlinks' # for back-compat.
Run Code Online (Sandbox Code Playgroud)
用法:
git rm-symlinks [symlink] [symlink] [...]
Run Code Online (Sandbox Code Playgroud)
这将逐个删除git符号链接,将其替换为NTFS硬链接(在文件的情况下)或NTFS联结(在目录的情况下).在"真正的"NTFS符号链接上使用硬链接+联结的好处是,为了创建它们,不需要提升的UAC权限.最后,在您自己的闲暇时,您可以选择取消标记为"已删除"的符号链接(或不包含)git checkout-symlinks
.
为方便起见,您还可以运行:
git submodule foreach --recursive git rm-symlinks
Run Code Online (Sandbox Code Playgroud)
这将删除当前存储库中的所有git符号链接,根据需要将它们替换为硬链接+联结,并自动标记要忽略的更改git add -A
.
要从子模块中删除符号链接,只需使用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 config --global alias.co-symlinks '!git checkout-symlinks'
Run Code Online (Sandbox Code Playgroud)
但是,对于像这样的每一个激烈的行动,逆转是很好的...
在Windows上恢复git符号链接
git submodule foreach --recursive git checkout-symlinks
Run Code Online (Sandbox Code Playgroud)
用法:mklink
,撤消add-symlink
,有效地将存储库恢复到其自然状态(除了您的更改,应保持完整).
对于子模块:
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
#
Run Code Online (Sandbox Code Playgroud)限制:
如果人们rm-symlink
在做某事之前忘了rm-symlinks
,他们就会污染回购!
使用之前的"示例回购":
. ./git-win-symlinks.sh
Run Code Online (Sandbox Code Playgroud)
哎呦...
因此,将这些别名作为在构建项目之前和之后为Windows用户执行的步骤而不是在结帐之后或推送之前包含这些别名是很好的.但每种情况都不同.这些别名对我来说足够有用,因此没有必要使用真正的结账后解决方案.
希望有所帮助!
参考文献:
http://git-scm.com/book/en/Git-Internals-Git-Objects
http://technet.microsoft.com/en-us/library/cc753194
UPDATE 2014年11月12日:因为我个人只做过大量使用的checkout-symlinks
和git checkout
上面的别名,我设法忽视在一个相当讨厌的错误120000
的别名.以前,git add-symlink <source_file_or_dir> <target_symlink>
没有传递给ln
负责创建git symlink文件的语句,该文件稍后将作为操作的一部分添加到临时区域git checkout-symlinks [symlink] [symlink] [...]
.这意味着git rm-symlinks
在使用创建的所有git符号链接中添加了一个尾随换行符(在Windows主机上)git checkout-symlinks
.虽然这些git符号链接在Windows主机上仍然是"可移动的" git add -A
,但是如果它们曾经被提交到公共存储库并且后来克隆在真正的基于posix的系统上,那么这些链接总是会在另一方面被破坏.此问题已得到修复,mklink
现在应按预期工作.
Jos*_*Lee 97
您可以通过查找具有以下模式的文件来查找符号链接120000
:
git ls-files -s | awk '/120000/{print $4}'
Run Code Online (Sandbox Code Playgroud)
更换链接后,我建议将它们标记为未更改git update-index --assume-unchanged
,而不是将其列入.git/info/exclude
.
sir*_*lot 65
最新版本的git scm(testet 2.11.1)允许启用符号链接.但是你必须再次使用符号链接克隆存储库git clone -c core.symlinks=true <URL>
.您需要使用管理员权限运行此命令.也可以在Windows上使用mklink创建符号链接.看看维基.
Cam*_*ind 53
mklink
权限git config --global core.symlinks true
切换分支将强制重新创建丢失的符号链接。
请注意,Windows 上的 git 中对符号链接的支持相对较新。有一些错误仍然影响一些 git 客户端。值得注意的是,..
由于libgit2中的(固定) 回归,在某些程序中,带有相对 ( ) 路径的符号链接被破坏了。例如,GitKraken 受此影响。
djs*_*djs 15
它应该在msysgit中实现,但有两个缺点:
我做了一个快速搜索,正在积极完成这项工作,请参阅问题224.
Sim*_*mon 14
因为GIT已经改变了,因为这里发布了很多这些答案是正确的说明,使得符号链接在Windows中正常工作
2018年8月
1.确保安装了git并支持符号链接
2.告诉Bash创建硬链接而不是符号链接
编辑 - (git文件夹)/etc/bash.bashrc
添加到底部 - MSYS=winsymlinks:nativestrict
3.设置git config以使用符号链接
git config core.symlinks true
Run Code Online (Sandbox Code Playgroud)
要么
git clone -c core.symlinks=true <URL>
Run Code Online (Sandbox Code Playgroud)
注意:我已经尝试将其添加到全局git配置中,目前它不适合我,所以我建议将其添加到每个repo ...
4.拉回购
注意:除非您在最新版本的Windows 10中启用了开发人员模式,否则您需要以管理员身份运行bash以创建符号链接
5.重置所有符号链接(可选)如果您有现有的存储库或正在使用子模块,您可能会发现未正确创建符号链接,因此要刷新存储库中的所有符号链接,您可以运行这些命令.
find -type l -delete
git reset --hard
Run Code Online (Sandbox Code Playgroud)
注意:这将重置自上次提交以来的任何更改,因此请确保您已先提交
Ora*_*ech 11
简短回答:如果您可以启用开发人员模式,现在可以很好地支持它们.
来自https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/
现在,在Windows 10 Creators Update中,用户(具有管理员权限)可以首先启用开发人员模式,然后计算机上的任何用户都可以运行mklink命令而无需升级命令行控制台.
是什么推动了这一变化?符号链接的可用性和使用对于现代开发人员来说是一个大问题:
许多流行的开发工具,如git和包管理器,如npm,分别在创建repos或包时识别并保留符号链接.当那些repos或包然后在别处恢复时,符号链接也会被恢复,从而确保不浪费磁盘空间(以及用户的时间).
容易忽略"Creator更新"的所有其他声明,但如果启用开发者模式,则可以创建没有提升权限的符号链接.您可能必须重新安装并确保启用支持,因为默认情况下不支持.
the*_*man 10
我建议你不要在回购中使用符号链接'.将实际内容存储在repo'中,然后将符号链接放在指向内容的repo'旁边.
因此,假设您正在使用回购'比较在*nix上托管您的网站与在win上托管.存储在您的回购协议"的内容,可以说/httpRepoContent
和c:\httpRepoContent
这个被认为是通过GIT,SVN等同步的文件夹
然后,替换您的网络服务器的内容文件夹(/var/www
并且c:\program files\web server\www
{名称并不重要,如果必须,则进行编辑}),并使用指向回购中内容的符号链接.Web服务器会将内容视为实际位于"正确"的位置,但您可以使用源代码控制.
但是,如果您需要在repo'中使用符号链接,则需要查看某种类型的前/后提交脚本.我知道你可以使用它们来做事情,比如通过格式化程序解析代码文件,所以应该可以在平台之间转换符号链接.
如果有人知道如何为常见的源代码控制SVN GIT MG学习这些脚本,那么请添加评论.
对于在Vista,Win7或更高版本上使用CygWin的用户,本机git
命令可以创建由Windows应用程序(如Android Studio)识别的"正确"符号链接.您只需要将CYGWIN
环境变量设置为包含winsymlinks:native
或winsymlinks:nativestrict
如此:
export CYGWIN="$CYGWIN winsymlinks:native"
Run Code Online (Sandbox Code Playgroud)
这方面的缺点(以及一个重要的一点)是CygWin shell必须"以管理员身份运行"才能拥有创建这种符号链接所需的操作系统权限.但是,一旦创建它们,就不需要特殊权限来使用它们.只要其他开发人员在存储库中没有更改它们,git
之后就可以正常用户权限运行.
就个人而言,我仅将此用于由Windows应用程序(即非CygWin)导航的符号链接,因为这增加了难度.
有关此选项的更多信息,请参阅此问题:如何在Windows 7中与cygwin建立符号链接
我刚刚尝试了 Git 2.30.0(2020 年 12 月 28 日发布)。
这不是一个完整的答案,但仍然是一些有用的花絮。(随意蚕食你自己的答案。)
安装 Git for Windows 时有一个文档链接
这个链接带你到这里:https : //github.com/git-for-windows/git/wiki/Symbolic-Links——这是一个相当长的讨论。
只是为了强调这个 wiki 条目的一个重要方面:我不知道这一点,但是有几种方法表面上都是“某种”符号链接,但在技术层面上却非常不同:
stat
命令实际上识别为“符号链接”的东西。)符号链接也不断出现在发行说明中。从 2.30.0 开始,这里仍然列为“已知问题”:
在 1703 之前的 Windows 10 上,或关闭开发人员模式时,使用符号链接克隆存储库时需要特殊权限,因此默认情况下禁用对符号链接的支持。使用
git clone -c core.symlinks=true <URL>
,使之详情,请参阅这里。
这是一个基于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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
92110 次 |
最近记录: |