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

发布于 2024-07-14 07:09:44 字数 583 浏览 8 评论 0 原文

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

/finisht
/static

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

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

Is there a way to do this with Git?

I have my Git repository which, at the root, has two subdirectories:

/finisht
/static

When this was in SVN, /finisht was checked out in one place, while /static was checked out elsewhere, like so:

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

Is there a way to do this with Git?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

甜嗑 2024-07-21 07:09:44

您尝试做的事情称为稀疏签出,该功能已在 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 的回答 docs/git-clone" rel="noreferrer">克隆 和稀疏结账。


从 Git 2.25.0(2020 年 1 月)开始,实验性 sparse-checkout Git 中添加命令:

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

What you are trying to do is called a sparse checkout, and that feature was added in Git 1.7.0 (Feb. 2012). 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:

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.

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.

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.


As of Git 2.25.0 (Jan 2020) an experimental sparse-checkout command is added in Git:

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
有深☉意 2024-07-21 07:09:44

git clone --filter + git稀疏-checkout 仅下载所需的文件

例如,仅克隆子目录 small/< 中的文件/code> 在此测试存储库中: https://github .com/cirosantilli/test-git-partial-clone-big-small-no-bigtree

git clone -n --depth=1 --filter=tree:0 \
  https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree
cd test-git-partial-clone-big-small-no-bigtree
git sparse-checkout set --no-cone small
git checkout

您还可以选择多个目录进行下载:

git sparse-checkout set --no-cone small small2

但是,此方法不适用于单个文件,但这是另一种方法这样做: 如何从 git 存储库中稀疏地只签出一个文件?

在这个测试中,克隆基本上是瞬时的,我们可以确认克隆的存储库非常小,如所期望的:

du --apparent-size -hs * .* | sort -hs

给出:

2.0K    small
226K    .git

该测试存储库包含:

  • 一个 big/ 子目录,包含 10x 10MB 文件
  • 10x 10MB 文件 0, 1, ... 9 在顶层(这是因为某些之前的尝试会下载顶级文件)
  • 一个 small/small2/ 子目录,其中包含 1000 个文件,每个文件大小为一个字节

所有内容都是伪随机的,因此不可压缩,因此我们可以轻松地注意是否下载了任何大文件,例如 ncdu

因此,如果您下载了不需要的任何内容,您将获得 100 MB 的额外空间,而且这是非常明显的。

在上面,git clone 下载单个对象,大概是提交:

Cloning into 'test-git-partial-clone-big-small'...
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), done.

然后最终签出下载我们请求的文件:

remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), 10.19 KiB | 2.04 MiB/s, done.
remote: Enumerating objects: 253, done.
remote: Counting objects: 100% (253/253), done.
Receiving objects: 100% (253/253), 2.50 KiB | 2.50 MiB/s, done.
remote: Total 253 (delta 0), reused 253 (delta 0), pack-reused 0
Your branch is up to date with 'origin/master'.

于 2023 年 1 月在 git 2.37.2、Ubuntu 22.10 上测试。

TODO 还可以防止下载不需要的树对象

上述方法下载所有 Git 树对象(即目录列表,但不是实际文件内容)。 我们可以通过运行来确认:

git ls-files

并看到它包含大文件目录,例如:

big/0

在大多数项目中,这不会成为问题,因为与实际文件内容相比,这些文件应该很小,但我的完美主义者希望避开他们。

我还在目录 big_tree 下创建了一个非常极端的存储库,其中包含一些非常大的树对象(100 MB):https://github.com/cirosantilli/test-git-partial-clone-big-small

如果有人找到克隆的方法,请告诉我其中的 small/ 目录!

关于命令

--filter 选项是与远程协议的更新一起添加的,它确实可以防止从服务器下载对象。

不幸的是,还需要稀疏结帐部分。 您也可以只下载更容易理解的某些文件:

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

