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

我有我的Git仓库,在根,有两个子目录:

/finisht /static 

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

 svn co svn+ssh://admin@domain.com/home/admin/repos/finisht/static static 

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

这被称为稀疏结帐 ,从版本1.7.0开始。

“稀疏结帐”允许稀疏地填充工作目录。 它使用skip-worktree位(请参阅git-update-index )告诉Git工作目录中的文件是否值得一看。

虽然$GIT_DIR/info/sparse-checkout通常用于指定文件所在的位置,但您也可以使用取反模式来指定不在的文件。 例如,要删除unwanted的文件:

 /* !unwanted 

有关详细信息,请参阅相关答案和手册 。

你所要做的就是称为稀疏结帐 ,而这个function是在git 1.7.0(2012年2月)中添加的。 执行稀疏克隆的步骤如下所示:

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

这将为您的远程创build一个空的存储库,并获取所有对象,但不检查它们。 然后做:

 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 “签出”文件(这些path仍然存在),并且不存在其他path。

你可能想看看扩展教程 ,你应该阅读稀疏结帐的官方文档 。


请注意,这仍将从服务器下载整个存储库 – 只有结账尺寸减小。 目前,只克隆一个目录是不可能的。 但是,如果您不需要存储库的历史logging,则至less可以通过创build浅度克隆来节省带宽。 请参阅下面的udondan的答案 ,了解如何将浅克隆和稀疏结帐相结合的信息。

您可以组合稀疏结帐浅层克隆function。 浅层克隆切断了历史logging,而稀疏结帐只会拉取与您的模式相匹配的文件。

 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来testing它。

这样,你仍然可以 ,这是不可能的与git archive

Git 1.7.0有“稀疏结账”。 请参阅git config手册页中的“core.sparseCheckout”, git read-tree手册页中的“Sparse checkout”以及git update-index手册页中的“Skip-worktree bit”。

这个接口并不像SVN那样方便(例如,在初始化克隆的时候没有办法做一个稀疏的检出),但是现在可以构build简单接口的基本function。

如果你从来没有计划与你克隆的仓库进行交互,你可以做一个完整的git克隆,并使用git filter-branch –subdirectory-filter重写你的仓库。 这样,至less历史将被保留下来。

这看起来简单得多:

 git archive --remote=<repo_url> <branch> <path> | tar xvf - 

对于只想从github 下载文件/文件夹的其他用户

简单地使用

 svn export <repo>/trunk/<folder> 

例如

 svn export https://github.com/lodash/lodash/trunk/docs 

(是的,这里是svn,显然在2016年,你仍然需要svn来简单地下载一些github文件)

礼貌从GitHub仓库下载单个文件夹或目录

重要! 确保你更新了github的URL,用'/ trunk /'取代'/ tree / master /'。

只有使用Git才能克隆子目录,但下面几个解决方法是不可能的。

筛选分支

您可能需要重写存储库,使其看起来像是trunk/public_html/作为其项目根目录,并放弃所有其他历史logging(使用filter-branch ),试试已经签出的分支:

 git filter-branch --subdirectory-filter trunk/public_html -- --all 

注意: --将过滤分支选项与修订选项分开,并且 – 全部重写所有分支和标记。 包括原始提交时间或合并信息的所有信息将被保留 这个命令可以使用.git/info/grafts文件,并且在refs/replace/命名空间中refs/replace/ ,所以如果你有任何移植或replace参数,运行这个命令将会使它们成为永久的。

警告! 重写后的历史logging将为所有对象设置不同的对象名称,并且不会与原始分支会聚。 您将无法轻松地将重写的分支推送并分发到原始分支之上。 如果您不知道全部含义,请不要使用这个命令,如果简单的单一提交就足以解决您的问题,请避免使用它。


稀疏结帐

这里有一些简单的步骤,使用稀疏的检出方法,这将稀疏地填充工作目录,所以你可以告诉Git工作目录中的文件夹或文件是值得检查的。

  1. 像往常一样克隆存储库( --no-checkout是可选的):

     git clone --no-checkout git@foo/bar.git cd bar 

    如果您的存储库已经被克隆,您可以跳过这一步。

    提示:对于大的回购,考虑浅克隆 ( – --depth 1 )只签出最新版本或/和--single-branch

  2. 启用sparseCheckout选项:

     git config core.sparseCheckout true 
  3. 指定稀疏结帐的文件夹(最后没有空格):

     echo "trunk/public_html/*"> .git/info/sparse-checkout 

    或编辑.git/info/sparse-checkout

  4. 检出分支(如master ):

     git checkout master 

现在你应该select当前目录中的文件夹。

如果您的目录层次过多,或者过滤分支,您可以考虑使用符号链接。


我刚刚为GitHub 写了一个脚本 。

用法:

 python get_git_sub_dir.py path/to/sub/dir <RECURSIVE> 

为什么不只是以下内容 – 初始化回购之后,请执行:git checkout

这适用于文件和文件夹,我一直这样做,当我想清理结帐的东西。