仅检出文件夹,不包括文件。

4

Windows可以通过在文件夹上使用此命令来处理区分大小写的文件:

fsutil.exe file setCaseSensitiveInfo "C:\examplefolderpath" enable

然而,问题在于它不会自动应用于子文件夹... 有一种方法可以使用PowerShell将其应用于子文件夹(链接),但首先必须实际存在。因此,我正在寻找一种在实际下载任何文件之前检索git库的文件夹结构的方法。只有在创建了文件夹结构并运行了PowerShell命令后,我才想要检出文件。
是否有一种只使用git命令就能方便地完成这个任务的方法?
如果没有,是否有一种方式让PowerShell从一个裸的git存储库(使用git clone --bare)中检索文件夹结构并设置文件夹结构?(对于我正在开发的项目的旁系项目,了解如何使用Go进行操作也很有用,除非仅使用git命令就能完成此任务。但是,这并不像知道如何使用PowerShell那样重要。)

Git并不真正“处理”文件夹:相反,当它需要创建一个名为path/to/file的文件时,它会检查是否已经存在path/to,如果不存在,则通过创建path/to来让操作系统满意,以便操作系统可以在path/to中创建一个名为file的文件,尽管在Git的索引/暂存区级别上,Git认为这是一个名为path/to/file文件,包括正斜杠。正如bk2204所指出的那样,在内部,Git的树形数据结构确实记录了您想要的单个名称组件,因此,如果不是Git首先通过其索引传递这些内容,那么它将更容易。 - torek
让Git-for-Windows在最低级别上学会自己的“设置区分大小写”可能是更好的前进道路。这很容易添加一个配置旋钮,并拦截“创建新目录”函数。 - torek
为什么这被标记为 [tag:go]? - torek
@torek,我在最后一句中提到,如果git命令无法完成,拥有能够执行此操作的Go代码将非常有用,尽管与使用PowerShell进行操作相比,这不那么重要。我曾经在自己内心挣扎是否应该添加go标签,也许这样做是错误的决定。 - Vopel
2个回答

2
Git没有提供只检出目录而不是文件的方法。但是你有一些选项:
  • 使用WSL中的Git创建仓库,根据这篇文章,这意味着它们将自动变成区分大小写的。
  • 避免运行git checkout,使用git ls-tree -rd HEAD(或者其他版本号)查找文件层次结构,然后生成这些目录,然后再运行git checkout。但是请注意,PowerShell的管道已知会损坏通过它传递的数据,因此在使用Git时,这不是一个好主意。

如果你想让Git for Windows原生支持这个功能,你可以去他们的问题跟踪器并要求支持此特性。我不知道实现这个需要多少工作量,也找不到所需API的文档,因此无法确定是否可以合理地在Git中实现它。


3
我完全期望这样,Git也会如此。这是Unix和CMD的工作方式,发送原始字节的效用是很好理解的。考虑到有意修改通过管道传递的数据,我认为“损坏”正是我要找的词。仅仅因为决定是有意的,并不代表它是好的。 - bk2204
1
实际上,如果PowerShell想要进行数据转换,它应该有相应的命令:例如 cmd1 | 转换 | cmd2。 - torek
1
如果管道无法不经修改地呈现所接收的数据,它就会破坏数据。就是这么简单。 - jthill
@mklement0 不行,不能这样做。你甚至不知道 git show :.gitignore 在PowerShell中是否有效,或者 git ls-files 是否有效,因为文件名不一定都是相同的文本编码。 - jthill
@jthill,我已经清理了之前的评论,转而在下一个评论中提供了摘要,希望能够全面说明PowerShell管道中缺乏原始字节支持的情况。我还要求修改about_pipelines帮助主题,在GitHub文档问题#8446中进行修改。 - mklement0
显示剩余7条评论

0
感谢bk2204的答案指引我正确的方向...在使用``创建一个裸仓库之后,我可以使用这个函数创建目录结构:
function Invoke-GitCloneCS {
  [Alias('igccs')]
  param([Parameter(Mandatory)] $url)

  # Terminate function if user isn't admin
  if (${env:=::}) { 'Function must be ran as administrator!'; return }

  # Normalize URL so the variable ends in .git
  $url = ("$url" -replace '.git$') -replace '$','.git'

  # Derive repo name from $url
  $repo = $url.Split('/')[-1] -replace '.git$'

  git clone $url --no-checkout

  # Navigate to repo directory and apply setCaseSensitiveInfo to it
  Set-Location $repo -pv D | & { fsutil.exe file setCaseSensitiveInfo $D enable }

  # Retrieve the folder structure
  (git ls-tree --name-only -rd HEAD).ForEach({
    # Create each folder listed, and apply setCaseSensitiveInfo to it
    New-Item $_ -Type D -pv D | & { fsutil.exe file setCaseSensitiveInfo $D enable }})

  git checkout
  Set-Location ..
}

现在,这并不是完整的命令,我仍然需要处理所有的


看起来你没有完成你的回答。而且 ${env:=::} 如何作为一个测试函数是否正在以提升权限运行还不清楚。 - mklement0
Set-Location produces no output by default, so -pv D won't populate variable $D - unless you add -PassThru. In general, you don't need -pv (-PipelineVariable) to simply pass output downstream in a pipeline - use ForEach-Object (whose alias is %) instead, and refer to each input object via the automatic $_ variable; e.g. 'foo' | % { "[$_]" } - mklement0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接