但由于某种原因,该方法 逐个下载文件一个非常慢,使其无法使用,除非目录中的文件很少。

另一个不太详细但失败的尝试是:

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

但是会下载顶级目录中的所有文件: 如何阻止 git clone --filter=blob:none --sparse 下载根目录下的文件?

梦想:任何目录都可以有 web接口元数据

此功能可能会彻底改变 Git。

想象一下,将企业的所有代码库放在一个单一的 monorepo 中,而无需 丑陋的第三方工具,例如 <代码>存储库

想象一下直接在存储库中存储巨大的blob,而不需要任何丑陋的第三方扩展

想象一下,如果 GitHub 允许每个文件/目录元数据,例如星号和权限,这样您就可以存储您的所有个人资料都位于一个存储库中。

想象一下,如果子模块被完全像常规目录一样对待:只需请求一个树 SHA,类似 DNS 的机制就会解析您的请求,首先查看您的 < a href="https://stackoverflow.com/questions/2350996/how-can-one-safely-use-a-shared-object-database-in-git">本地 ~/.git,然后首先到更近的服务器(您企业的镜像/缓存)并最终到达 GitHub。

我有一个梦想。

测试锥 monorepo 理念

这是一种无需子模块的 monorepo 维护的可能理念。

我们希望避免使用子模块,因为每次进行具有子模块和非子模块组件的更改时都必须提交到两个单独的存储库,这很烦人。

每个带有 Makefile 或类似文件的目录都应该自行构建和测试。

此类目录可以依赖于以下任一者:

  • 其下的每个文件和子目录直接在其最新版本中
  • 外部目录只能在指定版本中依赖

在 git 开始原生支持此功能(即只能跟踪子目录的子模块)之前,我们可以使用一些支持此功能git 跟踪文件中的元数据:

monorepo.json

{
    "path": "some/useful/lib",
    "sha": 12341234123412341234,
}

,其中 sha 指整个存储库的常用 SHA。 然后我们需要脚本来检查这些目录,例如在 gitignored monorepo 文件夹下:

monorepo/som/useful/lib

每当您更改文件时,您都必须沿着树向上并测试具有 Makefile 的所有目录。 这是因为目录可能依赖于最新版本的子目录,因此您总是可能会破坏上面的内容。

相关:

git clone --filter + git sparse-checkout downloads only the required files

E.g., to clone only files in subdirectory small/ in this test repository: https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree

git clone -n --depth=1 --filter=tree:0 \
  https://github.com/cirosantilli/test-git-partial-clone-big-small-no-bigtree
cd test-git-partial-clone-big-small-no-bigtree
git sparse-checkout set --no-cone small
git checkout

You could also select multiple directories for download with:

git sparse-checkout set --no-cone small small2

This method doesn't work for individual files however, but here is another method that does: How to sparsely checkout only one single file from a git repository?

In this test, clone is basically instantaneous, and we can confirm that the cloned repository is very small as desired:

du --apparent-size -hs * .* | sort -hs

giving:

2.0K    small
226K    .git

That test repository contains:

  • a big/ subdirectory with 10x 10MB files
  • 10x 10MB files 0, 1, ... 9 on toplevel (this is because certain previous attempts would download toplevel files)
  • a small/ and small2/ subdirectories with 1000 files of size one byte each

All contents are pseudo-random and therefore incompressible, so we can easily notice if any of the big files were downloaded, e.g. with ncdu.

So if you download anything you didn't want, you would get 100 MB extra, and it would be very noticeable.

On the above, git clone downloads a single object, presumably the commit:

Cloning into 'test-git-partial-clone-big-small'...
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 1 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), done.

and then the final checkout downloads the files we requested:

remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), 10.19 KiB | 2.04 MiB/s, done.
remote: Enumerating objects: 253, done.
remote: Counting objects: 100% (253/253), done.
Receiving objects: 100% (253/253), 2.50 KiB | 2.50 MiB/s, done.
remote: Total 253 (delta 0), reused 253 (delta 0), pack-reused 0
Your branch is up to date with 'origin/master'.

