协慌网

登录 贡献 社区

如何克隆仅 Git 存储库的子目录?

我有我的 Git 存储库,它在根目录下有两个子目录:

/finisht
/static

当这是在SVN 中时/finisht在一个地方签出,而/static在其他地方签出,如下所示:

svn co svn+ssh://[email protected]/home/admin/repos/finisht/static static

有没有办法用 Git 做到这一点?

答案

您要做的事情称为稀疏结账 ,该功能已添加到 git 1。7。0(2012 年 2 月)。执行稀疏克隆的步骤如下:

mkdir <repo>
cd <repo>
git init
git remote add -f origin <url>

这将使用您的遥控器创建一个空的存储库,并获取所有对象但不检查它们。然后做:

git config core.sparseCheckout true

现在,您需要定义要实际检出的文件 / 文件夹。这可以通过在.git/info/sparse-checkout列出来完成,例如:

echo "some/dir/" >> .git/info/sparse-checkout
echo "another/sub/tree" >> .git/info/sparse-checkout

最后但并非最不重要的是,使用远程状态更新您的空仓库:

git pull origin master

现在,您将在文件系统上为some/diranother/sub/tree “检出” 文件(这些路径仍然存在),并且不存在其他路径。

您可能希望查看扩展教程 ,您应该阅读稀疏结帐的官方文档

作为一个功能:

function git_sparse_clone() (
  rurl="$1" localdir="$2" && shift 2

  mkdir -p "$localdir"
  cd "$localdir"

  git init
  git remote add -f origin "$rurl"

  git config core.sparseCheckout true

  # Loops over remaining args
  for i; do
    echo "$i" >> .git/info/sparse-checkout
  done

  git pull origin master
)

用法:

git_sparse_clone "http://github.com/tj/n" "./local/location" "/bin"

请注意,这仍将从服务器下载整个存储库 - 只有结帐大小减少。目前,无法仅克隆单个目录。但是,如果您不需要存储库的历史记录,则可以通过创建浅层克隆来至少节省带宽。有关如何组合浅克隆和稀疏结账的信息,请参阅下面的udondan 答案

编辑 :从 Git 2.19 开始,这最终是可能的,这可以在这个答案中看到: https//stackoverflow.com/a/52269934/2988

考虑提出这个答案。

注意:在 Git 2.19 中,仅实现了客户端支持,仍然缺少服务器端支持,因此它仅在克隆本地存储库时有效。另请注意,大型 Git 托管服务商(例如 GitHub)实际上并不使用 Git 服务器,他们使用自己的实现,因此即使支持显示在 Git 服务器中,也不会自动意味着它可以在 Git 托管服务器上运行。 (OTOH,因为他们不使用 Git 服务器,他们可以在它们自己的实现中更快地实现它,然后才能在 Git 服务器中显示它。)


不,这在 Git 中是不可能的。

在 Git 中实现类似的功能将是一项重大工作,这意味着无法再保证客户端存储库的完整性。如果您有兴趣,请在 git mailinglist 上搜索关于 “sparse clone” 和 “sparse fetch” 的讨论。

一般来说,Git 社区的共识是,如果你有几个总是独立检出的目录,那么这些实际上是两个不同的项目,应该存在于两个不同的存储库中。您可以使用Git 子模块将它们粘合在一起。

您可以组合稀疏结帐浅克隆功能。 浅层克隆切断了历史记录, 稀疏结账只会拉出与您的模式匹配的文件。

git init <repo>
cd <repo>
git remote add origin <url>
git config core.sparsecheckout true
echo "finisht/*" >> .git/info/sparse-checkout
git pull --depth=1 origin master

你需要最低限度的 git 1.9 来实现这个目的。仅使用 2.2.0 和 2.2.2 对自己进行了测试。

这样你仍然可以推送 ,这是git archive无法实现的。