Windows下Git:检测仓库中应设为符号链接的文件及遍历指定类型对象
问题翻译
我的仓库里有很多文件和目录符号链接。克隆仓库时,得根据目标文件系统是否支持符号链接来决定操作:如果不支持(比如SMB网络驱动器),就用-c core.symlinks=false克隆,这时候Git会把符号链接检出成内容为链接目标的普通文本文件。我需要在post-checkout钩子中检测仓库里所有定义为符号链接,但当前文件系统中不是链接的文件。我试过git ls-files、git ls-remote、git ls-tree结合git cat-file这些底层命令,但没能成功检测对象/文件类型;对已知的符号链接执行git diff也没有差异提示。请问能不能检测仓库中应该是符号链接但当前检出不是的文件?怎么遍历仓库中特定类型的对象(比如所有文件、符号链接、目录)?
解决方案
一、检测应是符号链接但当前不是的文件
通过对比Git仓库记录的对象类型和本地文件系统的实际类型即可实现,具体步骤如下:
1. 筛选仓库中所有符号链接对象
Git用模式位120000标记符号链接对象,用git ls-tree递归遍历当前HEAD的树结构,筛选出对应条目:
git ls-tree -r HEAD | grep '^120000'
-r:递归遍历所有子目录HEAD:指定当前检出的分支/提交
2. 校验本地文件实际类型
对上面输出的每个路径,用系统命令test -L判断是否为符号链接,整合为脚本片段放入post-checkout钩子:
git ls-tree -r HEAD | grep '^120000' | while read mode type hash path; do if [ ! -L "$path" ]; then echo "文件 $path 应为符号链接,但当前是普通文件" fi done
关于之前方法失效的说明
git ls-files默认只输出路径,需加--stage参数才能看到模式位:git ls-files --stage | grep '^120000',同样能筛选仓库中的符号链接。git diff无提示是因为core.symlinks=false时,Git会把符号链接的目标路径当作文件内容,而仓库中符号链接对象的内容就是目标路径,Git认为本地文件与仓库内容一致,因此不显示差异。
二、遍历仓库中特定类型的对象
1. 遍历所有符号链接
除了git ls-tree,也可以用git ls-files --stage:
git ls-files --stage | grep '^120000' | awk '{print $4}'
2. 遍历所有普通文件
筛选模式位为100644(只读普通文件)或100755(可执行文件)的条目:
git ls-tree -r HEAD | grep '^100' | awk '{print $4}'
3. 遍历所有目录
Git中目录以树对象条目存在,模式位为040000:
git ls-tree -r HEAD | grep '^040000' | awk '{print $4}'
内容的提问来源于stack exchange,提问作者Bodenseematze
相关产品推荐
相关产品推荐

