Windows 中的 Git 符号链接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5917249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Git Symlinks in Windows
提问by Ken Hirakawa
Our developers use a mix of Windows and Unix based OS's. Therefore, symlinks created on Unix machines become a problem for Windows developers. In windows (msysgit), the symlink is converted to a text file with a path to the file it points to. Instead, I'd like to convert the symlink into an actual Windows symlink.
我们的开发人员混合使用基于 Windows 和 Unix 的操作系统。因此,在 Unix 机器上创建的符号链接成为 Windows 开发人员的一个问题。在 windows (msysgit) 中,符号链接被转换为带有指向文件路径的文本文件。相反,我想将符号链接转换为实际的 Windows 符号链接。
The (updated) solution I have to this is:
我必须对此的(更新的)解决方案是:
- Write a post-checkout script that will recursively look for "symlink" text files.
- Replace them with windows symlink (using mklink) with same name and extension as dummy "symlink"
- Ignore these windows symlink by adding entry into .git/info/exclude
- 编写一个结帐后脚本,该脚本将递归查找“符号链接”文本文件。
- 将它们替换为与虚拟“符号链接”具有相同名称和扩展名的 Windows 符号链接(使用 mklink)
- 通过在 .git/info/exclude 中添加条目来忽略这些窗口符号链接
I have not implemented this, but I believe this is a solid approach to this problem.
我还没有实现这个,但我相信这是解决这个问题的可靠方法。
Questions:
问题:
- What, if any, downsides do you see to this approach?
- Is this post-checkout script even implementable? i.e. can I recursively find out the dummy "symlink" files git creates?
- Has anybody already worked on such script?
- 您认为这种方法有哪些缺点(如果有)?
- 这个结账后脚本甚至可以实现吗?即我可以递归地找出 git 创建的虚拟“符号链接”文件吗?
- 有没有人已经研究过这样的脚本?
采纳答案by Josh Lee
You can find the symlinks by looking for files that have a mode of 120000
, possibly with this command:
您可以通过查找模式为 的文件来找到符号链接120000
,可能使用以下命令:
git ls-files -s | awk '/120000/{print }'
Once you replace the links, I would recommend marking them as unchanged with git update-index --assume-unchanged
, rather than listing them in .git/info/exclude
.
替换链接后,我建议将它们标记为未更改git update-index --assume-unchanged
,而不是将它们列在.git/info/exclude
.
回答by Mark G.
I was asking this exact same question a while back (not here, just in general) and ended up coming up with a very similar solution to OP's proposition. First I'll provide direct answers to questions 1 2 & 3, and then I'll post the solution I ended up using.
不久前我问了这个完全相同的问题(不是在这里,只是一般情况下),最终提出了一个与 OP 命题非常相似的解决方案。首先,我将直接回答问题 1 2 和 3,然后我将发布我最终使用的解决方案。
- There are indeed a few downsides to the proposed solution, mainly regarding an increased potential for repository pollution, or accidentally adding duplicate files while they're in their "Windows symlink" states. (More on this under "limitations" below.)
- Yes, a post-checkout script is implementable! Maybe not as a literal post-
git checkout
step, but the solution below has met my needs well enough that a literal post-checkout script wasn't necessary. - Yes!
- 所提议的解决方案确实有一些缺点,主要是关于存储库污染的可能性增加,或者在它们处于“Windows 符号链接”状态时意外添加了重复文件。(在下面的“限制”中详细介绍了这一点。)
- 是的,结账后脚本是可以实现的!也许不是字面意义上的后
git checkout
步骤,但下面的解决方案已经很好地满足了我的需求,因此不需要字面的结账后脚本。 - 是的!
The Solution:
解决方案:
Our developers are in much the same situation as OP's: a mixture of Windows and Unix-like hosts, repositories and submodules with many git symlinks, and no native support (yet) in the release version of MsysGit for intelligently handling these symlinks on Windows hosts.
我们的开发人员与 OP 的情况大致相同:混合了 Windows 和类 Unix 主机、存储库和带有许多 git 符号链接的子模块,并且在 MsysGit 的发布版本中(还)没有本机支持来智能地处理 Windows 主机上的这些符号链接.
Thanks to Josh Lee for pointing out the fact that git commits symlinks with special filemode 120000
. With this information it's possible to add a few git aliases that allow for the creation and manipulation of git symlinks on Windows hosts.
感谢 Josh Lee 指出 git 提交带有特殊文件模式的符号链接的事实120000
。有了这些信息,就可以添加一些 git 别名,允许在 Windows 主机上创建和操作 git 符号链接。
Creating git symlinks on Windows
git config --global alias.add-symlink '!'"$(cat <<'ETX' __git_add_symlink() { if [ $# -ne 2 ] || [ "" = "-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' [ "" = "-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 )"
Usage:
git add-symlink <source_file_or_dir> <target_symlink>
, where the argument corresponding to the source file or directory must take the form of a path relative to the target symlink.You can use this alias the same way you would normally useln
.E.g., the repository tree:
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/)
Can be created on Windows as follows:
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"
Replacing git symlinks with NTFS hardlinks+junctions
git config --global alias.rm-symlinks '!'"$(cat <<'ETX' __git_rm_symlinks() { case "" 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]\)_:_;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 = ; next } { print } END { exit status_code } ' } __git_rm_symlinks ETX )" git config --global alias.rm-symlink '!git rm-symlinks' # for back-compat.
Usage:
git rm-symlinks [symlink] [symlink] [...]
This alias can remove git symlinks one-by-one or all-at-once in one fell swoop. Symlinks will be replaced with NTFS hardlinks (in the case of files) or NTFS junctions (in the case of directories). The benefit of using hardlinks+junctions over "true" NTFS symlinks is that elevated UAC permissions are not required in order for them to be created.
To remove symlinks from submodules, just use git's built-in support for iterating over them:
git submodule foreach --recursive git rm-symlinks
But, for every drastic action like this, a reversal is nice to have...
Restoring git symlinks on Windows
git config --global alias.checkout-symlinks '!'"$(cat <<'ETX' __git_checkout_symlinks() { case "" 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'
Usage:
git checkout-symlinks [symlink] [symlink] [...]
, which undoesgit rm-symlinks
, effectively restoring the repository to its natural state (except for your changes, which shouldstay intact).And for submodules:
git submodule foreach --recursive git checkout-symlinks
Limitations:
Directories/files/symlinks with spaces in their paths should work. But tabs or newlines? YMMV… (By this I mean: don't do that, because it will notwork.)
If yourself or others forget to
git checkout-symlinks
before doing something with potentially wide-sweeping consequences likegit add -A
, the local repository could end up in a polluted state.Using our "example repo" from before:
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 #
Whoops...
For this reason, it's nice to include these aliases as steps to perform for Windows users before-and-after building a project, rather than after checkout or before pushing. But each situation is different. These aliases have been useful enough for me that a true post-checkout solution hasn't been necessary.
在 Windows 上创建 git 符号链接
git config --global alias.add-symlink '!'"$(cat <<'ETX' __git_add_symlink() { if [ $# -ne 2 ] || [ "" = "-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' [ "" = "-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>
,其中与源文件或目录对应的参数必须采用相对于目标符号链接的路径形式。您可以像通常使用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"
用 NTFS 硬链接+连接替换 git 符号链接
git config --global alias.rm-symlinks '!'"$(cat <<'ETX' __git_rm_symlinks() { case "" 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]\)_:_;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 = ; 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 符号链接一个一个或一次全部删除。符号链接将替换为 NTFS 硬链接(在文件的情况下)或 NTFS 连接(在目录的情况下)。使用硬链接+连接而不是“真正的”NTFS 符号链接的好处是不需要提升的 UAC 权限来创建它们。
要从子模块中删除符号链接,只需使用 git 的内置支持来迭代它们:
git submodule foreach --recursive git rm-symlinks
但是,对于像这样的每一个剧烈动作,逆转是很好的......
在 Windows 上恢复 git 符号链接
git config --global alias.checkout-symlinks '!'"$(cat <<'ETX' __git_checkout_symlinks() { case "" 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
,有效地将存储库恢复到其自然状态(除了您的更改,它应该保持完整)。对于子模块:
git submodule foreach --recursive git checkout-symlinks
限制:
路径中带有空格的目录/文件/符号链接应该可以工作。但是制表符或换行符?因人而异...(我的意思是:不这样做,因为它不会工作。)
如果你自己或其他人
git checkout-symlinks
在做一些可能产生广泛后果的事情之前忘记了,比如git add -A
,本地存储库可能最终处于污染状态。使用我们之前的“示例存储库”:
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 用户在构建项目之前和之后执行的步骤,而不是在签出之后或推送之前执行。但每种情况都不同。这些别名对我来说已经足够有用了,不需要真正的结账后解决方案。
Hope that helps!
希望有帮助!
References:
参考:
http://git-scm.com/book/en/Git-Internals-Git-Objects
http://git-scm.com/book/en/Git-Internals-Git-Objects
http://technet.microsoft.com/en-us/library/cc753194
http://technet.microsoft.com/en-us/library/cc753194
Last Update: 2019-03-13
最后更新:2019-03-13
- POSIX compliance (well, except for those
mklink
calls, of course) — no more Bashisms! - Directories and files with spaces in them are supported.
- Zero and non-zero exit status codes (for communicating success/failure of the requested command, respectively) are now properly preserved/returned.
- The
add-symlink
alias now works more like ln(1)and can be used from any directory in the repository, not just the repository's root directory. - The
rm-symlink
alias (singular) has been superseded by therm-symlinks
alias (plural), which now accepts multiple arguments (or no arguments at all, which finds all of the symlinks throughout the repository, as before) for selectively transforming git symlinks into NTFS hardlinks+junctions. - The
checkout-symlinks
alias has also been updated to accept multiple arguments (or none at all, == everything) for selective reversal of the aforementioned transformations.
- POSIX 合规性(
mklink
当然,除了那些调用)——不再是Bashisms! - 支持带有空格的目录和文件。
- 现在可以正确保留/返回零和非零退出状态代码(分别用于传达所请求命令的成功/失败)。
- 该
add-symlink
别名现在更像LN(1) ,可以从存储库中的任何目录中,而不仅仅是储存库的根目录中。 - 的
rm-symlink
别名(单数)已被取代由rm-symlinks
用于选择性地变换的git符号链接到NTFS硬链接+结别名(复数),它现在可以接受多个参数(或根本没有参数,它找到所有符号链接的整个库,如前) . - 该
checkout-symlinks
别名也已更新,以接受多个参数(在全或无,一切==)对上述转变的选择性逆转。
Final Note:While I did test loading and running these aliases using Bash 3.2 (and even 3.1) for those who may still be stuck on such ancient versions for any number of reasons, be aware that versions as old as these are notorious for their parser bugs. If you experience issues while trying to install any of these aliases, the first thing you should look into is upgrading your shell (for Bash, check the version with CTRL+X, CTRL+V). Alternatively, if you're trying to install them by pasting them into your terminal emulator, you may have more luck pasting them into a file and sourcing it instead, e.g. as
最后说明:虽然我确实使用 Bash 3.2(甚至 3.1)测试加载和运行这些别名,但对于那些可能由于各种原因仍然停留在这些古老版本上的人,请注意,像这些一样古老的版本因其解析器而臭名昭著错误。如果您在尝试安装这些别名时遇到问题,您应该首先考虑的是升级您的 shell(对于 Bash,请使用 CTRL+X、CTRL+V 检查版本)。或者,如果您尝试通过将它们粘贴到终端仿真器中来安装它们,您可能会更幸运地将它们粘贴到文件中并获取它,例如作为
. ./git-win-symlinks.sh
Good luck!
祝你好运!
回答by sirlunchalot
The most recent version of git scm(testet 2.11.1) allows to enable symbolic links. But you have to clone the repository with the symlinks again git clone -c core.symlinks=true <URL>
. You need to run this command with administrator rights. It is also possible to create symlinks on Windows with mklink.
Check out the wiki.
最新版本的git scm(testet 2.11.1) 允许启用符号链接。但是您必须再次使用符号链接克隆存储库git clone -c core.symlinks=true <URL>
。您需要以管理员权限运行此命令。也可以使用 mklink 在 Windows 上创建符号链接。查看维基。
回答by Simon
so as things have changed with GIT since alot of these answers were posted here is the correct instructions to get symlinks working correctly in windows as of
因此,由于 GIT 的情况发生了变化,因为这里发布了很多这些答案,这是使符号链接在 Windows 中正常工作的正确说明
AUGUST 2018
2018 年 8 月
1. Make sure git is installed with symlink support
1.确保安装了支持符号链接的git
2. Tell Bash to create hardlinks instead of symlinks
2. 告诉 Bash 创建硬链接而不是符号链接
EDIT -- (git folder)/etc/bash.bashrc
编辑——(git文件夹)/etc/bash.bashrc
ADD TO BOTTOM - MSYS=winsymlinks:nativestrict
添加到底部 - MSYS=winsymlinks:nativestrict
3. Set git config to use symlinks
3. 设置 git config 使用符号链接
git config core.symlinks true
or
或者
git clone -c core.symlinks=true <URL>
NOTE: I have tried adding this to the global git config and at the moment it is not working for me so I recommend adding this to each repo...
注意:我已经尝试将它添加到全局 git 配置中,但目前它对我不起作用,所以我建议将它添加到每个 repo ...
4. pull the repo
4.拉取repo
NOTE: Unless you have enabled developer mode in the latest version of Windows 10, you need to run bash as administrator to create symlinks
注意:除非您在最新版本的 Windows 10 中启用了开发者模式,否则您需要以管理员身份运行 bash 来创建符号链接
5. Reset all Symlinks(optional) If you have an existing repo, or are using submodules you may find that the symlinks are not being created correctly so to refresh all the symlinks in the repo you can run these commands.
5. 重置所有符号链接(可选)如果您有一个现有的存储库,或者正在使用子模块,您可能会发现没有正确创建符号链接,因此要刷新存储库中的所有符号链接,您可以运行这些命令。
find -type l -delete
git reset --hard
NOTE: this will reset any changes since last commit so make sure you have committed first
注意:这将重置自上次提交以来的所有更改,因此请确保您已先提交
回答by djs
It ought to be implemented in msysgit, but there are two downsides:
它应该在 msysgit 中实现,但有两个缺点:
- Symbolic links are only available in Windows Vista and later (should not be an issue in 2011, and yet it is...), since older versions only support directory junctions.
- (the big one) Microsoft considers symbolic links a security risk and so only administrators can create them by default. You'll need to elevate privileges of the git process or use fstool to change this behavior on every machine you work on.
- 符号链接仅在 Windows Vista 及更高版本中可用(在 2011 年应该不是问题,但它是......),因为旧版本仅支持目录连接。
- (最重要的)微软认为符号链接是一种安全风险,因此默认情况下只有管理员可以创建它们。您需要提升 git 进程的权限或使用 fstool 在您工作的每台机器上更改此行为。
I did a quick search and there is work being actively done on this, see issue 224.
我进行了快速搜索,正在积极开展这方面的工作,请参阅 issue 224。
回答by Orangutech
Short answer: They are now supported nicely, if you can enable developer mode.
简短回答:如果您可以启用开发人员模式,它们现在得到了很好的支持。
From https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/
来自https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/
Now in Windows 10 Creators Update, a user (with admin rights) can first enable Developer Mode, and then any user on the machine can run the mklink command without elevating a command-line console.
What drove this change? The availability and use of symlinks is a big deal to modern developers:
Many popular development tools like git and package managers like npm recognize and persist symlinks when creating repos or packages, respectively. When those repos or packages are then restored elsewhere, the symlinks are also restored, ensuring disk space (and the user's time) isn't wasted.
现在在 Windows 10 创意者更新中,用户(具有管理员权限)可以先启用开发者模式,然后机器上的任何用户都可以运行 mklink 命令,而无需提升命令行控制台。
是什么推动了这种变化?符号链接的可用性和使用对现代开发人员来说是一件大事:
许多流行的开发工具(如 git)和包管理器(如 npm)在创建存储库或包时分别识别和保留符号链接。当这些存储库或包随后在其他地方恢复时,符号链接也会恢复,确保不会浪费磁盘空间(和用户的时间)。
Easy to overlook with all the other announcements of the "Creator's update", but if you enable Developer Mode, you can create symlinks without elevated privileges. You might have to re-install git and make sure symlink support is enabled, as it's not by default.
“Creator's update”的所有其他公告很容易被忽视,但是如果您启用了开发人员模式,则无需提升权限即可创建符号链接。您可能需要重新安装 git 并确保启用了符号链接支持,因为默认情况下它不是。
回答by thecoshman
I would suggest you don't use symlinks within the repo'. Store the actual content inside the repo' and then place symlinks out side the repo' that point to the content.
我建议你不要在 repo' 中使用符号链接。将实际内容存储在 repo' 中,然后将符号链接放置在 repo' 之外,指向该内容。
So lets say you are using a repo' to compare hosting your site on *nix with hosting on win. Store the content in your repo', lets say /httpRepoContent
and c:\httpRepoContent
with this being the folder that is synced via GIT, SVN etc.
因此,假设您正在使用 repo' 来比较在 *nix 上托管您的网站与在 win 上托管。存储在您的回购协议”的内容,可以说/httpRepoContent
和c:\httpRepoContent
这个被认为是通过GIT,SVN等同步的文件夹
Then, replace the content folder of you web server (/var/www
and c:\program files\web server\www
{names don't really matter, edit if you must}) with a symbolic link to the content in your repo'. The web servers will see the content as actually in the 'right' place, but you get to use your source control.
然后,用指向存储库中内容的符号链接替换您的 Web 服务器的内容文件夹(/var/www
并且c:\program files\web server\www
{名称并不重要,如果必须,请编辑})。Web 服务器会将内容视为实际位于“正确”位置的内容,但您可以使用源代码控制。
However, if you need to use symlinks with in the repo', you will need to look into something like some sort of pre/post commit scripts. I know you can use them to do things, such as parse code files through a formatter for example, so it should be possible to convert the symlinks between platforms.
但是,如果您需要在 repo' 中使用符号链接,您将需要查看某种类型的提交前/提交后脚本。我知道您可以使用它们来做一些事情,例如通过格式化程序解析代码文件,因此应该可以在平台之间转换符号链接。
if any one knows a good place to learn how to do these scripts for the common source controls, SVN GIT MG, then please do add a comment.
如果有人知道学习如何为公共源代码控件 SVN GIT MG 编写这些脚本的好地方,请添加评论。
回答by Brian White
For those using CygWinon Vista, Win7, or above, the native git
command can create "proper" symlinks that are recognized by Windows apps such as Android Studio. You just need to set the CYGWIN
environment variable to include winsymlinks:native
or winsymlinks:nativestrict
as such:
对于在 Vista、Win7 或更高版本上使用CygWin的用户,本机git
命令可以创建 Windows 应用程序(例如Android Studio )识别的“正确”符号链接。您只需要将CYGWIN
环境变量设置为包含winsymlinks:native
或winsymlinks:nativestrict
这样:
export CYGWIN="$CYGWIN winsymlinks:native"
The downside to this (and a significant one at that) is that the CygWin shell has to be "Run as Administrator" in order for it to have the OS permissions required to create those kind of symlinks. Once they're created, though, no special permissions are required to usethem. As long they aren't changed in the repository by another developer, git
thereafter runs fine with normal user permissions.
这样做的缺点(也是一个重要的缺点)是 CygWin shell 必须“以管理员身份运行”才能拥有创建此类符号链接所需的操作系统权限。但是,一旦它们被创建,就不需要特殊的权限来使用它们。只要其他开发人员没有在存储库中更改它们,git
此后就可以在普通用户权限下正常运行。
Personally, I use this onlyfor symlinks that are navigated by Windows apps (i.e. non-CygWin) because of this added difficulty.
就我个人而言,我仅将它用于由 Windows 应用程序(即非 CygWin)导航的符号链接,因为这增加了难度。
For more information on this option, see this SO question: How to make symbolic link with cygwin in Windows 7
有关此选项的更多信息,请参阅此问题:如何在 Windows 7 中使用 cygwin 进行符号链接
回答by Cameron Tacklind
2020 Answer
2020 答案
- Enable "Developer mode" in Windows 10 -- gives
mklink
permissions - Ensure symlinks are enabled in git
git config --global core.symlinks true
- orcheck the checkbox when installing msysgit
- 在 Windows 10 中启用“开发者模式”——授予
mklink
权限 - 确保在 git 中启用符号链接
git config --global core.symlinks true
- 或在安装 msysgit 时选中复选框
Switching branches will force the recreation of missing symlinks.
切换分支将强制重新创建丢失的符号链接。
Be careful, support for Symlinks on Windows with some other Git clients is not complete. Notably GitKraken.
请注意,对 Windows 上的符号链接与其他一些 Git 客户端的支持尚不完整。尤其是 GitKraken。
回答by Quazistax
Here is a batch script for converting symlinks in repository, for files only, based on Josh Lee's answer. Script with some additional check for administrator rights is at https://gist.github.com/Quazistax/8daf09080bf54b4c7641.
这是一个批处理脚本,用于在存储库中转换符号链接,仅用于文件,基于 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