简体   繁体   English

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

[英]How do I clone a subdirectory only of a Git repository?

I have my Git repository which, at the root, has two sub directories:我有我的 Git 存储库,它在根目录下有两个子目录:

/finisht
/static

When this was in SVN , /finisht was checked out in one place, while /static was checked out elsewhere, like so:当这是在SVN时, /finisht在一个地方被签出,而/static在别处被签出,如下所示:

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

Is there a way to do this with Git?有没有办法用 Git 做到这一点?

What you are trying to do is called a sparse checkout , and that feature was added in Git 1.7.0 (Feb. 2012).您正在尝试执行的操作称为sparse checkout ,该功能已添加到 Git 1.7.0(2012 年 2 月)中。 The steps to do a sparse clone are as follows:进行稀疏克隆的步骤如下:

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

This creates an empty repository with your remote, and fetches all objects but doesn't check them out.这将使用您的遥控器创建一个空存储库,并获取所有对象但不检出它们。 Then do:然后做:

git config core.sparseCheckout true

Now you need to define which files/folders you want to actually check out.现在您需要定义要实际签出的文件/文件夹。 This is done by listing them in .git/info/sparse-checkout , eg:这是通过在.git/info/sparse-checkout中列出它们来完成的,例如:

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

Last but not least, update your empty repo with the state from the remote:最后但同样重要的是,使用远程状态更新您的空仓库:

git pull origin master

You will now have files "checked out" for some/dir and another/sub/tree on your file system (with those paths still), and no other paths present.您现在将在文件系统上“签出” some/diranother/sub/tree的文件(这些路径仍然存在),并且不存在其他路径。

You might want to have a look at the extended tutorial and you should probably read the official documentation for sparse checkout and read-tree .您可能想查看扩展教程,并且您可能应该阅读稀疏结帐read-tree的官方文档。

As a function:作为一个函数:

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
)

Usage:用法:

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

Note that this will still download the whole repository from the server – only the checkout is reduced in size.请注意,这仍然会从服务器下载整个存储库——只是结帐的大小减小了。 At the moment it is not possible to clone only a single directory.目前不可能只克隆一个目录。 But if you don't need the history of the repository, you can at least save on bandwidth by creating a shallow clone.但是,如果您不需要存储库的历史记录,您至少可以通过创建浅层克隆来节省带宽。 See udondan's answer below for information on how to combine shallow clone and sparse checkout.有关如何结合浅克隆和稀疏结帐的信息,请参阅下面的 udondan 答案


As of Git 2.25.0 (Jan 2020) an experimental sparse-checkout command is added in Git:从 Git 2.25.0(2020 年 1 月)开始,在 Git 中添加了一个实验性的sparse-checkout命令:

git sparse-checkout init
# same as:
# git config core.sparseCheckout true

git sparse-checkout set "A/B"
# same as:
# echo "A/B" >> .git/info/sparse-checkout

git sparse-checkout list
# same as:
# cat .git/info/sparse-checkout

git clone --filter from git 2.19 now works on GitHub (tested 2021-01-14, git 2.30.0) git clone --filter来自 git 2.19 现在可以在 GitHub 上运行(测试 2021-01-14,git 2.30.0)

This option was added together with an update to the remote protocol, and it truly prevents objects from being downloaded from the server.此选项是与远程协议的更新一起添加的,它确实可以防止从服务器下载对象。

Eg, to clone only objects required for directory d1 in this minimal test repository: https://github.com/cirosantilli/test-git-partial-clone I can do:例如,在这个最小的测试存储库中只克隆目录d1所需的对象: https://github.com/cirosantilli/test-git-partial-clone我可以这样做:

git clone \
  --depth 1  \
  --filter=blob:none  \
  --sparse \
  https://github.com/cirosantilli/test-git-partial-clone \
;
cd test-git-partial-clone
git sparse-checkout set d1

Here's a less minimal and more realistic version at https://github.com/cirosantilli/test-git-partial-clone-big-small这是https://github.com/cirosantilli/test-git-partial-clone-big-small

git clone \
  --depth 1  \
  --filter=blob:none  \
  --sparse \
  https://github.com/cirosantilli/test-git-partial-clone-big-small \
;
cd test-git-partial-clone-big-small
git sparse-checkout set small

That repository contains:该存储库包含:

  • a big directory with 10 10MB files一个包含 10 个 10MB 文件的大目录
  • a small directory with 1000 files of size one byte一个包含 1000 个大小为 1 字节的文件的小目录

All contents are pseudo-random and therefore incompressible.所有内容都是伪随机的,因此不可压缩。

Clone times on my 36.4 Mbps internet:在我的 36.4 Mbps 互联网上克隆时间:

  • full: 24s满:24s
  • partial: "instantaneous"部分:“瞬时”

The sparse-checkout part is also needed unfortunately.不幸的是, sparse-checkout部分也是需要的。 You can also only download certain files with the much more understandable:您也可以只下载某些更易于理解的文件:

git clone \
  --depth 1  \
  --filter=blob:none  \
  --no-checkout \
  https://github.com/cirosantilli/test-git-partial-clone \
;
cd test-git-partial-clone
git checkout master -- d1

but that method for some reason downloads files one by one very slowly , making it unusable unless you have very few files in the directory.但是由于某种原因,该方法会非常缓慢地逐个下载文件,除非目录中的文件很少,否则无法使用。

Analysis of the objects in the minimal repository分析最小存储库中的对象

The clone command obtains only:克隆命令仅获得:

  • a single commit object with the tip of the master branch带有master分支尖端的单个提交对象
  • all 4 tree objects of the repository:存储库的所有 4 个树对象
    • toplevel directory of commit提交的顶级目录
    • the the three directories d1 , d2 , master三个目录d1 , d2 , master

Then, the git sparse-checkout set command fetches only the missing blobs (files) from the server:然后, git sparse-checkout set命令仅从服务器获取丢失的 blob(文件):

  • d1/a
  • d1/b

