- Вопрос или проблема
- Подтверждение того, что мы действительно не скачали ненужные файлы
- TODO Также предотвратить загрузку ненужных объектов дерева
- О командах
- Мечта: У любой директории может быть метаданные веб-интерфейса
- Ответ или решение
- 1. Sparse Checkout
- 2. Менее Инвазивные Методы Клонирования
- 3. Использование Инструментов SVN
- Заключение
Вопрос или проблема
Я нашел коллекцию slackbuilds, некоторые из которых мне нужны, они находятся на GitHub.
https://github.com/PhantomX/slackbuilds/
Я не хочу загружать весь git.
git clone https://github.com/PhantomX/slackbuilds.git
Но мне нужен только slackbuild для этого.
Как это сделать? Это возможно?
Вы в конечном итоге скачаете всю историю, поэтому я не вижу в этом много пользы, но вы можете проверить конкретные части, используя “разреженный” клон. Цитируя этот пост на Stack Overflow:
Шаги для создания разреженного клона следующие:
mkdir <repo> cd <repo> git init git remote add -f origin <url>
Я собираюсь прервать здесь. Поскольку я цитирую другой пост, я не хочу редактировать цитируемые части, но не используйте -f
с git remote add
. Это сделает fetch, который заберет всю историю. Просто добавьте удаленный репозиторий без fetch:
git remote add origin <url>
Затем выполните поверхностный fetch, как описано позже.
Это создаст пустой репозиторий с вашим удаленным, и загрузит все объекты, но не проверит их. Затем выполните:
git config core.sparseCheckout true
Теперь вам нужно определить, какие файлы/папки вы хотите фактически проверить. Это делается путем перечисления их в
.git/info/sparse-checkout
, например:echo "some/dir/" >> .git/info/sparse-checkout echo "another/sub/tree" >> .git/info/sparse-checkout
[…]
Вам может быть интересно взглянуть на расширенное руководство, и вам, вероятно, следует прочитать официальную документацию по разреженному
checkout.
Вам может быть лучше воспользоваться поверхностным клоном. Вместо обычного git pull
, попробуйте:
git pull --depth=1 origin master
У меня была возможность протестировать это снова недавно, пытаясь получить только шрифты Ubuntu Mono Powerline. Шаги выше в итоге загрузили около 11 МБ, в то время как сами шрифты Ubuntu занимают ~900 КБ:
% git pull --depth=1 origin master
remote: Enumerating objects: 310, done.
remote: Counting objects: 100% (310/310), done.
remote: Compressing objects: 100% (236/236), done.
remote: Total 310 (delta 75), reused 260 (delta 71), pack-reused 0
Receiving objects: 100% (310/310), 10.40 MiB | 3.25 MiB/s, done.
Resolving deltas: 100% (75/75), done.
From https://github.com/powerline/fonts
* branch master -> FETCH_HEAD
* [new branch] master -> origin/master
% du -hxd1 .
11M ./.git
824K ./UbuntuMono
12M .
Обычный clone
занял около 20 МБ. Есть небольшая экономия, но недостаточно.
Использование метода --filter
+ checkout из ответа Сиро Сантили действительно сокращает размер, но, как упоминалось там, загружает каждый blob по одному, что медленно:
% git fetch --depth=1 --filter=blob:none
remote: Enumerating objects: 52, done.
remote: Counting objects: 100% (52/52), done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 52 (delta 1), reused 35 (delta 1), pack-reused 0
Receiving objects: 100% (52/52), 14.55 KiB | 1.32 MiB/s, done.
Resolving deltas: 100% (1/1), done.
From https://github.com/powerline/fonts
* [new branch] master -> origin/master
* [new branch] terminus -> origin/terminus
% git checkout origin/master -- UbuntuMono
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (1/1), 1.98 KiB | 1.98 MiB/s, done.
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), 581 bytes | 581.00 KiB/s, done.
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), 121.43 KiB | 609.00 KiB/s, done.
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), 100.66 KiB | 512.00 KiB/s, done.
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), 107.62 KiB | 583.00 KiB/s, done.
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), 112.15 KiB | 791.00 KiB/s, done.
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), 454 bytes | 454.00 KiB/s, done.
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), 468 bytes | 468.00 KiB/s, done.
% du -hxd1 .
692K ./.git
824K ./UbuntuMono
1.5M .
Итог: Используйте --filter
, разреженный checkout и поверхностный клон, чтобы сократить общий объем загрузки, или просто используйте разреженный checkout + поверхностный клон, если вам не важен общий объем загрузки, и вы просто хотите эту одну директорию, каким бы образом это ни было получено.
git clone --filter
+ git sparse-checkout
загружает только необходимые файлы
Например, чтобы склонировать только файлы в подпапке small/
в этом тестовом репозитории: 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
Слэш в /small
обязателен, если вы сделаете просто small
, то git также загрузит любую другую директорию с именем small
, у нас есть директория subdir/small/ в репозитории для тестирования этого.[1]
Примечание: Этот метод не работает для отдельных файлов, однако вот другой метод, который работает: https://stackoverflow.com/questions/2466735/how-to-sparsely-checkout-only-one-single-file-from-a-git-repository/52270527#52270527
Подтверждение того, что мы действительно не скачали ненужные файлы
В приведенном выше тестовом репозитории содержится:
- подкаталог
big/
с файлами по 10 МБ каждый - 10x файлы по 10 МБ
0
,1
, …9
на верхнем уровне (это связано с тем, что в предыдущих попытках загружались верхнеуровневые файлы) - подкаталоги
small/
иsmall2/
с 1000 файлов размером по одному байту каждый
Все содержимое является псевдослучайным и, следовательно, не поддается сжатию, так что мы легко замечаем, если какие-либо из больших файлов были загружены, например, с помощью ncdu
.
Таким образом, если вы скачаете что-либо, чего не хотели, вы получите 100 МБ дополнительного пространства, и это будет очень заметно.
Все команды git выполнялись практически мгновенно, и мы можем подтвердить, что клонированный репозиторий очень мал, как и ожидалось:
du --apparent-size -hs * .* | sort -hs
что дает:
2.0K small
226K .git
Запуск 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.
А затем финальный checkout загружает файлы, которые мы запросили:
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
Ваш бранч обновлен в соответствии с 'origin/master'.
Проверено на git 2.37.2, Ubuntu 22.10, в январе 2023 года.
TODO Также предотвратить загрузку ненужных объектов дерева
Приведенный выше метод загружает все объекты дерева Git (т.е. списки директорий, но не фактические содержимое файлов). Мы можем это подтвердить, выполнив:
git ls-files
и увидеть, что он содержит директории крупных файлов, таких как:
big/0
В большинстве проектов это не будет проблемой, так как они должны быть маленькими по сравнению с фактическим содержимым файлов, но перфекционист во мне хотел бы избежать их.
Я также создал очень экстремальный репозиторий с несколькими очень большими объектами дерева (100 МБ) в директории big_tree
: https://github.com/cirosantilli/test-git-partial-clone-big-small
Сообщите мне, если кто-то найдет способ клонировать только директорию small/
из него!
О командах
Опция --filter
была добавлена вместе с обновлением протокола удаленного доступа, и она действительно предотвращает загрузку объектов с сервера.
Часть sparse-checkout
также требуется, к сожалению. Вы также можете загружать определенные файлы с помощью гораздо более понятного:
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
но это загружает все файлы в верхнем уровне директории: https://stackoverflow.com/questions/75311408/how-to-prevent-git-clone-filter-blobnone-sparse-from-downloading-files-on-t
Мечта: У любой директории может быть метаданные веб-интерфейса
Эта функция может произвести революцию в Git.
Представьте, что у вас есть вся кодовая база вашего предприятия в едином монорепозитории без громоздких сторонних инструментов вроде repo
.
Представьте хранение огромных blob’ов непосредственно в репозитории без каких-либо громоздких сторонних расширений.
Представьте, если бы GitHub разрешал метаданные по файлам/директориям, такие как звезды и разрешения, так что вы можете хранить все свои личные вещи в одном репозитории.
Представьте, если бы подмодули рассматривались как обычные директории: просто запросите SHA дерева, и механизм, похожий на DNS, разрешает ваш запрос, сначала проверяя ваш локальный ~/.git
, затем сначала к ближайшим серверам (зеркало/кеш вашего предприятия) и заканчивая на GitHub.
У меня есть мечта.
Философия тестового конусного монорепозитория
Это возможная философия для обслуживания монорепозитория без подмодулей.
Мы хотим избежать подмодулей, потому что это неудобно каждый раз делать коммит в два отдельных репозитория, когда вы вносите изменения, которые касаются как подмодуля, так и компонента без подмодуля.
Каждая директория с Makefile или аналогичным должна собирать и тестировать себя.
Такие директории могут зависеть от:
- каждого файла и подпапки под ней непосредственно на их последних версиях
- внешние директории могут использоваться только на указанных версиях
Пока git не начнет поддерживать это нативно (т.е. подмодули, которые могут отслеживать только подпапки), мы можем поддерживать это с помощью некоторой метаданных в файле, отслеживаемом git:
monorepo.json
{
"path": "some/useful/lib",
"sha": 12341234123412341234,
}
где sha
относится к обычному SHA всего репозитория. Затем нам нужны скрипты, которые будут проверять такие директории, например, под игнорируемой git monorepo
папкой:
monorepo/som/useful/lib
Каждый раз, когда вы меняете файл, вам нужно подниматься по дереву и тестировать все директории, у которых есть Makefile. Это потому, что директории могут зависеть от подпапок на их последних версиях, поэтому вы всегда можете что-то сломать выше.
Связано:
Попробуйте это:
svn export https://github.com/PhantomX/slackbuilds/trunk/${directory}
рабочее решение :
вам нужно отключить сжатие:
git config --global core.compression 0
тогда вам нужно использовать поверхностный клон
git clone --depth=1 <url>
тогда самый важный шаг — это перейти в ваш клонированный проект
cd <шагово клонированный проект dir>
теперь разверните клон, шаг за шагом
git fetch --depth=N, с увеличением N
например.
git fetch --depth=4
затем,
git fetch --depth=100
затем,
git fetch --depth=500
вы можете выбрать, сколько шагов вы хотите, заменив это N,
и наконец загрузите все оставшиеся ревизии, используя,
git fetch --unshallow
поставьте лайк, если это вам помогает 🙂
В конце концов, я смог это сделать благодаря вышеописанному. Я редактировал файл напрямую, получая ошибки, случайно включая кавычки. Ваш файл .git/info/sparse-checkout должен содержать только директорию, без кавычек. Вот пример:
Этот гигантский проект: https://github.com/SharePoint/sp-dev-fx-webparts, я хотел только react-script-editor в директории samples.
https://github.com/SharePoint/sp-dev-fx-webparts/tree/master/samples/react-script-editor
Я следовал инструкциям выше и все заработало, когда в моем файле .git/info/sparse-checkout было только это
samples/react-script-editor
Это клонирует конкретную папку и удаляет всю историю, не относящуюся к ней.
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
Для репозиториев GitHub вы можете клонировать любые подкаталоги любого репозитория GitHub (по любой ссылке), используя https://github.com/HR/github-clone
Я отвечу, указав конкретные ограничения, с которыми я столкнулся.
- В VSO SSH был отключен по соображениям безопасности, поэтому не удалось использовать git archive. Поддерживались только PAT/ CredentialProvider.
- В нашей ветке был огромный код, поэтому git clone занимал минимум 15 минут.
Вот что я сделал:
- Однократный ручной процесс: в UI VSO создайте новую удаленную ветку, скажем, ’emptyBranch’, в которой нет файлов (все удалены).
git clone --depth=1 --single-branch --branch emptyBranch <remote>
(довольно быстро)git checkout <branchToSyncTo> <directoryToSyncTo>
(проверяет только конкретную папку)
Ответ или решение
Клонирование части проекта на Git действительно возможно, и существует несколько способов добиться этого. Каждый из подходов имеет свои особенности и подходит для различных сценариев в зависимости от ваших требований к загрузке и объему данных. Позвольте мне подробно объяснить основные методы, которые можно использовать для клонирования конкретной директории или файла из репозитория GitHub.
1. Sparse Checkout
Sparse Checkout – это метод, позволяющий загружать только определенные файлы или директории из репозитория, однако требуется предварительная настройка. Вот основные шаги, которые вам нужно выполнить:
-
Создайте пустой каталог и инициализируйте репозиторий:
mkdir slackbuilds cd slackbuilds git init git remote add origin https://github.com/PhantomX/slackbuilds.git
-
Включите режим Sparse Checkout:
git config core.sparseCheckout true
-
Добавьте нужные директории в
.git/info/sparse-checkout
:
В этом файле укажите путь к директории, которую вы хотите клонировать. Например, для директорииdcmtk
:echo "dcmtk/*" >> .git/info/sparse-checkout
-
Загрузите данные и проверьте их:
git pull origin master
Таким образом, вы получите только необходимые файлы и директории, но имейте в виду, что этот метод часто загружает информацию о всей истории репозитория.
2. Менее Инвазивные Методы Клонирования
Существует несколько альтернативных подходов, которые могут оказаться менее ресурсозатратными:
-
Технология "Shallow Clone" (мелкое клонирование):
Вы можете использовать--depth
для ограничения количества коммитов, которые загружаются из репозитория.git clone --depth=1 https://github.com/PhantomX/slackbuilds.git
-
Команда для загрузки конкретной директории:
Другой метод заключается в использованииgit sparse-checkout set
, который позволяет вам загрузить только необходимые директории.git clone --filter=tree:0 --no-checkout https://github.com/PhantomX/slackbuilds.git cd slackbuilds git sparse-checkout set dcmtk git checkout master
3. Использование Инструментов SVN
Если вам нужно получить только определённые файлы или директории без необходимости взаимодействия с Git, можно использовать svn
, что позволяет экспортировать содержимое репозитория:
svn export https://github.com/PhantomX/slackbuilds/trunk/dcmtk
Этот метод также актуален, если в репозитории активированы ограничения по Git.
Заключение
Существует множество методов клонирования отдельных частей репозитория Git, и выбор подходящего зависит от ваших намерений и спецификаций проекта. Sparse Checkout и Shallow Clone позволяют вам контролировать объем загружаемой информации, в то время как использование SVN может стать удобным решением для извлечения конкретных файлов или директорий, особенно если вам не требуется сохранять историю изменений.
При выборе метода обязательно учитывайте как текущую структуру вашего проекта, так и ваши последующие планы по ее сопровождению и обновлению.