Tested on git 2.37.2, Ubuntu 22.10, on January 2023.

TODO also prevent download of unneeded tree objects

The above method downloads all Git tree objects (i.e. directory listings, but not actual file contents). We can confirm that by running:

git ls-files

and seeing that it contains the directories large files such as:

big/0

In most projects this won't be an issue, as these should be small compared to the actual file contents, but the perfectionist in me would like to avoid them.

I've also created a very extreme repository with some very large tree objects (100 MB) under the directory big_tree: https://github.com/cirosantilli/test-git-partial-clone-big-small

Let me know if anyone finds a way to clone just the small/ directory from it!

About the commands

The --filter option was added together with an update to the remote protocol, and it truly prevents objects from being downloaded from the server.

The sparse-checkout part is also needed unfortunately. 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-big-small
cd test-git-partial-clone-big-small
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.

Another less verbose but failed attempt was:

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

but that downloads all files in the toplevel directory: How to prevent git clone --filter=blob:none --sparse from downloading files on the root directory?

The dream: any directory can have web interface metadata

This feature could revolutionize Git.

Imagine having all the code base of your enterprise in a single monorepo without ugly third-party tools like repo.

Imagine storing huge blobs directly in the repo without any ugly third party extensions.

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.

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.

I have a dream.

The test cone monorepo philosophy

This is a possible philosophy for monorepo maintenance without submodules.

We want to avoid submodules because it is annoying to have to commit to two separate repositories every time you make a change that has a submodule and non-submodule component.

Every directory with a Makefile or analogous should build and test itself.

Such directories can depend on either:

  • every file and subdirectory under it directly at their latest versions
  • external directories can be relied upon only at specified versions

Until git starts supporting this natively (i.e. submodules that can track only subdirectories), we can support this with some metadata in a git tracked file:

monorepo.json

{
    "path": "some/useful/lib",
    "sha": 12341234123412341234,
}

where sha refers to the usual SHA of the entire repository. Then we need scripts that will checkout such directories e.g. under a gitignored monorepo folder:

monorepo/som/useful/lib

Whenever you change a file, you have to go up the tree and test all directories that have Makefile. This is because directories can depend on subdirectories at their latest versions, so you could always break something above you.

Related:

浮世清欢 2024-07-21 07:09:44

从 Git 2.19 开始,这终于成为可能,如此答案中所示。

考虑投票赞成该答案。

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


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

在 Git 中实现这样的事情将是一项巨大的工作,这意味着客户端存储库的完整性将无法再得到保证。 如果您有兴趣,请在 Git 邮件列表上搜索有关“稀疏克隆”和“稀疏获取”的讨论。

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

As of Git 2.19, this is finally possible, as can be seen in this answer.

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. Also note that large Git hosters, e.g. 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. (On the other hand, since they don't use the Git server, they could implement it faster in their own implementations before it shows up in Git server.)


No, that's not possible in Git.

Implementing something like this in Git would be a substantial effort and it would mean that the integrity of the client-side repository could no longer be guaranteed. If you are interested, search for discussions on "sparse clone" and "sparse fetch" on the Git mailing list.

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. You can glue them back together using Git Submodules.

尴尬癌患者 2024-07-21 07:09:44

您可以将稀疏结帐浅克隆功能结合起来。 浅克隆会切断历史记录,而稀疏签出只会提取与您的模式匹配的文件。

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 无法实现的。

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. Tested it myself only with 2.2.0 and 2.2.2.

This way you'll be still able to push, which is not possible with git archive.

过度放纵 2024-07-21 07:09:44

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

svn export <repo>/trunk/<folder>

eg

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
}

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

For other users who just want to download a file/folder from github, simply use:

svn export <repo>/trunk/<folder>

e.g.

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)

Courtesy: Download a single folder or directory from a GitHub repo

