Как клонировать только некоторые каталоги из репозитория git?

Например, я хочу загрузить PCL 3d_rec_framework.

Это репозиторий git PCL: https://github.com/PointCloudLibrary/pcl.git

Как я могу загрузить этот каталог?

https://github.com/PointCloudLibrary/pcl/tree/master/apps

Я пробовал это, но это не сработало:

sam@sam:~/code/pcl_standalone$ git clone https://github.com/PointCloudLibrary/pcl/tree/master/apps/3d_rec_frameworkCloning into '3d_rec_framework'...error: The requested URL returned error: 403 while accessing https://github.com/PointCloudLibrary/pcl/tree/master/apps/3d_rec_framework/info/refsfatal: HTTP request failedsam@sam:~/code/pcl_standalone$ 

Я не хочу загружать git из PCL и удалять все другие каталоги, которые мне не нужны.

Как мне загрузить только один каталог?

ответ доби больше не актуален со времен git v1.7. Теперь вы можете извлекать определенные папки из репозитория. Полные инструкции находятся здесь здесь.

git init <repo>cd <repo>git remote add -f origin <url>git config core.sparseCheckout trueecho "some/dir/" >> .git/info/sparse-checkoutecho "another/sub/tree" >> .git/info/sparse-checkout

Это сообщает git, какие каталоги вы хотите проверить. Затем вы можете извлечь только эти каталоги

git pull origin master

Во-первых, сделайте:

git clone --depth 1 [repo root] [name of destination directory]

Затем:

cd [name of destination directory]

...И, наконец,:

git filter-branch --prune-empty --subdirectory-filter [path to sub-dir] HEAD

Это так просто. Git перепишет репозиторий так, чтобы был включен только желаемый вложенный каталог. Это работает, даже если вложенный каталог имеет глубину в несколько слоев. Просто назовите целевой каталог именем вложенного каталога. Затем в команде "git filter-branch" укажите относительный путь к вложенному каталогу. О, этот --depth 1 говорит git чтобы загрузить только верхнюю часть головы (по сути, удаляя историю).

git clone --filter из git 2.19 теперь работает на GitHub (протестировано 2021-01-14, git 2.30.0)

Эта опция была добавлена вместе с обновлением удаленного протокола, и она действительно предотвращает загрузку объектов с сервера.

Например, клонировать только объекты, необходимые для 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-clonegit sparse-checkout init --conegit sparse-checkout set d1

Вот менее минималистичная и более реалистичная версия на 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-clonegit sparse-checkout init --conegit sparse-checkout set small

Это хранилище содержит:

  • большой каталог с файлами размером 10 10 МБ
  • небольшой каталог с 1000 файлами размером в один байт

Все содержимое является псевдослучайным и, следовательно, несжимаемым.

Время клонирования в моем Интернете со скоростью 36,4 Мбит/с:

  • полный: 24 секунды
  • частичный: "мгновенный";

То sparse-checkout часть, к сожалению, тоже нужна. Вы также можете загружать только определенные файлы с гораздо более понятным:

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

но этот метод по какой-то причине загружает файлы один за другим очень медленно, что делает его непригодным для использования, если у вас в каталоге очень мало файлов.

Анализ объектов в минимальном репозитории

Команда clone получает только:

Затем, в git sparse-checkout set команда извлекает только отсутствующие большие двоичные объекты (файлы) с сервера:

  • d1/a
  • d1/b

Еще лучше то, что позже GitHub, скорее всего, начнет поддерживать:

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

где --filter=tree:0 из Git 2.20 предотвратит ненужные clone выборка всех объектов дерева и позволяет отложить ее до checkout. Но в моем тесте 2020-09-18, который терпит неудачу с:

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

предположительно, потому, что --filter=combine: составной фильтр (добавлен в Git 2.24, подразумевается несколькими --filter) еще не реализован.

Я наблюдал, какие объекты были извлечены с помощью:

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

как упоминалось в: https://stackoverflow.com/questions/7348698/git-how-to-list-all-objects-in-the-database/18793029#18793029 Это не дает мне очень четкого представления о том, что именно представляет собой каждый объект, но в нем указывается тип каждого объекта (commit, tree, blob), и поскольку в этом минимальном репозитории так мало объектов, я могу однозначно определить, что представляет собой каждый объект.

git rev-list --objects --all действительно выдал более четкий вывод с путями для дерева / больших двоичных объектов, но, к сожалению, он извлекает некоторые объекты, когда я его запускаю, что затрудняет определение того, что было извлечено, когда, дайте мне знать, если у кого-нибудь есть лучшая команда.

TODO найти объявление GitHub, в котором говорится, когда они начали его поддерживать. https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/ от 2020-01-17 уже упоминает --filter blob:none.

git sparse-checkout

