仅针对整个项目检出特定文件类型的git命令

22

有没有一种方法可以对某些文件类型(.xlf)执行git checkout操作,并递归地遍历整个代码库?结果应该包含存储库的结构,即特定扩展名的文件夹和包含的文件。

Repo A

file.xlf
file.txt
level2/
    file2.xlf
    file2.txt
    level3/
        file3.xlf
        file3.txt 

提交代码后,仓库 B 看起来是这样的:

仓库 B

file.xlf
    /level2
    file2.xlf
        /level3
        file3.xlf

这是我目前为止的内容:

$ git checkout FETCH_HEAD -- '*.xlf'

这会提取根目录下所有 ".xlf" 文件,但不会递归到子目录。

感谢您的帮助。

6个回答

32

你不需要使用find或sed,你可以使用通配符,因为Git能够理解它们(不依赖于你的shell):

git checkout -- "*.xml"
引号将防止你的Shell在执行命令之前将其扩展为当前目录中的文件。

您还可以禁用Shell Glob扩展(使用bash):


set -f
git checkout -- *.xml

当然,这将不可避免地擦除您的更改!


这绝对是最干净的解决方案。 - mariocatch
如何匹配除了特定类型的文件之外的所有内容? - mmKALLL
1
这个可以递归执行吗?至少在Windows上不行。 - aoetalks
4
对于我来说,它是递归的。但仅限于使用 git checkout -- "*.xml"(从索引中签出)版本,git checkout HEAD -- "*.xml"(从分支名称签出)似乎不会递归地工作。 - Mariusz Pawelski
git checkout HEAD -- **/*.xml 是让你递归地遍历当前目录下的所有文件夹,并检出这些文件夹中的所有 .xml 文件。如果这些文件夹中还有更多的子文件夹,那么就需要像这样链接起来:**/**/*.xml 等等。 - Benji Weiss

17

更新:请看Dadaso的答案,大多数情况下可以解决问题。

你可以尝试像这样使用git ls-treegrep

git checkout origin/master -- `git ls-tree origin/master -r --name-only | grep ".xlf"`

请注意,这需要一个名为origin的远程库在master分支中。此外,您必须提供正确的过滤器/扩展名给grep

在运行此命令之前,您应该已经完成类似以下操作:

git init
git remote add origin <project.git>
git fetch

1
谢谢,这解决了问题。需要注意的一点是,如果文件扩展名有错别字,git 会报“Detached Head”的错误。如果文件扩展名正确,就不会出现这个错误信息。 - user5088790

4

Dadaso的答案 git checkout -- "*.xml" 会从索引(index)检出所有递归的.xml文件到工作目录。

但是,由于某些原因,git checkout branch-name -- "*.xml"(从branch-name分支检出文件)不会递归地工作,仅检查根目录中的"xml"文件。

因此,在我看来,最好使用git ls-tree,然后过滤您感兴趣的文件名,并将其传递给git checkout branch-name --。以下是您可以使用的命令:

  • Bash (and git bash on windows) version:

    git ls-tree branch-name --full-tree --name-only -r | grep "\.xml" | xargs git checkout branch-name --
    
  • cmd (windows) version (if you don't have "C:\Program Files\Git\usr\bin" in you PATH):

    git ls-tree branch-name --full-tree --name-only -r | "C:\Program Files\Git\usr\bin\grep.exe" "\.xml" | "C:\Program Files\Git\usr\bin\xargs.exe" git checkout branch-name --
    
  • for powershell it's still better to call cmd.exe because it's much faster (powershell doesn't have good support for native stdin/stdout pipelining):

    cmd.exe /C 'git ls-tree branch-name --full-tree --name-only -r | "C:\Program Files\Git\usr\bin\grep.exe" "\.xml" | "C:\Program Files\Git\usr\bin\xargs.exe" git checkout branch-name --'
    
  • However you you have small number of files you can try this in powershell (like in @aoetalks answer). But I found it extremely slow for couple of houndeds files:

    git ls-tree branch-name --full-tree --name-only -r | sls "\.xml" | %{ git checkout branch-name -- $_ }
    

2
在PowerShell上(Windows,尚未尝试过PowerShell Core+Linux),我可以这样做: git ls-tree master -r --name-only | sls ".cscfg" | foreach { git checkout origin/master -- $_ }

这个最终对我起作用了,因为我的目录中有空格。我只需要在 $_ 部分周围加上 "" 就可以了。 - KeizerHarm

0
不行,git是在整个仓库(和历史记录)级别上操作的;没有办法获取部分仓库的部分检出。当然,您可以检出仓库,然后删除与您的文件不匹配的所有内容,但这样做实际上并没有什么好处。

顺便说一下,现在可以进行每个 Blob 的克隆了:https://dev59.com/QHRB5IYBdhLWcg3wgXhV#52269934 :-) - Ciro Santilli OurBigBook.com

0

我遇到了提供的解决方案问题,这是我的解决方案:

  1. 从其他分支检出所有更改 git checkout branch -- ./
  2. 只暂存特定类型 git add \*.type
  3. 提交已暂存文件 git commit
  4. 重置其他文件 git reset --hard

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