Even better, later on GitHub will likely start supporting:更好的是,稍后在 GitHub 上可能会开始支持:

  --filter=blob:none \
  --filter=tree:0 \

where --filter=tree:0 from Git 2.20 will prevent the unnecessary clone fetch of all tree objects, and allow it to be deferred to checkout .其中--filter=tree:0来自 Git 2.20将防止对所有树对象进行不必要的clone获取,并允许将其推迟到checkout But on my 2020-09-18 test that fails with:但是在我的 2020-09-18 测试中失败了:

fatal: invalid filter-spec 'combine:blob:none+tree:0'

presumably because the --filter=combine: composite filter (added in Git 2.24, implied by multiple --filter ) is not yet implemented.大概是因为--filter=combine:复合过滤器(在 Git 2.24 中添加,由多个--filter暗示)尚未实现。

I observed which objects were fetched with:我观察了哪些对象被提取:

git verify-pack -v .git/objects/pack/*.pack

as mentioned at: How to list ALL git objects in the database?如前所述: 如何列出数据库中的所有 git 对象? It does not give me a super clear indication of what each object is exactly, but it does say the type of each object ( commit , tree , blob ), and since there are so few objects in that minimal repo, I can unambiguously deduce what each object is.它并没有给我一个非常清楚的指示每个对象到底是什么,但它确实说明了每个对象的类型( committreeblob ),并且由于那个最小的 repo 中的对象很少,我可以明确地推断出什么每个对象都是。

git rev-list --objects --all did produce clearer output with paths for tree/blobs, but it unfortunately fetches some objects when I run it, which makes it hard to determine what was fetched when, let me know if anyone has a better command. git rev-list --objects --all确实产生了带有树/blob 路径的更清晰的输出,但不幸的是,当我运行它时它会获取一些对象,这使得很难确定何时获取了什么,让我知道是否有人有更好的指挥。

TODO find GitHub announcement that saying when they started supporting it. TODO 找到 GitHub 的公告,上面写着他们何时开始支持它。 https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/ from 2020-01-17 already mentions --filter blob:none . https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/从 2020-01-17 已经提到--filter blob:none

git sparse-checkout

I think this command is meant to manage a settings file that says "I only care about these subtrees" so that future commands will only affect those subtrees.我认为这个命令旨在管理一个设置文件,上面写着“我只关心这些子树”,以便将来的命令只会影响这些子树。 But it is a bit hard to be sure because the current documentation is a bit... sparse ;-)但是有点难以确定,因为当前的文档有点……稀疏;-)

It does not, by itself, prevent the fetching of blobs.它本身并不能阻止获取 blob。

If this understanding is correct, then this would be a good complement to git clone --filter described above, as it would prevent unintentional fetching of more objects if you intend to do git operations in the partial cloned repo.如果这种理解是正确的,那么这将是对上述git clone --filter的一个很好的补充,因为如果您打算在部分克隆的 repo 中执行 git 操作,它可以防止意外获取更多对象。

When I tried on Git 2.25.1:当我尝试使用 Git 2.25.1 时:

git clone \
  --depth 1 \
  --filter=blob:none \
  --no-checkout \
  https://github.com/cirosantilli/test-git-partial-clone \
;
cd test-git-partial-clone
git sparse-checkout init

it didn't work because the init actually fetched all objects.它不起作用,因为init实际上获取了所有对象。

However, in Git 2.28 it didn't fetch the objects as desired.但是,在 Git 2.28 中,它并没有按需要获取对象。 But then if I do:但是,如果我这样做:

git sparse-checkout set d1

d1 is not fetched and checked out, even though this explicitly says it should: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/#sparse-checkout-and-partial-clones With disclaimer: d1没有被提取和检出,即使这明确表示它应该: https ://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/#sparse -checkout-and-partial-clones带有免责声明:

Keep an eye out for the partial clone feature to become generally available[1].请留意部分克隆功能是否会普遍可用[1]。

[1]: GitHub is still evaluating this feature internally while it's enabled on a select few repositories (including the example used in this post). [1]:GitHub 仍在内部评估此功能,同时它已在少数几个存储库(包括本文中使用的示例)上启用。 As the feature stabilizes and matures, we'll keep you updated with its progress.随着该功能的稳定和成熟,我们会及时通知您其进展情况。

So yeah, it's just too hard to be certain at the moment, thanks in part to the joys of GitHub being closed source.所以,是的,目前很难确定,这部分归功于 GitHub 是封闭源代码的乐趣。 But let's keep an eye on it.但让我们密切关注它。

Command breakdown命令分解

The server should be configured with:服务器应配置:

git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

Command breakdown:命令分解:

  • --filter=blob:none skips all blobs, but still fetches all tree objects --filter=blob:none跳过所有 blob,但仍获取所有树对象

  • --filter=tree:0 skips the unneeded trees: https://www.spinics.net/lists/git/msg342006.html --filter=tree:0跳过不需要的树: https ://www.spinics.net/lists/git/msg342006.html

  • --depth 1 already implies --single-branch , see also: How do I clone a single branch in Git? --depth 1已经暗示了--single-branch ,另请参阅: 如何在 Git 中克隆单个分支?

  • file://$(path) is required to overcome git clone protocol shenanigans: How to shallow clone a local git repository with a relative path? file://$(path)是克服git clone协议恶作剧所必需的: 如何用相对路径浅克隆本地 git 存储库?

  • --filter=combine:FILTER1+FILTER2 is the syntax to use multiple filters at once, trying to pass --filter for some reason fails with: "multiple filter-specs cannot be combined". --filter=combine:FILTER1+FILTER2是一次使用多个过滤器的语法,尝试通过--filter出于某种原因失败:“多个过滤器规格无法组合”。 This was added in Git 2.24 at e987df5fe62b8b29be4cdcdeb3704681ada2b29e "list-objects-filter: implement composite filters"这是在 Git 2.24 的 e987df5fe62b8b29be4cdcdeb3704681ada2b29e “list-objects-filter:实现复合过滤器”中添加的

    Edit: on Git 2.28, I experimentally see that --filter=FILTER1 --filter FILTER2 also has the same effect, since GitHub does not implement combine: yet as of 2020-09-18 and complains fatal: invalid filter-spec 'combine:blob:none+tree:0' .编辑:在 Git 2.28 上,我通过实验看到--filter=FILTER1 --filter FILTER2也具有相同的效果,因为 GitHub 没有实现combine:然而截至 2020-09-18 并抱怨fatal: invalid filter-spec 'combine:blob:none+tree:0' TODO introduced in which version? TODO在哪个版本推出?

The format of --filter is documented on man git-rev-list . --filter的格式记录在man git-rev-list上。

Docs on Git tree: Git 树上的文档:

Test it out locally在本地测试一下

The following script reproducibly generates the https://github.com/cirosantilli/test-git-partial-clone repository locally, does a local clone, and observes what was cloned:以下脚本可重现地在本地生成https://github.com/cirosantilli/test-git-partial-clone存储库,执行本地克隆,并观察克隆的内容:

#!/usr/bin/env bash
set -eu

list-objects() (
  git rev-list --all --objects
  echo "master commit SHA: $(git log -1 --format="%H")"
  echo "mybranch commit SHA: $(git log -1 --format="%H")"
  git ls-tree master
  git ls-tree mybranch | grep mybranch
  git ls-tree master~ | grep root
)

# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

rm -rf server_repo local_repo
mkdir server_repo
cd server_repo

# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet

# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet

# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet

echo "# List and identify all objects"
list-objects
echo

# Restore master.
git checkout --quiet master
cd ..

# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo

# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo

echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo

echo "# Git checkout fetches the missing directory from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/
echo

echo "# Missing objects after checking out d1"
git rev-list --all --quiet --objects --missing=print

GitHub upstream . GitHub 上游.

Output in Git v2.19.0: Git v2.19.0 中的输出:

# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root

# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63

# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

# Missing objects after checking out d1
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb

Conclusions: all blobs from outside of d1/ are missing.结论:来自d1/之外的所有 blob 都丢失了。 Eg 0975df9b39e23c15f63db194df7f45c76528bccb , which is d2/b is not there after checking out d1/a .例如0975df9b39e23c15f63db194df7f45c76528bccb ,即d2/b签出后不存在d1/a

Note that root/root and mybranch/mybranch are also missing, but --depth 1 hides that from the list of missing files.请注意, root/rootmybranch/mybranch也丢失了,但--depth 1将其从丢失的文件列表中隐藏了。 If you remove --depth 1 , then they show on the list of missing files.如果您删除--depth 1 ,则它们会显示在丢失文件列表中。

I have a dream我有一个梦想

This feature could revolutionize Git.这个特性可能会彻底改变 Git。

Imagine having all the code base of your enterprise in a single repo without ugly third-party tools like repo .想象一下,将您企业的所有代码库都放在一个仓库中,而无需repo这样丑陋的第三方工具

Imagine storing huge blobs directly in the repo without any ugly third party extensions .想象一下,在没有任何丑陋的第三方扩展的情况下,直接在 repo 中存储巨大的 blob

Imagine if GitHub would allow per file / directory metadata like stars and permissions, so you can store all your personal stuff under a single repo.想象一下,如果 GitHub 允许每个文件/目录的元数据,如星号和权限,那么您可以将所有个人资料存储在一个存储库中。

Imagine if submodules were treated exactly like regular directories : just request a tree SHA, and a DNS-like mechanism resolves your request , first looking on your local ~/.git , then first to closer servers (your enterprise's mirror / cache) and ending up on GitHub.想象一下,如果子模块被视为与常规目录完全一样:只需请求树 SHA,类似 DNS 的机制会解析您的请求,首先查看本地~/.git ,然后首先查看更接近的服务器(您企业的镜像/缓存)并结束在 GitHub 上。

EDIT : As of Git 2.19, this is finally possible, as can be seen in this answer .编辑:从 Git 2.19 开始,这终于成为可能,正如可以在这个答案中看到的那样。

Consider upvoting that answer.考虑支持该答案。

Note: in Git 2.19, only client-side support is implemented, server-side support is still missing, so it only works when cloning local repositories.注意:在 Git 2.19 中,仅实现了客户端支持,仍然缺少服务器端支持,因此仅在克隆本地存储库时有效。 Also note that large Git hosters, eg GitHub, don't actually use the Git server, they use their own implementation, so even if support shows up in the Git server, it does not automatically mean that it works on Git hosters.另请注意,大型 Git 托管服务商,例如 GitHub,实际上并不使用 Git 服务器,它们使用自己的实现,因此即使 Git 服务器中出现支持,这并不意味着它自动适用于 Git 托管服务商。 (OTOH, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.) (OTOH,因为他们不使用 Git 服务器,所以他们可以在自己的实现中更快地实现它,然后它才会出现在 Git 服务器中。)


No, that's not possible in Git.不,这在 Git 中是不可能的。

Implementing something like this in Git would be a substantial effort and it would mean that the integrity of the clientside repository could no longer be guaranteed.在 Git 中实现这样的东西将是一项巨大的努力,这意味着客户端存储库的完整性将不再得到保证。 If you are interested, search for discussions on "sparse clone" and "sparse fetch" on the git mailinglist.如果您有兴趣,请在 git 邮件列表中搜索有关“稀疏克隆”和“稀疏获取”的讨论。

In general, the consensus in the Git community is that if you have several directories that are always checked out independently, then these are really two different projects and should live in two different repositories.一般来说,Git 社区的共识是,如果你有几个总是独立签出的目录,那么它们实际上是两个不同的项目,应该存在于两个不同的存储库中。 You can glue them back together using Git Submodules .您可以使用Git Submodules将它们粘合在一起。

You can combine the sparse checkout and the shallow clone features.您可以结合稀疏结帐浅克隆功能。 The shallow clone cuts off the history and the sparse checkout only pulls the files matching your patterns.浅克隆会切断历史记录,而稀疏检出只会提取与您的模式匹配的文件。

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

You'll need minimum git 1.9 for this to work.你需要最低 git 1.9 才能工作。 Tested it myself only with 2.2.0 and 2.2.2.仅使用 2.2.0 和 2.2.2 自己测试过。

This way you'll be still able to push , which is not possible with git archive .这样你仍然可以push ,这是git archive无法做到的。

For other users who just want to download a file/folder from github, simply use:对于只想从 github 下载文件/文件夹的其他用户,只需使用:

svn export <repo>/trunk/<folder>

eg例如

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

(yes, that's svn here. apparently in 2016 you still need svn to simply download some github files) (是的,这里是 svn。显然在 2016 年你仍然需要 svn 来简单地下载一些 github 文件)

Courtesy: Download a single folder or directory from a GitHub repo礼貌: 从 GitHub 存储库下载单个文件夹或目录

Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.重要- 确保更新 github URL 并将/tree/master/替换为 '/trunk/'。

As bash script:作为 bash 脚本:

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

Note This method downloads a folder, does not clone/checkout it.注意此方法下载一个文件夹,而不是克隆/签出它。 You can't push changes back to the repository.您无法将更改推送回存储库。 On the other hand - this results in smaller download compared to sparse checkout or shallow checkout.另一方面 - 与稀疏结帐或浅结帐相比,这会导致下载量更小。

If you never plan to interact with the repository from which you cloned, you can do a full git clone and rewrite your repository using如果您从不打算与克隆的存储库进行交互,您可以执行完整的git clone并使用重写您的存储库

git filter-branch --subdirectory-filter <subdirectory>

This way, at least the history will be preserved.这样,至少历史将被保留。

看起来要简单得多:

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

Git 1.7.0 has “sparse checkouts”. Git 1.7.0 有“稀疏检出”。 See “core.sparseCheckout” in the git config manpage , “Sparse checkout” in the git read-tree manpage , and “Skip-worktree bit” in the git update-index manpage .请参阅git config手册页中的“core.sparseCheckout”、 git read-tree手册页中的“Sparse checkout”和git update-index手册页中的“Skip-worktree bit”。

The interface is not as convenient as SVN's (eg there is no way to make a sparse checkout at the time of an initial clone), but the base functionality upon which simpler interfaces could be built is now available.该接口不如 SVN 方便(例如,在初始克隆时无法进行稀疏检出),但现在可以使用可以构建更简单接口的基本功能。

It's not possible to clone subdirectory only with Git, but below are few workarounds.仅使用 Git 无法克隆子目录,但以下是一些解决方法。

Filter branch过滤器分支

You may want to rewrite the repository to look as if trunk/public_html/ had been its project root, and discard all other history (using filter-branch ), try on already checkout branch:您可能希望重写存储库,使其看起来好像trunk/public_html/是其项目根目录,并丢弃所有其他历史记录(使用filter-branch ),尝试已签出分支:

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

Notes: The -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags.注意: --将过滤器分支选项与修订选项分开, --all用于重写所有分支和标签。 All information including original commit times or merge information will be preserved .包括原始提交时间或合并信息在内的所有信息都将被保留 This command honors .git/info/grafts file and refs in the refs/replace/ namespace, so if you have any grafts or replacement refs defined, running this command will make them permanent.此命令尊重.git/info/grafts文件和 refs refs/replace/命名空间中的 refs,因此如果您定义了任何移植或替换refs ,运行此命令将使它们永久化。

Warning!警告! The rewritten history will have different object names for all the objects and will not converge with the original branch.重写的历史对于所有对象将具有不同的对象名称,并且不会与原始分支收敛。 You will not be able to easily push and distribute the rewritten branch on top of the original branch.您将无法在原始分支之上轻松推送和分发重写的分支。 Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit would suffice to fix your problem.如果您不知道全部含义,请不要使用此命令,并且无论如何都避免使用它,如果一个简单的单个提交就足以解决您的问题。


Sparse checkout稀疏结帐

Here are simple steps with sparse checkout approach which will populate the working directory sparsely, so you can tell Git which folder(s) or file(s) in the working directory are worth checking out.以下是稀疏检出方法的简单步骤,它将稀疏地填充工作目录,因此您可以告诉 Git 工作目录中的哪些文件夹或文件值得检出。

  1. Clone repository as usual ( --no-checkout is optional):像往常一样克隆存储库( --no-checkout是可选的):

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

    You may skip this step, if you've your repository already cloned.如果您已经克隆了存储库,则可以跳过此步骤。

    Hint: For large repos, consider shallow clone ( --depth 1 ) to checkout only latest revision or/and --single-branch only.提示:对于大型存储库,考虑浅克隆--depth 1 )仅签出最新版本或/和--single-branch

  2. Enable sparseCheckout option:启用sparseCheckout选项:

     git config core.sparseCheckout true
  3. Specify folder(s) for sparse checkout ( without space at the end):为稀疏结帐指定文件夹(末尾没有空格):

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

    or edit .git/info/sparse-checkout .或编辑.git/info/sparse-checkout

  4. Checkout the branch (eg master ):签出分支(例如master ):

     git checkout master

Now you should have selected folders in your current directory.现在您应该已经在当前目录中选择了文件夹。

You may consider symbolic links if you've too many levels of directories or filtering branch instead.如果您有太多级别的目录或过滤分支,则可以考虑使用符号链接。


This will clone a specific folder and remove all history not related to it.这将克隆特定文件夹并删除与其无关的所有历史记录。

git clone --single-branch -b {branch} git@github.com:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin git@github.com:{user}/{new-repo}.git
git push -u origin master

I just wrote a script for GitHub .我刚刚为GitHub写了一个脚本

Usage:用法:

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

here is what I do这就是我所做的

git init
git sparse-checkout init
git sparse-checkout set "YOUR_DIR_PATH"
git remote add origin https://github.com/AUTH/REPO.git
git pull --depth 1 origin <SHA1_or_BRANCH_NAME>

Simple note简单的笔记

  • sparse-checkout 稀疏结帐

  • git sparse-checkout init many articles will tell you to set git sparse-checkout init --cone If I add --cone will get some files that I don't want. git sparse-checkout init许多文章会告诉你设置git sparse-checkout init --cone如果我添加--cone会得到一些我不想要的文件。

  • git sparse-checkout set "..." will set the .git\info\sparse-checkout file contents as ... git sparse-checkout set "...".git\info\sparse-checkout文件内容设置为...

    Suppose you don't want to use this command.假设您不想使用此命令。 Instead, you can open the git\info\sparse-checkout and then edit.相反,您可以打开git\info\sparse-checkout然后进行编辑。


Example例子

Suppose I want to get 2 folder full repo size>10GB↑ (include git) , as below total size < 2MB假设我想获得2 个文件夹完整repo大小>10GB↑ (包括 git) ,如下图总大小 < 2MB

  1. chrome/common/extensions/api 铬/通用/扩展/API
  2. chrome/common/extensions/permissions 铬/通用/扩展/权限
git init
git sparse-checkout init
// git sparse-checkout set "chrome/common/extensions/api/"
start .git\info\sparse-checkout   👈 open the "sparse-checkut" file

/* .git\info\sparse-checkout  for example you can input the contents as below 👇
chrome/common/extensions/api/
!chrome/common/extensions/api/commands/     👈 ! unwanted : https://www.git-scm.com/docs/git-sparse-checkout#_full_pattern_set
!chrome/common/extensions/api/devtools/
chrome/common/extensions/permissions/
*/

