1. 概述

Git 提供了将存储库的工作树限制为仅子目录或文件的选项 - 这个功能称为 git sparse-checkout。在我们只想要跟踪特定文件或子目录时,这非常有用。

除了 git sparse-checkout,还有其他从 Git 存储库检索目录或文件子集的方法。在这篇教程中,我们将讨论从 git 存储库克隆子目录的不同方法。

2. 使用 git sparse-checkout

在继续之前,我们必须指出,在撰写本教程时,git sparse-checkout 是实验性的**。因此,其行为可能会有不规则性。

要使用 git sparse-checkout 克隆子目录,我们首先需要使用 git clone 克隆目录:

$ git clone --depth=1 https://github.com/Baeldung/stackify.git

–depth=1 选项确保克隆仅包含最近的提交。

接下来,我们使用 cd 命令进入本地目录:

$ cd stackify

然后,我们使用 git sparse-checkout set 检出到所需的子目录:

$ git sparse-checkout set tomcat-app

运行 git sparse-checkout set 后,我们使用 ls -F 查看目录中的资源:

$ ls -F
pom.xml  README.md  tomcat-app/

如图所示,我们的目录包含检出时的 tomcat-app 子目录及其兄弟文件,尽管我们仅指定了 tomcat-app。这是因为 git sparse-checkout 默认以 cone 模式运行。

cone 模式下,兄弟文件和子资源会被包含在检出中。但我们可以通过执行 no-cone 模式的稀疏检出来避免这种情况。

–no-cone 模式下,git sparse-checkout 命令读取参数作为模式。因此,如果我们只想获取 tomcat-app 而不包括其兄弟文件,我们可以传递一个匹配的模式:

$ git sparse-checkout set --no-cone tomcat-app

使用此新命令,我们仅检查出了根目录下的 tomcat-app 子目录:

$ ls -F
tomcat-app/

然而,如果工作树中其他位置存在名为 tomcat-app 的资源,该命令会将它们包含在稀疏检出中。但是,我们也可以通过传递模式来限制这种结果:

$ git sparse-checkout set --no-cone tomcat-app/ '!*/tomcat-app'

‘!\*/tomcat-app’ 模式会指导命令忽略 tomcat-app 子目录的兄弟子目录中任何名为 tomcat-app 的子资源:

$ ls -F
tomcat-app/

2.1. git sparse-checkout add

运行 git sparse-checkout set 覆盖先前的 git sparse-checkout 设置命令会替换初始跟踪的文件或目录。因此,如果我们要添加另一个子目录到工作树,我们将运行 git sparse-checkout add 并跟上子目录的名称:

$ git sparse-checkout add webservices

现在,我们有了 tomcat-appwebservices 两个子目录:

$ ls -F
tomcat-app/  webservices/

如果一开始想要克隆多个目录或文件,我们可以在一次 git sparse-checkout set 命令中传递所有它们

我们还可以使用 git sparse-checkout 来处理文件。但是,由于 git sparse-checkout 命令仍处于实验阶段,使用它可能会产生意外的结果。

2.2. 禁用稀疏检出

如果我们要恢复到完全跟踪的仓库,我们将运行 disable 命令:

$ git sparse-checkout disable

这样,我们将拥有克隆的所有文件和仓库:

$ ls -F
core-java/    core-kotlin/  junit5-example/  logback-example/  pom.xml    remote-debugging/  spring-boot-app/  spring-security/  tomcat-app/
core-java-9/  deep-jsf/     log4j2-example/  memory-leaks/     README.md  slf4j/             spring-mvc/       thread-pools/     webservices/

3. 使用 git checkout

为了使用 git checkout 克隆子目录或文件,我们首先需要不进行 HEAD 检出克隆仓库:

$ git clone --no-checkout --depth=1 https://github.com/Baeldung/stackify.git

执行上述命令会在本地创建仓库的 .git 文件夹。然而,本地仓库的根目录将没有任何文件或子目录。我们可以通过 tree 命令验证这一点:

$ tree stackify
stackify

0 directories, 0 files

在执行 –no-checkout 克隆后,我们进入本地仓库的主要目录:

$ cd stackify

然后,我们使用 git checkout 和分支名称检查所需子目录或文件:

$ git checkout master -- tomcat-app

现在,我们只有 tomcat-app 子目录:

$ ls -F
tomcat-app/

使用这种方法从 Git 仓库克隆单个子目录或文件意味着 当我们提交更改时,仓库的其他文件和子目录将会被删除

因此,当我们可以删除仓库的其他资源时,我们会使用这种方法。或者,我们可以使用这种方法获取文件或子目录,然后通过删除 .git 目录将其从仓库中解关联 - 基本上就像下载文件或子目录。

git checkout 方法不同, git sparse-checkout 在我们提交更改时不会删除其他文件和子目录。我们对跟踪资源所做的任何更改都仅影响该资源。因此,即使我们向远程仓库推送,远程仓库中仅跟踪的文件才会更新。

4. 使用 git show

如果已经有一个本地仓库并且我们想下载其中一个文件,我们可以将 git show 的输出重定向到本地文件:

$ git --git-dir ./stackify/.git show master:README.md > /home/baeldung/stackify-README.md

git checkout 方法类似,我们仅在需要文件(而不需要整个仓库)时使用此方法。

5. 总结

在这篇文章中,我们讨论了如何使用 git 克隆存储库的子目录以及 git sparse-checkout 的方法。我们也谈到了如何从仓库中克隆资源,而不将其链接到仓库的情况。