Important - Make sure you update the github URL and replace /tree/master/ with '/trunk/'.

As bash script:

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.

¢蛋碎的人ぎ生 2024-07-21 07:09:44

2022年答案

我不知道为什么这个问题有这么多复杂的答案。 通过将存储库稀疏克隆到您想要的文件夹,可以轻松完成此操作。

  1. 导航到您想要克隆子目录的文件夹。
  2. 打开 cmd 并运行以下命令。
  3. git clone --filter=blob:none --sparse %your-git-repo-url%
  4. cd %存储库目录%
  5. git稀疏-checkout add %要克隆的子目录%
  6. cd %your-subdirectory%

瞧! 现在您仅克隆了所需的子目录!

解释 - 这些命令到底在做什么?

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

在上面的命令中,

  • <代码>--filter=blob:none => 您告诉 git 您只想克隆元数据文件。 这样 git 就可以从远程收集基本分支详细信息和其他元数据,这将确保您将来从原点签出的过程顺利进行。
  • --稀疏 => 告诉 git 这是一个稀疏克隆。 在这种情况下,Git 将仅检出根目录。

现在 git 已获知元数据,并准备好签出您想要使用的任何子目录/文件。

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

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

稀疏克隆有一个包含多个子目录的大型存储库并且您并不总是处理所有子目录时特别有用。 当您在大型存储库上进行稀疏克隆时,节省大量时间和带宽

此外,
现在,在这个部分克隆的存储库中,您可以像平常一样继续结账和工作。 所有这些命令都可以完美运行。

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%

2022 Answer

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.

  1. Navigate to the folder where you'd like to clone the subdirectory.
  2. Open cmd and run the following commands.
  3. git clone --filter=blob:none --sparse %your-git-repo-url%
  4. cd %the repository directory%
  5. git sparse-checkout add %subdirectory-to-be-cloned%
  6. 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. This way git collects the basic branch details and other meta from remote, which will ensure that your future checkouts from origin are smooth.
  • --sparse => Tell git that this is a sparse clone. Git will checkout only the root directory in this case.

Now git is informed with the metadata and ready to checkout any subdirectories/files that you want to work with.

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. Saves a lot of time and bandwidth when you do a sparse clone on a large repo.

Additionally,
now in this partially cloned repo you can continue to checkout and work like you normally would. 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%
时光病人 2024-07-21 07:09:44

如果您从不打算与克隆的存储库进行交互,则可以执行完整的 git 克隆并使用

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

这种方式重写您的存储库,至少可以保留历史记录。

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 filter-branch --subdirectory-filter <subdirectory>

This way, at least the history will be preserved.

浅紫色的梦幻 2024-07-21 07:09:44

看起来要简单得多:

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

This looks far simpler:

git archive --remote=<repo_url> <branch> <path> | tar xvf -
梦明 2024-07-21 07:09:44

Git 1.7.0 有“稀疏签出”。 看
git config 手册页中的“core.sparseCheckout”,
中的“稀疏结帐” git read-tree 手册页,以及
< 中的“Skip-worktree 位” em>git update-index 手册页

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

Git 1.7.0 has “sparse checkouts”. 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.