git remote add origin https://github.com/chromium/chromium.git
start .git\config

/* .git\config
[core]
    repositoryformatversion = 1
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
[extensions]
    worktreeConfig = true
[remote "origin"]
    url = https://github.com/chromium/chromium.git
    fetch = +refs/heads/*:refs/remotes/Github/*
    partialclonefilter = blob:none  // 👈 Add this line, This is important. Otherwise, your ".git" folder is still large (about 1GB)
*/
git pull --depth 1 origin 2d4a97f1ed2dd875557849b4281c599a7ffaba03
// or
// git pull --depth 1 origin master

  • partialclonefilter = blob:none

    I know to add this line because I know from: git clone --filter=blob:none it will write this line.我知道要添加这一行,因为我知道: git clone --filter=blob:none它会写这一行。 so I imitate it.所以我模仿它。

git version: git version 2.29.2.windows.3 git版本: git version 2.29.2.windows.3

Just to clarify some of the great answers here, the steps outlined in many of the answers assume that you already have a remote repository somewhere.只是为了澄清这里的一些很好的答案,许多答案中概述的步骤假设您已经在某个地方拥有一个远程存储库。

Given: an existing git repository, eg git@github.com:some-user/full-repo.git , with one or more directories that you wish to pull independently of the rest of the repo, eg directories named app1 and app2给定:一个现有的 git 存储库,例如git@github.com:some-user/full-repo.git ,其中包含一个或多个您希望独立于 repo 的其余部分提取的目录,例如名为app1app2的目录

