Git:如何在*checkout*时忽略/指定文件。

24
如果我不想追踪 .html 文件,我可以将该模式添加到 .gitignore 中,这样它们就会被忽略。 我想知道如何做相反的操作-在检出时,如何要求 git 仅检出某些类型的文件或不检出某些类型的文件?
例如,如果我不希望 html 文件,我可以编写以下内容:
git checkout HEAD . --no .html

如果这样的东西存在。是否已经内置了一种方法,或者我只需在检出后运行其他东西?


7
读者们如果在寻找一种正常使用Git(例如检出,提交,合并等)但只有整个工作树的子集存在(即另一种解释“忽略/指定检出文件”),则应考虑Git的稀疏检出功能。它在git read-tree手册“稀疏检出”部分中有详细说明。 - Chris Johnsen
5个回答

25

Git的稀疏检出

如果你只想检出仓库的一部分,你可以使用Git的稀疏检出选项,该选项具有强大的包含/排除规则。

以下StackOverflow问题提供了一些有用的指导:
GIT checkout except one folder

但简要来说:

  1. 启用 sparseCheckout 选项:

    git config core.sparseCheckout true
    
  2. 创建名为.git/info/sparse-checkout的文件,其中包含:

  3. /*
    !node_modules
    

    这实际上意味着,在将存储库检出到工作目录时,除node_modules目录以外的所有内容都会被包含。


1
这里的配置将针对目录中的所有文件夹进行检查,因此我认为应该是:!^node_modules,否则它也会忽略名为 node_modules 的子目录。 - Nathan

21
如果您想打包文件以进行部署,则可能不需要 - 或者不希望包含 - 存储库本身。这正是git archive的用途。以下是手册页面(链接)中的几个示例:

git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)

创建一个tar归档文件,其中包含当前分支上最新提交的内容,并将其提取到/var/tmp/junk目录中。

git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip > git-1.4.0.tar.gz

为v1.4.0版本创建一个压缩的tarball。

您应该能够使用export-ignore属性使其完全符合您的要求:

export-ignore

具有属性export-ignore的文件和目录将不会添加到存档文件中。有关详细信息,请参见gitattributes(5)

例如,要排除目录private以及文件mine.txtsecret.c,可以在文件.gitattributes中输入:
private/     export-ignore
secret.c     export-ignore

就像.gitignore文件一样,你可以将它们放在仓库中的任何位置,并且它们会从该目录运行,但是从顶层开始操作是一个好主意。


1
这更接近我所寻找的内容。至少我可以将其通过其他命令进行处理,这样就不会是一个繁琐的过程了。谢谢。 - ian

3

如果您只想进行一次更改(或不需要持续性更改),或者您不想将文件放在 .gitignore 中,那么请按照以下步骤操作:

  1. 将要从 checkout 排除的特定文件储存起来
git stash push -m "files_to_ignore" my/path/of/the/file/file.txt

按照您之前的预期进行结帐:
git checkout .

提取储藏的内容:
git stash apply stash^{/files_to_ignore}

完整的使用git别名的解决方案可以如下所示:
alias reset-non-dev='git stash push -m "ignore_files" MyRepo/file1.txt MyRepo/dir/file2.js MyRepo/dir/dir2/file3.cs PSOne/Startup/PSOne/Views/Login.xaml.cs ; git checkout . ; git stash apply stash^{/ignore_files} ;'

稍后您可以在git bash中输入别名并按回车键,从而使用该别名。
我观察到这种方法的一个好处是,您可以随时更改文件或跳过它们,而不必将这些文件标记为始终被忽略。

2

我希望将我的代码不带测试文件部署到生产服务器上。

最简单的方法就是在解压归档文件后使用以下命令删除所有测试文件:rsync --exclude 'tests'


1

你不仅可以像Simon East答案中提到的那样使用git sparse-checkout,还可以使用规则,例如

/*
!^node_modules

但是,从Git 2.41(2023年第二季度)开始,您可以验证这些规则!
"git sparse-checkout"(man)命令学会了一种用于稀疏规则定义的调试辅助工具。

查看提交 00408ad提交 24fc2cd(2023年3月27日),由William Sprent(williams-unity完成。
(由Junio C Hamano -- gitster --提交 d02343b中合并,2023年4月11日)

builtin/sparse-checkout:添加check-rules命令

签名作者:William Sprent

没有直接的方法可以查询 git 哪些路径与给定的稀疏规则匹配。
可以从 git 中获取此信息,但它包括检出包含路径的提交,应用稀疏检出模式,然后使用类似 'git ls-files -t'(man) 的命令来检查是否设置了跳过工作树位。
这在某些情况下有效,但有些情况下为了此目的生成检出是困难或不可行的。
公开稀疏检出的模式匹配使得更多的工具可以被构建,并避免了那些想要推理稀疏检出的工具包含并行实现规则的情况。
为了适应这一点,在 'sparse-checkout' 内置命令中添加一个 'check-rules' 子命令,类似于 'git check-ignore'(man) 和 'git check-attr'(man) 命令。
新命令接受标准输入上的路径列表,并输出与稀疏检出匹配的路径。
为了允许在裸仓库中使用,并允许查询当前规则以外的其他模式,包括一个 '--rules-file' 选项,允许调用者显式传递稀疏检出规则,格式与 'sparse-checkout set --stdin' 接受的格式相同。
为了允许在 '--rules-file' 标志下重复使用输入模式的处理,修改 'add_patterns_from_input()' 以能够从 'FILE' 中读取,而不仅仅是标准输入。
为了允许重复使用决定规则是否应解释为 cone-mode 模式的逻辑,将其从 'update_modes()' 中分离出来,以便可以在不修改配置的情况下调用它。
另一种选择是创建一个新的 'check-sparsity' 命令。
然而,将其放置在 'sparse-checkout' 下允许:
a) 更容易地重复使用稀疏检出模式匹配和锥形/非代码模式处理;
b) 将命令的文档放在实验警告和锥形模式讨论旁边。

git sparse-checkout现在在其手册页面中包含以下内容:

'git sparse-checkout' (init | list | set | add | reapply | disable | check-rules) [<options>]

git sparse-checkout现在在其手册页面中包含以下内容:

'check-rules'

检查稀疏规则是否与一个或多个路径匹配。

默认情况下,check-rules 从标准输入读取路径列表,并仅输出与当前稀疏规则匹配的路径。输入应该包含每行一个路径,与 git ls-tree --name-only 的输出相匹配,包括以双引号 (") 开头的路径名被解释为 C 风格的引用字符串。

当使用 --rules-file <file> 标志调用时,输入文件将与在 <file> 中找到的稀疏检出规则进行匹配,而不是当前规则。文件中的规则应该与 git sparse-checkout set --stdin 接受的形式相同(特别是它们必须是换行符分隔的)。

默认情况下,传递给 --rules-file 选项的规则被解释为锥形模式目录。要通过 --rules-file 传递非锥形模式模式,请将该选项与 --no-cone 选项组合使用。

当使用 -z 标志调用时,标准输入上的路径格式以及输出路径都是 \0 结尾的,而不是引用的。请注意,这不适用于使用 --rules-file 选项传递的规则格式。

示例:

cat >rules <<-\EOF &&
    folder1
    deep/deeper1/deepest
    EOF
    git -C bare ls-tree -r --name-only HEAD >all-files &&
    git -C bare sparse-checkout check-rules --cone \
        --rules-file ../rules >check-rules-file <all-files &&
    git -C repo sparse-checkout set --cone --stdin <rules&&
    git -C repo ls-files -t >out &&
    sed -n "/^S /!s/^. //p" out >ls-files &&
    git -C repo sparse-checkout check-rules >check-rules-default <all-files

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