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


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

/finisht
/static

当它进入时 SVN/finisht 在一个地方检查,而 /static 在其他地方检查过,如下:

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

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


1004
2018-03-01 16:46


起源


可能重复 在Git中查看子目录? - Joachim Breitner
对于2014年的用户来说,是什么 git clone 最简单的命令??我用了 这个 简单的答案。如果有更简单的事情,请评论 - Peter Krauss
对于那些试图克隆存储库内容(而不是创建根文件夹)的人来说,这是一个非常简单的解决方案: stackoverflow.com/questions/6224626/... - Marc
@OP你能否将接受的答案改为 @ Chronial的回答? - Cole Johnson


答案:


这个答案已经过时,只适用于低于1.7.0的git版本(2012年2月)。有关较新版本,请参阅下文。

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

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

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


421
2018-03-01 18:00



根据具体情况,您可能希望使用git子树而不是git子模块。看到 alumnit.ca/~apenwarr/log/?m=200904#30 - C Pirate
+0链接断开。我想你想要的 这个。 - Mr. Shtuffs
@StijndeWitt:稀疏结账期间发生 git-read-tree,这是很久以后 get-fetch。问题不在于只检查一个子目录,而是关于 克隆 只是一个子目录。我不知道稀疏结账可能会如何做到这一点,因为 git-read-tree 克隆已经完成后运行。 - Jörg W Mittag
为了帮助您只显示所需的目录,您必须执行git read-tree -m -u HEAD - JackXu
你想要删除这个答案,而不是这个“存根”,所以Chronial可以浮到顶端吗?你不能自己删除它,因为它已被接受,但主持人可以。你会保留你从中获得的声誉,因为它太老了。 (我之所以遇到这个,是因为有人将其标记为“仅链接”。:-) - Cody Gray♦


你要做的是做一个 稀疏结账,该功能已添加到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/dir 和 another/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"

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


1351
2017-12-06 07:37



在Apple上'-f'外围不起作用。只需要执行git remote add origin <url>而不使用-f - Anno2001
这是一个改进,但仍然需要下载并存储源的远程存储库的完整副本,如果他只对代码库的某些部分感兴趣(或者如果在我的情况下有文档子文件夹,则可能完全避免) ) - a1an
有没有办法将所需的目录内容(不是目录本身)直接克隆到我的存储库中?例如,我想要克隆内容 https://github.com/Umkus/nginx-boilerplate/tree/master/src 进入 /etc/nginx - mac
@Chronial,@ ErikE:你是对还是错:P The git remote add 命令呢 不 暗示抓取,但是 git remote add -f,这里使用,做!那是什么的 -f 手段。 - ntc2
用这个和 --depth=1 我克隆了Chromium Devtools 338 MB而不是4.9 GB的完整Blink源+历史记录。优秀。 - Rudie


你可以结合使用 稀疏结账 和 浅克隆 特征。该 浅克隆 切断了历史和历史 稀疏结账 仅拉取与您的模式匹配的文件。

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


326
2018-01-20 07:33



这是正确的答案。所有其他答案都拉得太多了。 - Johan
这很有用,可能是最好的答案,但它仍然是 克隆 你不关心的内容(如果它在你拉的分支上),即使它没有出现在结账中。 - nobar
你的git版本是什么?根据git help是深度选项吗? - udondan
当最后一个命令没有时,对我不起作用 git pull --depth=1 origin master 但 git pull --depth=1 origin <any-other-branch>。这太奇怪了,请看我的问题: stackoverflow.com/questions/35820630/... - Shuman
这仍然会下载所有数据!使用svn找到此解决方案: stackoverflow.com/a/18324458/2302437 - Ben Marten


对于其他用户 只是想下载 来自github的文件/文件夹,只需使用:

svn export <repo>/trunk/<folder>

例如

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

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

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

重要  - 确保更新github URL并替换 /tree/master/ 用'/ trunk /'。

作为bash脚本:

git-download(){
    folder=${@/tree\/master/trunk}
    folder=${folder/blob\/master/trunk}
    svn export $folder
}

注意 此方法下载文件夹,不克隆/签出。您无法将更改推送回存储库。另一方面 - 与稀疏结账或浅结账相比,这会导致更小的下载。


78
2017-09-04 13:02



只有github为我工作的版本。 git命令检出> 10k文件,svn导出只有我想要的700。谢谢! - Christopher Lörken
试过这样做 https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity 但得到了 svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't exist 错误:( - zthomas.nc
@ zthomas.nc您需要删除udacity之前的'trunk',并将/ tree / master /替换为/ trunk /。 - Speedy
这个命令对我有用!我只想从repo中获取一个文件的副本,以便我可以在本地修改它。好老SVN救援! - Michael J
它有效,但似乎很慢。需要一些开始,然后文件滚动相对缓慢 - Aryeh Beitz