Assuming you have a git repository as the above...假设您有一个如上所述的 git 存储库...

Then: you can run steps like the following to pull only specific directories from that larger repo:然后:您可以运行以下步骤以仅从该较大的存储库中提取特定目录:

mkdir app1
cd app1
git init
git remote add origin git@github.com:some-user/full-repo.git
git config core.sparsecheckout true
echo "app1/" >> .git/info/sparse-checkout
git pull origin master

I had mistakenly thought that the sparse-checkout options had to be set on the original repository, but this is not the case: you define which directories you want locally, prior to pulling from the remote.我错误地认为必须在原始存储库上设置稀疏签出选项,但事实并非如此:您在从远程提取之前定义了本地想要的目录。 The remote repo doesn't know or care about your only wanting to track a part of the repo.远程仓库不知道也不关心您只想跟踪仓库的一部分。

Hope this clarification helps someone else.希望这个澄清对其他人有所帮助。

Here's a shell script I wrote for the use case of a single subdirectory sparse checkout这是我为单个子目录稀疏结帐的用例编写的 shell 脚本

coSubDir.sh 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

Using Linux?使用 Linux? And only want easy to access and clean working tree ?并且只想要易于访问和清洁工作树? without bothering rest of code on your machine.无需打扰您机器上的其余代码。 try symlinks !尝试符号链接