The interface is not as convenient as SVN’s (e.g. 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.

余生一个溪 2024-07-21 07:09:44

仅使用 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 
      光盘吧 
      

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

    提示:对于大型存储库,请考虑浅克隆--深度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 
      

现在您应该已经在当前目录中选择了文件夹。

如果您有太多级别的目录或过滤分支,您可以考虑使用符号链接。


It's not possible to clone subdirectory only with Git, but below are few workarounds.

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:

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

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.

  1. Clone repository as usual (--no-checkout is optional):

    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.

  2. Enable sparseCheckout option:

    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.

  4. Checkout the branch (e.g. 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.


云醉月微眠 2024-07-21 07:09:44

这将克隆特定文件夹并删除与其不相关的所有历史记录。

git clone --single-branch -b {branch} [email protected]:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin [email protected]:{user}/{new-repo}.git
git push -u origin master

This will clone a specific folder and remove all history not related to it.

git clone --single-branch -b {branch} [email protected]:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin [email protected]:{user}/{new-repo}.git
git push -u origin master
一场信仰旅途 2024-07-21 07:09:44

它对我有用-(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>

It worked for me- (git version 2.35.1)

git init
git remote add origin <YourRepoUrl>
git config core.sparseCheckout true
git sparse-checkout set <YourSubfolderName>
git pull origin <YourBranchName>
十秒萌定你 2024-07-21 07:09:44

这就是我所做的

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>

简单注释

  • sparse-checkout

  • git稀疏结帐init 许多文章会告诉你设置 git稀疏-checkout init --cone 如果我添加 --cone 会得到一些我不想要的文件.

  • git稀疏-checkout set“...”会将.git\info\sparse-checkout文件内容设置为...

    假设您不想使用此命令。 相反,您可以打开 git\info\sparse-checkout 然后进行编辑。


示例

假设我想获取 2 文件夹完整repo 大小>10GB ↑(包含git),如下总大小 2MB

  1. chrome/common/extensions/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

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 set "..." will set the .git\info\sparse-checkout file contents as ...

    Suppose you don't want to use this command. Instead, you can open the git\info\sparse-checkout and then edit.


Example

Suppose I want to get 2 folderfull repo size>10GB↑ (include git), as below total size < 2MB

  1. chrome/common/extensions/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. so I imitate it.

git version: git version 2.29.2.windows.3

那些过往 2024-07-21 07:09:44

编写了一个 Python 2 脚本用于从 GitHub 下载子目录。

用法:

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

Python 3 fork https://gitlab.com/vitaly-zdanevich/github-download -dir

I wrote a Python 2 script for downloading a subdirectory from GitHub.

Usage:

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

Python 3 fork https://gitlab.com/vitaly-zdanevich/github-download-dir

街道布景 2024-07-21 07:09:44

使用Linux? 只想轻松访问和清理工作树? 而不打扰机器上的其余代码。 尝试符号链接

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

测试

cd ~/Desktop/my-subfolder
git status

Using 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
江湖彼岸 2024-07-21 07:09:44

只是为了澄清这里的一些很好的答案,许多答案中概述的步骤假设您已经在某个地方有一个远程存储库。

给定:现有的 git 存储库,例如 [email  protected]:some-user/full-repo.git,包含一个或多个您希望独立提取存储库其余部分的目录,例如名为 < code>app1 和 app2

假设您有一个如上所述的 git 存储库...

然后:您可以运行如下步骤来仅拉取 来自较大存储库的特定目录:

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

我错误地认为必须在原始存储库上设置稀疏签出选项,但事实并非如此:您在从本地存储库中提取之前定义了本地所需的目录偏僻的。 远程存储库不知道也不关心您只想跟踪存储库的一部分。

希望这个澄清对其他人有帮助。

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, e.g. [email protected]:some-user/full-repo.git, with one or more directories that you wish to pull independently of the rest of the repo, e.g. directories named app1 and app2

Assuming you have a git repository as the above...

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 [email protected]: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.

仄言 2024-07-21 07:09:44

这是我为单个子目录稀疏签出

coSubDir.sh的用例编写的 shell 脚本

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

Here's a shell script I wrote for the use case of a single subdirectory sparse checkout

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
聽兲甴掵 2024-07-21 07:09:44
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>

仅克隆来自此 repo

git init MyFolder
cd MyFolder 
git remote add origin [email protected]:android/compose-samples.git
git config core.sparsecheckout true
echo "Jetsurvey/*" >> .git/info/sparse-checkout
git pull --depth=1 origin main
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

git init MyFolder
cd MyFolder 
git remote add origin [email protected]:android/compose-samples.git
git config core.sparsecheckout true
echo "Jetsurvey/*" >> .git/info/sparse-checkout
git pull --depth=1 origin main
装纯掩盖桑 2024-07-21 07:09:44

@Chronial 的答案不再适用于最新版本,但它是一个有用的答案,因为它提出了一个脚本。

为了仅检出分支的一个或多个子目录,我创建了以下 shell 函数。 它仅获取所提供目录的分支中最新版本的浅表副本。

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

  git clone "$rurl" --branch "$branch" --no-checkout "$localdir" --depth 1  # limit history
  cd "$localdir" || return
  
  # git sparse-checkout init --cone  # fetch only root file

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

  git checkout --ignore-other-worktrees "$branch"
)

示例使用:

git_sparse_clone_branch [email protected]:user/repo.git localpath branch-to-clone path1_to_fetch path2_to_fetch

在我的例子中,克隆“仅”23MB,而完整克隆则为 385MB。

使用 git 版本 2.36.1 进行测试。

@Chronial 's answer is no longer applicable to recent versions, but it was a useful answer as it proposed a script.

To checkout only one or more subdirectories of a branch, I created the following 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() (
  local rurl="$1" localdir="$2" branch="$3" && shift 3

  git clone "$rurl" --branch "$branch" --no-checkout "$localdir" --depth 1  # limit history
  cd "$localdir" || return
  
  # git sparse-checkout init --cone  # fetch only root file

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

  git checkout --ignore-other-worktrees "$branch"
)

So example use:

git_sparse_clone_branch [email protected]: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.

Tested with git version 2.36.1 .

梦情居士 2024-07-21 07:09:44

我编写了一个 .gitconfig [alias] 来执行“稀疏结帐”。 检查一下(没有双关语):

在 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"

否则:

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'

用法

# 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

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

I wrote a .gitconfig [alias] for performing a "sparse checkout". Check it out (no pun intended):

On Windows run in 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:

# 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
仅此而已 2024-07-21 07:09:44

这里有很多很好的回复,但我想补充一点,在 Windows Sever 2016 上使用目录名称周围的引号对我来说是失败的。文件根本没有被下载。

而不是

"mydir/myfolder"

我必须使用

mydir/myfolder

另外,如果您想简单地下载所有子目录,只需使用

git sparse-checkout set *

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.

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 *
夏末染殇 2024-07-21 07:09:44

如果您实际上只对目录的最新版本文件感兴趣,Github 允许您将存储库下载为 Zip 文件,该文件不包含历史记录。 所以下载速度要快得多。

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. So downloading is very much faster.

隱形的亼 2024-07-21 07:09:44

(扩展此答案

克隆特定标签中的子目录

如果您想克隆特定标签的特定子目录,您可以按照步骤如下。

我克隆了 cxfdistribution/src/main/release/samples/ 子目录> github 仓库 cxf -3.5.4 标签。

注意:如果您尝试克隆上述存储库,您会发现它非常大。 下面的命令仅克隆需要的内容。

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

克隆特定分支中的子目录

我克隆了 distribution/src/main/release/samples/ 子目录>cxf github 仓库 2.6.x-fixes 分支。

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/

(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.

Note: if you attempt to just clone the above repo you will see that it is very big. 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.

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/
随遇而安 2024-07-21 07:09:44

虽然我讨厌在处理 git repos 时实际上必须使用 svn :/我一直使用它;

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

这允许您从 github url 复制出来而无需修改。 用法;

--- /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/

While I hate actually having to use svn when dealing with git repos :/ I use this all the time;

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. 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/
潇烟暮雨 2024-07-21 07:09:44

上面有很多好的想法和脚本。 我忍不住将它们组合成一个带有帮助和错误检查的 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
[email protected]:django/django.git into ./app_template:

\$ $(basename $0) [email protected]: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) [email protected]: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

Lots of good ideas and scripts above. I could not help myself and combined them into a bash script with help and error checking:

#!/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
[email protected]:django/django.git into ./app_template:

\$ $(basename $0) [email protected]: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) [email protected]: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
扛刀软妹 2024-07-21 07:09:44

degit 制作 git 存储库的副本。 当你运行数字时
some-user/some-repo,它会找到最新的提交
https://github.com/some-user/some-repo 并下载伴生焦油
如果没有,则将文件保存到 ~/.degit/some-user/some-repo/commithash.tar.gz
本地已经存在。 (这比使用 git clone 快得多,
因为您没有下载整个 git 历史记录。)

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

了解更多信息 https://www.npmjs.com /包/数字

degit makes copies of git repositories. 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. (This is much quicker than using git clone,
because you're not downloading the entire git history.)

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

Find out more https://www.npmjs.com/package/degit

不疑不惑不回忆 2024-07-21 07:09:44

您仍然可以使用 svn:

svn export https://[email protected]/home/admin/repos/finisht/static static --force

到“git clone”子目录,然后到“git pull”这个子目录。

(这并不是为了提交和推送。)

You can still use svn:

svn export https://[email protected]/home/admin/repos/finisht/static static --force

to "git clone" a subdirectory and then to "git pull" this subdirectory.

(It is not intended to commit & push.)

顾冷 2024-07-21 07:09:44
  • 如果您想克隆

    git clone --no-checkout ; 
      cd ; 
      
    1. 现在设置您想要拉入工作目录的特定文件/目录:
      git稀疏结帐设置 
        
    2. 之后,您应该将您的工作目录硬重置为您想要拉取的提交。
      <块引用>

      例如,我们将其重置为默认的 origin/master 的 HEAD 提交。

      git reset --hard HEAD 
        
  • 如果你想git init然后远程添加

    <前><代码>git init
    git remote add origin ;

    1. 现在设置您想要拉入工作目录的特定文件/目录:
      git稀疏结帐设置 
        
    2. 拉取最后一次提交:
      git pull origin master 
        

注意:

如果您想将另一个目录/文件添加到您的工作目录,您可以这样做:

git稀疏结帐添加; 
  

如果您想将所有存储库添加到工作目录,请像这样操作:

git稀疏结帐添加* 
  

如果您想清空工作目录,请像这样操作:

git稀疏结帐设置为空 
  

如果需要,您可以通过运行以下命令来查看指定的跟踪文件的状态:

git status

If如果你想退出稀疏模式并克隆所有存储库,你应该运行:

git sparse-checkout set *
git sparse-checkout set init
git sparse-checkout set disable
  • If you want to 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.

      git reset --hard HEAD
      
  • If you want to git init and then 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:

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
野却迷人 2024-07-21 07:09:44

我不知道是否有人成功拉取特定目录,这是我的经验: git clone --filter=blob:none --single-branch ,下载对象时立即取消,输入 repo,然后 git checkout origin/ master

,忽略错误 (sha1),输入 dir,对每个子目录重复签出(使用新目录)。 我通过这种方式很快就得到了源文件

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. I managed to quickly get source files in this way

时光病人 2024-07-21 07:09:44

对于 macOS 用户

对于 zsh 用户(特别是 macOS 用户)使用 ssh 克隆 Repos,我只是根据 @Ciro Santilli 的答案创建一个 zsh 命令:

要求:git 的版本很重要。 由于 --sparse 选项,它不适用于 2.25.1。 尝试将您的 git 升级到最新版本。 (例如测试的2.36.1

示例用法:

git clone [email protected]:google-research/google-research.git etcmodel

代码:

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 "$@"

For macOS users

For zsh users (macOS users, specifically) cloning Repos with ssh, I just create a zsh command based on the answer by @Ciro Santilli:

requirement: The version of git matters. It doesn't work on 2.25.1 because of the --sparse option. Try upgrade your git to the latest version. (e.g. tested 2.36.1)

example usage:

git clone [email protected]: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 "$@"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文