Git 1.7.0有“稀疏结账”。看到 “core.sparseCheckout”中的 git配置 手册页, “稀疏结账”中 git read-tree 手册页,和 “Skip-worktree bit”中的 git update-index 手册页

该接口不如SVN那样方便(例如,在初始克隆时无法进行稀疏检出),但现在可以使用可以构建更简单接口的基本功能。


63
2018-05-18 21:15





如果您从未计划与克隆的存储库进行交互,则可以执行完整操作 git clone 并使用重写您的存储库 git filter-branch --subdirectory-filter。这样,至少会保留历史记录。


60
2018-03-01 21:17



对于那些不了解命令的人来说,确实如此 git filter-branch --subdirectory-filter <subdirectory> - Jaime Hablutzel
这种方法的优点是您选择的子目录成为新存储库的根目录,这恰好正是我想要的。 - Andrew Schulman
git log --all 仍显示所有日志.. - cychoi


这个 看起来更简单:

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

60
2017-09-10 17:03



当我在github上执行此操作时,我会致命:协议不支持操作。意外的命令流结束 - Michael Fox
这适用于bitbucket =) - Paul Rigor
如果你正在使用github,你可以使用 svn export 代替 - 0sh
无法使用Github - >无效命令:'git-upload-archive'xxx / yyy.git''您似乎正在使用ssh来克隆git:// URL。确保未设置core.gitProxy配置选项和GIT_PROXY_COMMAND环境变量。致命:远程端意外挂断 - Nianliang
这不适用于GitHub:“我们不支持使用git-archive直接从GitHub中提取存档。您可以在本地克隆存储并运行git-archive,或者单击Download ZIP按钮回购页面。“ github.com/xuwupeng2000/capistrano-scm-gitcopy/issues/16 - Donn Lee


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

过滤分支

您可能希望重写存储库以使其看起来像 trunk/public_html/ 曾经是它的项目根,并丢弃所有其他历史(使用 filter-branch),尝试已结帐分支:

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

备注: -- 将过滤器分支选项与修订选项分开,以及 --all 重写所有分支和标签。所有信息包括原始提交时间或合并信息 罐头。这个命令很荣幸 .git/info/grafts 文件和引用 refs/replace/ 命名空间,所以如果您有任何移植或替换 refs 定义,运行此命令将使它们永久化。

警告!重写的历史将具有所有对象的不同对象名称,并且不会与原始分支会聚。您将无法轻松地在原始分支的顶部推送和分发重写的分支。如果您不知道完整的含义,请不要使用此命令,并且无论如何都要避免使用它,如果简单的单个提交就足以解决您的问题。


稀疏结账

这里有简单的步骤 稀疏结账 将稀疏地填充工作目录的方法,这样你就可以告诉Git工作目录中哪些文件夹或文件值得检出。

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

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

    如果已经克隆了存储库,则可以跳过此步骤。

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


22
2018-03-22 23:06



将 过滤分支 仍允许你 pull? - sam
@sam:没有。 filter-branch 会重写父提交,因此他们有不同的SHA1 ID,因此过滤后的树将没有与远程树共同的提交。 git pull 不知道从哪里尝试合并。 - Peter Cordes


我只是 写了一个脚本 对于 GitHub上

用法:

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

11
2018-01-23 18:49



仅供参考,这是为了 GitHub上 只要。 - Sz.
显然这是为了 下载 目录,不是 克隆 一个包含所有元数据的回购......对吗? - LarsH


这是我为单个子目录稀疏结账的用例编写的shell脚本

coSubDir.sh

localRepo=$1
remoteRepo=$2
subDir=$3


# Create local repository for subdirectory checkout, make it hidden to avoid having to drill down to the subfolder
mkdir ./.$localRepo
cd ./.$localRepo
git init
git remote add -f origin $remoteRepo
git config core.sparseCheckout true

# Add the subdirectory of interest to the sparse checkout.
echo $subDir >> .git/info/sparse-checkout

git pull origin master

# Create convenience symlink to the subdirectory of interest
cd ..
ln -s ./.$localRepo$subDir $localRepo

4
2018-03-08 19:39



好的脚本,只有应该修复的东西是符号链接,应该是 ln -s ./.$localRepo/$subDir $localRepo 代替 ln -s ./.$localRepo$subDir $localRepo - valentin_nasta