git clone https://github.com:{user}/{repo}.git ~/my-project
ln -s ~/my-project/my-subfolder ~/Desktop/my-subfolder

Test测试

cd ~/Desktop/my-subfolder
git status

I wrote a .gitconfig [alias] for performing a "sparse checkout".我写了一个.gitconfig [alias]来执行“稀疏结帐”。 Check it out (no pun intended):看看(不是双关语):

On Windows run in cmd.exe在 Windows 上运行cmd.exe

git config --global alias.sparse-checkout "!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p \"$L/.git/info\" && cd \"$L\" && git init --template= && git remote add origin \"$1\" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo \"$2\" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 origin master;};f"

Otherwise:否则:

git config --global alias.sparse-checkout '!f(){ [ $# -eq 2 ] && L=${1##*/} L=${L%.git} || L=$2; mkdir -p "$L/.git/info" && cd "$L" && git init --template= && git remote add origin "$1" && git config core.sparseCheckout 1; [ $# -eq 2 ] && echo "$2" >> .git/info/sparse-checkout || { shift 2; for i; do echo $i >> .git/info/sparse-checkout; done }; git pull --depth 1 origin master;};f'

Usage :用法

# Makes a directory ForStackExchange with Plug checked out
git sparse-checkout https://github.com/YenForYang/ForStackExchange Plug

# To do more than 1 directory, you have to specify the local directory:
git sparse-checkout https://github.com/YenForYang/ForStackExchange ForStackExchange Plug Folder

The git config commands are 'minified' for convenience and storage, but here is the alias expanded:为了方便和存储, git config命令被“缩小”,但这里是扩展的别名:

# Note the --template= is for disabling templates.
# Feel free to remove it if you don't have issues with them (like I did)
# `mkdir` makes the .git/info directory ahead of time, as I've found it missing sometimes for some reason
f(){
    [ "$#" -eq 2 ] && L="${1##*/}" L=${L%.git} || L=$2;
    mkdir -p "$L/.git/info"
        && cd "$L"
        && git init --template=
        && git remote add origin "$1"
        && git config core.sparseCheckout 1;
    [ "$#" -eq 2 ]
        && echo "$2" >> .git/info/sparse-checkout
        || {
            shift 2;
            for i; do
                echo $i >> .git/info/sparse-checkout;
            done
        };
    git pull --depth 1 origin master;
};
f

Lots of great responses here, but I wanted to add that using the quotations around the directory names was failing for me on Windows Sever 2016. The files simply were not being downloaded.这里有很多很好的回应,但我想补充一点,在 Windows Sever 2016 上使用目录名称周围的引号对我来说是失败的。这些​​文件根本没有被下载。

Instead of代替

"mydir/myfolder"

I had to use我不得不使用

mydir/myfolder

Also, if you want to simply download all sub directories just use此外,如果您只想下载所有子目录,只需使用

git sparse-checkout set *

It worked for me- (git version 2.35.1)它对我有用-(git 版本 2.35.1)

git init
git remote add origin <YourRepoUrl>
git config core.sparseCheckout true
git sparse-checkout set <YourSubfolderName>
git pull origin <YourBranchName>
git init <repo>
cd <repo>
git remote add origin <url>
git config core.sparsecheckout true
echo "<path you want to clone>/*" >> .git/info/sparse-checkout
git pull --depth=1 origin <branch you want to fetch>

Example for cloning only Jetsurvey Folder from this repo从此repo仅克隆Jetsurvey文件夹的示例

git init MyFolder
cd MyFolder 
git remote add origin git@github.com:android/compose-samples.git
git config core.sparsecheckout true
echo "Jetsurvey/*" >> .git/info/sparse-checkout
git pull --depth=1 origin main

If you're actually ony interested in the latest revision files of a directory, Github lets you download a repository as Zip file, which does not contain history.如果您实际上只对目录的最新修订文件感兴趣,Github 允许您将存储库下载为 Zip 文件,其中不包含历史记录。 So downloading is very much faster.所以下载速度要快得多。

While I hate actually having to use svn when dealing with git repos :/ I use this all the time;虽然我讨厌在处理 git repos 时实际上必须使用 svn:/ 我一直都在使用它;

function git-scp() (
  URL="$1" && shift 1
  svn export ${URL/blob\/master/trunk}
)

This allows you to copy out from the github url without modification.这允许您从 github url 复制而无需修改。 Usage;用法;

--- /tmp » git-scp https://github.com/dgraph-io/dgraph/blob/master/contrib/config/kubernetes/helm                                                                                                                  1 ↵
A    helm
A    helm/Chart.yaml
A    helm/README.md
A    helm/values.yaml
Exported revision 6367.

--- /tmp » ls | grep helm
Permissions Size User    Date Modified    Name
drwxr-xr-x     - anthony 2020-01-07 15:53 helm/

Lots of good ideas and scripts above.上面有很多好的想法和脚本。 I could not help myself and combined them into a bash script with help and error checking:我忍不住将它们组合成一个带有帮助和错误检查的 bash 脚本:

#!/bin/bash

function help {
  printf "$1
Clones a specific directory from the master branch of a git repository.

Syntax:
  $(basename $0) [--delrepo] repoUrl sourceDirectory [targetDirectory]

If targetDirectory is not specified it will be set to sourceDirectory.
Downloads a sourceDirectory from a Git repository into targetdirectory.
If targetDirectory is not specified, a directory named after `basename sourceDirectory`
will be created under the current directory.

If --delrepo is specified then the .git subdirectory in the clone will be removed after cloning.


Example 1:
Clone the tree/master/django/conf/app_template directory from the master branch of
git@github.com:django/django.git into ./app_template:

\$ $(basename $0) git@github.com:django/django.git django/conf/app_template

\$ ls app_template/django/conf/app_template/
__init__.py-tpl  admin.py-tpl  apps.py-tpl  migrations  models.py-tpl  tests.py-tpl  views.py-tpl


Example 2:
Clone the django/conf/app_template directory from the master branch of
https://github.com/django/django/tree/master/django/conf/app_template into ~/test:

\$ $(basename $0) git@github.com:django/django.git django/conf/app_template ~/test

\$ ls test/django/conf/app_template/
__init__.py-tpl  admin.py-tpl  apps.py-tpl  migrations  models.py-tpl  tests.py-tpl  views.py-tpl

"
  exit 1
}

if [ -z "$1" ]; then help "Error: repoUrl was not specified.\n"; fi
if [ -z "$2" ]; then help "Error: sourceDirectory was not specified."; fi

if [ "$1" == --delrepo ]; then
  DEL_REPO=true
  shift
fi

REPO_URL="$1"
SOURCE_DIRECTORY="$2"
if [ "$3" ]; then
  TARGET_DIRECTORY="$3"
else
  TARGET_DIRECTORY="$(basename $2)"
fi

echo "Cloning into $TARGET_DIRECTORY"
mkdir -p "$TARGET_DIRECTORY"
cd "$TARGET_DIRECTORY"
git init
git remote add origin -f "$REPO_URL"
git config core.sparseCheckout true

echo "$SOURCE_DIRECTORY" > .git/info/sparse-checkout
git pull --depth=1 origin master

if [ "$DEL_REPO" ]; then rm -rf .git; fi

You can still use svn :您仍然可以使用svn

svn export https://admin@domain.example/home/admin/repos/finisht/static static --force

to " git clone " a subdirectory and then to " git pull " this subdirectory.到“ git clone ”一个子目录,然后到“ git pull ”这个子目录。

(It is not intended to commit & push.) (它不打算提交和推送。)