Я думаю, что эта команда предназначена для управления файлом настроек, в котором говорится: "Меня интересуют только эти поддеревья", так что будущие команды будут влиять только на эти поддеревья. Но в этом немного сложно быть уверенным, потому что текущая документация немного ... скудная ;-)

Само по себе это не препятствует извлечению больших двоичных объектов.

Если это понимание верно, то это было бы хорошим дополнением к git clone --filter описано выше, так как это предотвратило бы непреднамеренную выборку большего количества объектов, если вы собираетесь выполнять операции git в частично клонированном репозитории.

Когда я попробовал 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-clonegit sparse-checkout init

это не сработало, потому что init фактически извлек все объекты.

Однако в Git 2.28 он не извлекал объекты так, как хотелось бы. Но тогда, если я это сделаю:

git sparse-checkout set d1

d1 не извлекается и не извлекается, хотя в этом явно сказано, что это должно: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/#sparse-checkout-and-partial-clones С отказом от ответственности:

Следите за тем, чтобы функция частичного клонирования стала общедоступной[1].

[1]: GitHub все еще оценивает эту функцию внутренне, пока она включена в нескольких избранных репозиториях (включая пример, использованный в этом посте). По мере стабилизации и развития функции мы будем держать вас в курсе ее прогресса.

Так что да, на данный момент слишком сложно быть уверенным, отчасти благодаря тому, что GitHub является закрытым исходным кодом. Но давайте будем следить за этим.

Разбивка команд

Сервер должен быть настроен с:

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

Разбивка команд:

  • --filter=blob:none пропускает все двоичные объекты, но по-прежнему извлекает все древовидные объекты

  • --filter=tree:0 пропускает ненужные деревья: https://www.spinics.net/lists/git/msg342006.html

  • --depth 1 уже подразумевает --single-branch, смотрите также: https://stackoverflow.com/questions/1778088/how-to-clone-a-single-branch-in-git

  • file://$(path) требуется для преодоления git clone протокольные махинации: https://stackoverflow.com/questions/47307578/how-to-shallow-clone-a-local-git-repository-with-a-relative-path

  • --filter=combine:FILTER1+FILTER2 является синтаксисом для одновременного использования нескольких фильтров, пытаясь передать --filter по какой-то причине происходит сбой с: "несколько спецификаций фильтра не могут быть объединены". Это было добавлено в Git 2.24 по адресу e987df5fe62b8b29be4cdcdeb3704681ada2b29e "список объектов-фильтр: реализация составных фильтров";

    Редактировать: в Git 2.28 я экспериментально вижу, что --filter=FILTER1 --filter FILTER2 также имеет тот же эффект, поскольку GitHub не реализует combine: тем не менее, по состоянию на 2020-09-18 и жалуется fatal: invalid filter-spec 'combine:blob:none+tree:0'. TODO введен в какой версии?

Формат --filter задокументировано на man git-rev-list.

Документы по дереву Git:

Протестируйте его на месте

Следующий сценарий воспроизводимо генерирует https://github.com/cirosantilli/test-git-partial-clone репозиторий локально, выполняет локальный клонирование и наблюдает за тем, что было клонировано:

#!/usr/bin/env bashset -eulist-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_repomkdir server_repocd server_repo# Create repo.git init --quietgit config --local uploadpack.allowfilter 1git config --local uploadpack.allowanysha1inwant 1# First commit.# Directories present in all branches.mkdir d1 d2printf 'd1/a' > ./d1/aprintf 'd1/b' > ./d1/bprintf 'd2/a' > ./d2/aprintf 'd2/b' > ./d2/b# Present only in root.mkdir 'root'printf 'root' > ./root/rootgit add .git commit -m 'root' --quiet# Second commit only on master.git rm --quiet -r ./rootmkdir 'master'printf 'master' > ./master/mastergit add .git commit -m 'master commit' --quiet# Second commit only on mybranch.git checkout -b mybranch --quiet master~git rm --quiet -r ./rootmkdir 'mybranch'printf 'mybranch' > ./mybranch/mybranchgit add .git commit -m 'mybranch commit' --quietecho "# List and identify all objects"list-objectsecho# Restore master.git checkout --quiet mastercd ..# Clone. Don't checkout for now, only .git/ dir.git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repocd local_repo# List missing objects from master.echo "# Missing objects after --no-checkout"git rev-list --all --quiet --objects --missing=printechoecho "# Git checkout fails without internet"mv ../server_repo ../server_repo.off! git checkout masterechoecho "# Git checkout fetches the missing directory from internet"mv ../server_repo.off ../server_repogit checkout master -- d1/echoecho "# Missing objects after checking out d1"git rev-list --all --quiet --objects --missing=print

Восходящий поток GitHub.

Вывод в Git v2.19.0:

# List and identify all objectsc6fcdfaf2b1462f809aecdad83a186eeec00f9c1fc5e97944480982cfc180a6d6634699921ee63ec7251a83be9a03161acde7b71a8fda9be19f4712862d67bce3c672fe2b9065f372726a11e57bade7eb64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1308150e8fddde043f3dbbb8573abb6af1df96e63 d1/af70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b84de03c312dc741d0f2a66df7b2f168d823e122a d20975df9b39e23c15f63db194df7f45c76528bccb d2/a41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master8b25206ff90e9432f6f1a8600f87a7bd695a24af master/masteref29f15c9a7c5417944cc09711b6a9ee51b01d8919f7a4ca4a038aff89d803f017f76d2b66063043 mybranch1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranchc3760bb1a0ece87cdbaf9a563c77a45e30a4e30ea0234da53ec608b54813b4271fbf00ba5318b99f root93ca1422a8da0a9effc465eccbcb17e23015542d root/rootmaster commit SHA: fc5e97944480982cfc180a6d6634699921ee63ecmybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root# Missing objects after --no-checkout?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4?8b25206ff90e9432f6f1a8600f87a7bd695a24af?41484c13520fcbb6e7243a26fdb1fc9405c08520?0975df9b39e23c15f63db194df7f45c76528bccb?308150e8fddde043f3dbbb8573abb6af1df96e63# Git checkout fails without internetfatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repositoryfatal: Could not read from remote repository.Please make sure you have the correct access rightsand the repository exists.# Git checkout fetches the missing directory from internetremote: 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

Выводы: все капли из-за пределов d1/ отсутствуют. Например. 0975df9b39e23c15f63db194df7f45c76528bccb, который является d2/b не существует после проверки d1/a.

Обратите внимание, что root/root и mybranch/mybranch также отсутствуют, но --depth 1 скрывает это из списка отсутствующих файлов. Если вы удалите --depth 1, затем они отображаются в списке отсутствующих файлов.

У меня есть мечта

Эта функция может произвести революцию в Git.

Представьте, что у вас есть вся кодовая база вашего предприятия в одном репозитории без уродливые сторонние инструменты, такие как repo.

Воображать хранение огромных двоичных объектов непосредственно в репозитории без каких-либо уродливых сторонних расширений.

Представьте, если бы GitHub позволил для каждого файла / каталога метаданных например, звездочки и разрешения, чтобы вы могли хранить все свои личные вещи в одном репозитории.

Представьте, что если подмодули обрабатывались точно так же, как обычные каталоги: просто запросите дерево SHA, и DNS-подобный механизм разрешает ваш запрос, сначала взглянув на ваш местный ~/.git, затем сначала на более близкие серверы (зеркало / кэш вашего предприятия) и в конечном итоге на GitHub.

Ты не можешь. С помощью git вы клонируете весь репозиторий и полную историю репозитория.

Есть несколько обходных решений, позволяющих получить один файл из архива git, указанного на Ответ Stack Exchange на тот же вопрос, но вам все равно придется загрузить весь репозиторий, чтобы получить тот единственный файл или каталог, который вы хотите.

Если URL-адрес репозитория такой

https://github.com/blah/blah2.git

и оттуда вам нужны изображения папок, которые вы видите по этому URL-адресу

https://github.com/blah/blah2/tree/master/images

Затем сделайте

# Install subversion to use svn!apt-get install subversion# Get what you want by adding "/trunk" to the repo url and the folder you want#!svn checkout REPO_URL/trunk/DIRECTORY!svn checkout https://github.com/blah/blah2.git/trunk/images

Это работает внутри Google Colab

Для репозиториев GitHub вы можете клонировать любые подкаталоги любого репозитория GitHub (по любой ссылке), используя https://github.com/HR/github-clone

Краткий, современный (2020+) ответ

Да, это можно сделать с помощью git 2.19+, которому уже несколько лет.

Разреженный клон:

git clone --no-checkout --depth 1 --sparse --filter=blob:none \    ssh://git@git.domain.tld:7999/$ORG/$REPO.gitcd $REPO# git config ... # as needed

Редкий выезд:

git sparse-checkout init --conegit sparse-checkout add relevant/dir/  # trailing / said importantcat .git/info/sparse-checkout          # to verifygit checkout $BRANCH  # should take only a momentgit status    On branch $BRANCH    Your branch is up to date with 'origin/$BRANCH'.    You are in a sparse checkout with '2%' of tracked files present.    nothing to commit, working tree clean

менять tree/master/ к trunk/

простой :

svn export https://github.com/REPONAME/examples/trunk/lite/examples/

Как для вашего

svn export https://github.com/PointCloudLibrary/pcl/trunk/apps

Чтобы установить svn UBUNTU:https://linuxtechlab.com/simple-guide-to-install-svn-on-ubuntu/

Окна: https://tortoisesvn.net/downloads.html

enter image description here