degit makes copies of git repositories. degit 制作 git 存储库的副本。 When you run degit some-user/some-repo, it will find the latest commit on https://github.com/some-user/some-repo and download the associated tar file to ~/.degit/some-user/some-repo/commithash.tar.gz if it doesn't already exist locally.当你运行 degit some-user/some-repo 时,它会在https://github.com/some-user/some-repo上找到最新的提交并将相关的 tar 文件下载到 ~/.degit/some-user/ some-repo/commithash.tar.gz 如果它在本地不存在。 (This is much quicker than using git clone, because you're not downloading the entire git history.) (这比使用 git clone 快得多,因为您没有下载整个 git 历史记录。)

degit <https://github.com/user/repo/subdirectory> <output folder>

Find out more https://www.npmjs.com/package/degit了解更多https://www.npmjs.com/package/degit

2022 Answer 2022答案

I'm not sure why there are so many complicated answers to this question.我不知道为什么这个问题有这么多复杂的答案。 It can be done easily by doing a sparse cloning of the repo, to the folder that you want.可以通过将 repo 稀疏克隆到您想要的文件夹来轻松完成。

  1. Navigate to the folder where you'd like to clone the subdirectory.导航到要克隆子目录的文件夹。
  2. Open cmd and run the following commands.打开cmd并运行以下命令。
  3. git clone --filter=blob:none --sparse %your-git-repo-url%
  4. git sparse-checkout add %subdirectory-to-be-cloned%
  5. cd %your-subdirectory%

Voila!瞧! Now you have cloned only the subdirectory that you want!现在您只克隆了您想要的子目录!

Explanation - What are these commands doing really?说明 - 这些命令到底在做什么?

git clone --filter=blob:none --sparse %your-git-repo-url%

In the above command,在上面的命令中,

  • --filter=blob:none => You tell git that you only want to clone the metadata files. --filter=blob:none => 你告诉 git 你只想克隆元数据文件。 This way git collects the basic branch details and other meta from remote, which will ensure that your future checkouts from origin are smooth.通过这种方式 git 从远程收集基本的分支详细信息和其他元数据,这将确保您将来从源结帐顺利进行。
  • --sparse => Tell git that this is a sparse clone. --sparse => 告诉 git 这是一个稀疏克隆。 Git will checkout only the root directory in this case.在这种情况下,Git 将只检出根目录。

Now git is informed with the metadata and ready to checkout any subdirectories/files that you want to work with.现在 git 收到元数据通知,并准备签出您要使用的任何子目录/文件。

git sparse-checkout add gui-workspace ==> Checkout folder

git sparse-checkout add gui-workspace/assets/logo.png ==> Checkout a file

Sparse clone is particularly useful when there is a large repo with several subdirectories and you're not always working on them all .有一个包含多个子目录的大型 repo 并且您并不总是对它们都进行处理时,稀疏克隆特别有用。 Saves a lot of time and bandwidth when you do a sparse clone on a large repo.在大型 repo 上进行稀疏克隆时可以节省大量时间和带宽

Additionally, now in this partially cloned repo you can continue to checkout and work like you normally would.此外,现在在这个部分克隆的 repo 中,您可以继续像往常一样结帐和工作。 All these commands work perfectly.所有这些命令都可以完美运行。

git switch -c  %new-branch-name% origin/%parent-branch-name% (or) git checkout -b %new-branch-name% origin/%parent-branch-name% 
git commit -m "Initial changes in sparse clone branch"
git push origin %new-branch-name%

@Chronial 's anwser is no longer applicable to recent versions, but it was a useful anwser as it proposed a script. @Chronial 的 anwser 不再适用于最新版本,但它是一个有用的 anwser,因为它提出了一个脚本。

Given information I gathered and the fact that I wanted to checkout only a subdirectory of a branch, I created the following shell function.鉴于我收集的信息以及我只想签出分支的子目录的事实,我创建了以下 shell function。 It gets a shallow copy of only the most recent version in the branch for the provided directories.它仅获取所提供目录的分支中最新版本的浅表副本。

function git_sparse_clone_branch() (
  rurl="$1" localdir="$2" branch="$3" && shift 3

  git clone "$rurl" --branch "$branch" --no-checkout "$localdir" --depth 1  # limit history
  cd "$localdir"

  # git sparse-checkout init --cone  # fetch only root file

  # Loops over remaining args
  for i; do
    git sparse-checkout set "$i"
  done

  git checkout $branch
)

So example use:所以示例使用:

git_sparse_clone_branch git@github.com:user/repo.git localpath branch-to-clone path1_to_fetch path2_to_fetch

In my case the clone was "only" 23MB versus 385MB for the full clone.就我而言,克隆“仅”为 23MB,而完整克隆为 385MB。

Tested with git version 2.36.1.使用 git 版本 2.36.1 进行测试。

(extending this answer ) (扩展这个答案

Cloning subdirectory in specific tag在特定标签中克隆子目录

If you want to clone a specific subdirectory of a specific tag you can follow the steps below.如果你想克隆特定标签的特定子目录,你可以按照以下步骤操作。

I clone the distribution/src/main/release/samples/ subdirectory of cxf github repo in cxf-3.5.4 tag.我在cxf-3.5.4标签中克隆了cxf github repo 的distribution/src/main/release/samples/子目录。

Note: if you attempt to just clone the above repo you will see that it is very big.注意:如果你试图只克隆上面的 repo,你会发现它非常大。 The commands below clones only what is needed.以下命令仅克隆需要的内容。

git clone --depth 1 --filter=blob:none --sparse https://github.com/apache/cxf
cd cxf/
git sparse-checkout set distribution/src/main/release/samples/
git fetch --depth 1 origin cxf-3.5.4
# This is the hash on which the tag points, however using the tag does not work.
git switch --detach 3ef4fde

Cloning subdirectory in specific branch在特定分支中克隆子目录

I clone the distribution/src/main/release/samples/ subdirectory of cxf github repo in 2.6.x-fixes branch.我在2.6.x-fixes分支中克隆了cxf github repo 的distribution/src/main/release/samples/子目录。

git clone --depth 1 --filter=blob:none --sparse https://github.com/apache/cxf --branch 2.6.x-fixes
cd cxf/
git sparse-checkout set distribution/src/main/release/samples/
  • If you want to clone如果你想clone

     git clone --no-checkout <REPOSITORY_URL> cd <REPOSITORY_NAME>
    1. Now set the specific file / directory you wish to pull into the working-directory :现在设置您希望拉入工作目录的特定文件/目录
       git sparse-checkout set <PATH_TO_A_SPECIFIC_DIRECTORY_OR_FILE_TO_PULL>
    2. Afterwards, you should reset hard your working-directory to the commit you wish to pull.之后,您应该将您的工作目录硬重置为您希望提取的提交。

      For example, we will reset it to the default origin/master 's HEAD commit.例如,我们将其重置为默认origin/master的 HEAD 提交。

       git reset --hard HEAD
  • If you want to git init and then remote add如果你想git init然后remote add

     git init git remote add origin <REPOSITORY_URL>
    1. Now set the specific file / directory you wish to pull into the working-directory :现在设置您希望拉入工作目录的特定文件/目录
       git sparse-checkout set <PATH_TO_A_SPECIFIC_DIRECTORY_OR_FILE_TO_PULL>
    2. Pull the last commit:拉最后一次提交:
       git pull origin master

NOTE:笔记:

If you want to add another directory/file to your working-directory , you may do it like so:如果您想将另一个目录/文件添加到您的工作目录,您可以这样做:

 git sparse-checkout add <PATH_TO_ANOTHER_SPECIFIC_DIRECTORY_OR_FILE_TO_PULL>

If you want to add all the repository to the working-directory , do it like so:如果要将所有存储库添加到working-directory ,请这样做:

 git sparse-checkout add *

If you want to empty the working-directory , do it like so:如果要清空工作目录,请这样做:

 git sparse-checkout set empty

If you want, you can view the status of the tracked files you have specified, by running:如果需要,您可以通过运行以下命令查看您指定的跟踪文件的状态:

git status

If you want to exit the sparse mode and clone all the repository, you should run:如果要退出稀疏模式并克隆所有存储库,则应运行:

git sparse-checkout set *
git sparse-checkout set init
git sparse-checkout set disable

I don't know if anyone succeeded pulling specific directory, here is my experience: git clone --filter=blob:none --single-branch <repo>, cancel immediately while downloading objects, enter repo, then git checkout origin/master <dir>, ignore errors (sha1), enter dir, repeat checkout (using new dir) for every sub-directory.不知道有没有人成功拉取特定目录,这是我的经验:git clone --filter=blob:none --single-branch <repo>,下载对象时立即取消,进入repo,然后git checkout origin/master <dir>,忽略错误(sha1),输入目录,为每个子目录重复检出(使用新目录)。 I managed to quickly get source files in this way我设法以这种方式快速获取源文件

For macOS users对于 macOS 用户

For zsh users (macOS users, specifically) cloning Repos with ssh, I just create a zsh command based on the answer by @Ciro Santilli:对于使用 ssh 克隆 Repos 的 zsh 用户(特别是 macOS 用户),我只是根据@Ciro Santilli 的回答创建了一个 zsh 命令:

requirement: The version of git matters.要求:git 的版本很重要。 It doesn't work on 2.25.1 because of the --sparse option.由于--sparse选项,它在2.25.1上不起作用。 Try upgrade your git to the latest version.尝试将您的 git 升级到最新版本。 (eg tested 2.36.1 ) (例如测试2.36.1

example usage:示例用法:

git clone git@github.com:google-research/google-research.git etcmodel

code:代码:

function gitclone {
    readonly repo_root=${1?Usage: gitclone repo.git sub_dir}
    readonly repo_sub=${2?Usage: gitclone repo.git sub_dir}
    echo "-- Cloning $repo_root/$repo_sub"
    git clone \
      --depth 1 \
      --filter=tree:0 \
      --sparse \
      $repo_root \
    ;
    repo_folder=${repo_root#*/}
    repo_folder=${repo_folder%.*}
    cd $repo_folder
    git sparse-checkout set $repo_sub
    cd -
}


gitclone "$@"

So i tried everything in this tread and nothing worked for me ... Turns out that on version 2.24 of Git (the one that comes with cpanel at the time of this answer), you don't need to do this所以我尝试了这方面的一切,但对我没有任何效果......结果是在 Git 2.24 版(在这个答案时随 cpanel 一起提供的版本),你不需要这样做

echo "wpm/*" >> .git/info/sparse-checkout

all you need is the folder name您只需要文件夹名称

wpm/*

So in short you do this所以简而言之,你这样做

git config core.sparsecheckout true

you then edit the .git/info/sparse-checkout and add the folder names (one per line) with /* at the end to get subfolders and files然后,您编辑 .git/info/sparse-checkout 并在末尾添加文件夹名称(每行一个)和 /* 以获取子文件夹和文件

wpm/*

Save and run the checkout command保存并运行结帐命令

git checkout master

The result was the expected folder from my repo and nothing else Upvote if this worked for you结果是我的 repo 中的预期文件夹,如果这对你有用,没有别的 Upvote

Darker made a post on dev.to on getting this done using a bash script. Darker 在 dev.to 上发表了一篇关于使用 bash 脚本完成这项工作的帖子。 Check out https://dev.to/sanixdarker/git-cloning-a-subdirectory-of-a-gi-project-2mld查看https://dev.to/sanixdarker/git-cloning-a-subdirectory-of-a-gi-project-2mld

Darker made a post on dev.to on getting this done using a bash script. Darker 在 dev.to 上发表了一篇关于使用 bash 脚本完成这项工作的帖子。 Check out https://dev.to/sanixdarker/git-cloning-a-subdirectory-of-a-gi-project-2mld查看https://dev.to/sanixdarker/git-cloning-a-subdirectory-of-a-gi-project-2mld

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM