Можно ли сделать редкую проверку без предварительной проверки всего хранилища?

171

Я работаю с репозиторием с очень большим количеством файлов, для извлечения которых требуются часы. Я изучаю возможность того, будет ли Git хорошо работать с этим типом репозитория, поскольку он поддерживает разреженные извлечения, но каждый пример, который я могу найти, делает следующее:

git clone <path>
git config core.sparsecheckout true
echo <dir> > .git/info/sparse-checkout
git read-tree -m -u HEAD

Проблема с этой последовательностью команд заключается в том, что оригинальный клон также выполняет проверку. Если вы добавите -n к исходной команде клонирования, то команда read-tree приведет к следующей ошибке:

ошибка: редкая проверка не оставляет записи в рабочем каталоге

Как можно сделать редкую проверку, не проверив сначала все файлы?

dromodel
источник
Примечание: git worktree add --no-checkoutбудет работать (не только git clone --no-checkout) с git 2.9 (Just 2016). Смотрите мой ответ ниже
VonC
После того, как вы попробовали все решения здесь, единственный, который просто загружает каталог (не нажимая впоследствии!), - это .
LondonRob

Ответы:

24

В 2020 году существует более простой способ справиться с разреженной проверкой, не беспокоясь о файлах .git. Вот как я это сделал:

git clone <URL> --no-checkout <directory>
cd <directory>
git sparse-checkout init --cone # to fetch only root files
git sparse-checkout set apps/my_app libs/my_lib # etc, to list sub-folders to checkout
# they are checked out immediately after this command, no need to run git pull

Обратите внимание, что для этого требуется установленная версия git 2.25. Подробнее об этом читайте здесь: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/

ОБНОВИТЬ:

Приведенная выше git cloneкоманда все еще будет клонировать репо с его полной историей, но без проверки файлов. Если вам не нужна полная история, вы можете добавить в команду параметр --depth , например:

# create a shallow clone,
# with only 1 (since depth equals 1) latest commit in history
git clone <URL> --no-checkout <directory> --depth 1
Алексей Гринько
источник
1
Это правда, хорошая мысль. Upvoted. Я следил за sparse-checkout --coneфункцией в stackoverflow.com/a/59515426/6309
VonC
Стоит добавить частичный clone ( --filter) к вашему ответу здесь.
Тао
@ alexey-grinko, первая команда все еще должна была клонировать весь репо, даже если он не проверил это ... Я искал, чтобы сэкономить время, не клонируя все вещи, которые мне не нужны .. .
mropp
1
@mropp, я обновил ответ, добавив --depthпараметр, который позволяет нам делать мелкий клон. Это поможет? @ Тао, не уверен, как использовать --filterв этом случае, я не пробовал. Не могли бы вы привести пример или опубликовать другой ответ на эту тему?
Алексей Гринько
4
обратите внимание, что в версии 2.27 это не работает, я не знаю почему.
Блейз
162

Обратите внимание, что этот ответ загружает полную копию данных из хранилища. Команда git remote add -fклонирует весь репозиторий. Со страницы руководстваgit-remote :

С -fопцией, git fetch <name>запускается сразу после удаленной информации устанавливается.


Попробуй это:

mkdir myrepo
cd myrepo
git init
git config core.sparseCheckout true
git remote add -f origin git://...
echo "path/within_repo/to/desired_subdir/*" > .git/info/sparse-checkout
git checkout [branchname] # ex: master

Теперь вы обнаружите, что у вас есть «сокращенная» проверка, в которой присутствуют только файлы из пути / inside_repo / to / required_subdir (и по этому пути).

Обратите внимание, что в командной строке Windows вы не должны заключать путь в кавычки, то есть вы должны изменить шестую команду с помощью этой:

echo path/within_repo/to/desired_subdir/* > .git/info/sparse-checkout

если вы этого не сделаете, вы получите кавычки в файле sparse-checkout, и он не будет работать

apenwarr
источник
3
Я не могу использовать команду "git checkout [branchname]" (также обнаружена ошибка: Sparse checkout не оставляет записи в рабочем каталоге). Я использовал "git pull origin master", и он работает правильно.
Натти
2
В git версии 1.7.2.5 для linux я получил следующие результаты: echo 'dir / *' проверяет только файлы в dir /, но не в его подкаталогах; echo 'dir /' (без звездочки!) правильно проверяет все дерево в каталоге dir /. HTH
павек
37
Это просто не сработало для меня - команда "git remote" привела к тому, что весь репо был проверен - bam! - прямо тогда; поэтому «git config ...» и спецификация подкаталога, представляющего интерес для следующих команд, не имели никакого эффекта. Является ли URL-адрес хранилища, указанный в команде «git remote», просто путем к файлу .git верхнего уровня? Или это должен быть путь к интересующему подразделу?
Роб Крэнфилл
10
Вот упрощенная версия (не нужно вручную создавать каталог, выполнять инициализацию и удаленное добавление, просто выполните обычный цикл git clone + checkout с опцией --no-checkout, как упомянуто @onionjake): git clone --no-checkout <project> cd <project> echo <dir>> .git / info / sparse-checkout git checkout <branch>
Грегор,
22
Команда git remote addзагружает все, потому что это то, что -fделает - говорит ей немедленно выбрать, прежде чем вы определили параметры разреженного извлечения. Но пропустить или изменить порядок, который не поможет. Разреженные проверки влияют только на рабочее дерево, а не на хранилище. Если вы хотите, чтобы ваш репозиторий садился на диету, тогда вам нужно посмотреть на опции --depthили --single-branch.
Мирал
43

Git клон имеет опцию ( --no-checkoutили-n ), которая делает то, что вы хотите.

В вашем списке команд просто измените:

git clone <path>

К этому:

git clone --no-checkout <path>

Затем вы можете использовать редкие проверки, как указано в вопросе.

onionjake
источник
7
да, это не делает проверку, но все еще делает выборку, чтобы загрузить всю историю репо
Джейсон С
9
@JasonS вопрос был конкретно о том, чтобы не делать проверку. Если вы не хотите, то всю историю используйте --depth <depth>опцию на git clone. Это загрузит только последние <depth>коммиты из истории. В настоящее время нет возможности частично загрузить один коммит с помощью git, хотя, если ваш пульт поддерживает его, вы можете использовать его git archive --remoteдля загрузки частичных наборов файлов.
луковица
Теперь вы также можете «проверить» коммит, не загружая никаких файлов, используя vfsforgit.org . Это может быть полезно, если кто-то пытается получить только небольшое подмножество одного коммита.
лук репчатый
22

У меня был похожий вариант использования, за исключением того, что я хотел извлечь только коммит для тега и удалить каталоги. Использование --depth 1делает его действительно разреженным и может действительно ускорить процесс.

mkdir myrepo
cd myrepo
git init
git config core.sparseCheckout true
git remote add origin <url>  # Note: no -f option
echo "path/within_repo/to/subdir/" > .git/info/sparse-checkout
git fetch --depth 1 origin tag <tagname>
git checkout <tagname>
sourcedelica
источник
3
--depth 1 называется мелким клоном, просто к вашему сведению.
Марк Эллисон
1
Это помогло! Спасибо
kp123
1
Спасибо за это. Получил это с этим после попытки многих других способов предотвратить загрузку всего репо.
J ... S
12

Я нашел ответ, который искал, в однострочнике, опубликованном ранее pavek (спасибо!), Поэтому я хотел предоставить полный ответ в одном ответе, который работает на Linux (GIT 1.7.1):

1--> mkdir myrepo
2--> cd myrepo
3--> git init
4--> git config core.sparseCheckout true
5--> echo 'path/to/subdir/' > .git/info/sparse-checkout
6--> git remote add -f origin ssh://...
7--> git pull origin master

Я немного изменил порядок команд, но это, похоже, не оказывает никакого влияния. Ключом является наличие косой черты "/" в конце пути на шаге 5.

Дж. Ф. Бержерон
источник
3
ты уверен, что это то, что ты хочешь? -f означает получение всех данных, вы все равно получаете всю другую информацию, которая вам не нужна, и она медленная. (Это все еще «проверка всего хранилища»)
Shuman
1
Я попытался описанные выше шаги в Windows, но запасная проверка не работает в командной строке, поэтому я попробовал оболочку Git Bash, и она сработала !! Командная строка способна выполнить все команды git, такие как push, pull и т. д., но когда дело доходит до разреженного извлечения, происходит сбой.
user593029
Как сделать только файлы из подкаталога. Я хочу только получить файлы внутри определенного подкаталога.
Бабиш Шреста
@BabishShrestha см. Комментарий onionjake на другой ответ FWIW: |
rogerdpack
9

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

В моем случае я хотел пропустить папки с конфигами IntelliJ IDEA.

Вот что я сделал:


Бегать git clone https://github.com/myaccount/myrepo.git --no-checkout

Бегать git config core.sparsecheckout true

Создано .git\info\sparse-checkoutсо следующим содержанием

!.idea/*
!.idea_modules/*
/*

Запустите «git checkout -», чтобы получить все файлы.


Главное, чтобы это работало, было добавить /*имя папки.

У меня есть мерзавец 1.9

эксперт
источник
3
Нет, он все еще загружает все, все коммиты и все файлы, git 2.3.2
Tyguy7
6
Разреженные проверки влияют только на рабочее дерево. Они не влияют на размер хранилища или то, что выбирается. Вам нужны разные варианты, если вы этого хотите.
Мирал
Попробуйте Git Bash Shell в следующий раз, если работаете в Windows, и используйте описанные выше шаги с помощью 'pbetkier', все работает нормально
user593029
6

Да, можно скачать папку вместо загрузки всего хранилища. Даже любой / последний коммит

Хороший способ сделать это

D:\Lab>git svn clone https://github.com/Qamar4P/LolAdapter.git/trunk/lol-adapter -r HEAD
  1. -r HEAD загрузит только последнюю ревизию, игнорируя всю историю.

  2. Обратите внимание на ствол и / specific-folder

Скопируйте и измените URL до и после /trunk/. Надеюсь, это кому-нибудь поможет. Наслаждаться :)

Обновлено 26 сентября 2019 г.

Камар
источник
применимо только для тех, кто приходит или использует SVN. Не буду одобрять этот.
С Джонсон
@CJohnson, как вы можете видеть, я клонирую папку git repo. Работает нормально
Камар,
1
Обратите внимание, что это не то, что предлагает git из коробки, а то, что предлагает концентратор Git рядом с обычным предложением Git. Тем не менее, это прекрасно работает, когда вы можете использовать его. Спасибо!
Qix - МОНИКА БЫЛА ПОВТОРЕНА
1
Из множества предложений по SO ваше самое краткое и ясное решение.
Boardrider
5

Обновленный ответ 2020:

Теперь есть команда git sparse-checkout, которую я подробно представляю с помощью Git 2.25 (первый квартал 2020 года).

nicono «s ответ показывает его использование:

git sparse-checkout init --cone # to fetch only root files
git sparse-checkout add apps/my_app
git sparse-checkout add libs/my_lib

Он развивался с Git 2.27 и знает, как «повторно» использовать редкие проверки, как здесь .
Обратите внимание, что в Git 2.28 git statusбудет упоминаться, что вы находитесь в заархивированном хранилище.

Оригинальный ответ: 2016

git 2.9 (июнь 2016 г.) обобщит --no-checkoutопцию на git worktree add(команда, которая позволяет работать с несколькими рабочими деревьями для одного репо )

Смотрите коммит ef2a0ac (29 марта 2016 г.) от Ray Zhang ( OneRaynyDay) .
Помогают: Эрик Саншайн ( sunshineco) и Хунио С. Хамано ( gitster) .
(Объединено Junio ​​C Hamano - gitster- в коммите 0d8683c , 13 апреля 2016 г.)

Страница git worktreeman теперь включает в себя:

--[no-]checkout:

По умолчанию, addвыселяется <branch>, однако, --no-checkoutможет быть использованы для подавления проверки для того , чтобы сделать настройки, такими как настройка разреженной проверки .

VonC
источник
4

Шаги для разреженной проверки только конкретной папки:

1) git clone --no-checkout  <project clone url>  
2) cd <project folder>
3) git config core.sparsecheckout true   [You must do this]
4) echo "<path you want to sparce>/*" > .git/info/sparse-checkout
    [You must enter /* at the end of the path such that it will take all contents of that folder]
5) git checkout <branch name> [Ex: master]
SANDEEP MACHIRAJU
источник
К вашему сведению, на первом (1) шаге вам не нужно использовать --no-checkout. Просто клонируйте весь репозиторий и затем выполните все шаги 2-5 (упомянутые выше), вы получите результат, который вы хотите. Дайте мне знать, если вы не поняли.
SANDEEP MACHIRAJU
4

На основании этого ответа по apenwarr и этот комментарий по Miral я придумал следующее решение , которое спасло меня почти 94% дискового пространства при клонировании в Linux мерзавец хранилище локально в то время как только хочет один подкаталог Documentation:

$ cd linux
$ du -sh .git .
2.1G    .git
894M    .
$ du -sh 
2.9G    .
$ mkdir ../linux-sparse-test
$ cd ../linux-sparse-test
$ git init
Initialized empty Git repository in /…/linux-sparse-test/.git/
$ git config core.sparseCheckout true
$ git remote add origin ../linux
# Parameter "origin master" saves a tiny bit if there are other branches
$ git fetch --depth=1 origin master
remote: Enumerating objects: 65839, done.
remote: Counting objects: 100% (65839/65839), done.
remote: Compressing objects: 100% (61140/61140), done.
remote: Total 65839 (delta 6202), reused 22590 (delta 3703)
Receiving objects: 100% (65839/65839), 173.09 MiB | 10.05 MiB/s, done.
Resolving deltas: 100% (6202/6202), done.
From ../linux
 * branch              master     -> FETCH_HEAD
 * [new branch]        master     -> origin/master
$ echo "Documentation/hid/*" > .git/info/sparse-checkout
$ git checkout master
Branch 'master' set up to track remote branch 'master' from 'origin'.
Already on 'master'
$ ls -l
total 4
drwxr-xr-x 3 abe abe 4096 May  3 14:12 Documentation/
$  du -sh .git .
181M    .git
100K    .
$  du -sh
182M    .

Таким образом, я сократился с 2,9 ГБ до 182 МБ, что уже довольно приятно.

Я, однако, не стал работать с этим git clone --depth 1 --no-checkout --filter=blob:none file:///…/linux linux-sparse-test( намекнул здесь ), поскольку все отсутствующие файлы были добавлены в индекс как удаленные. Так что, если кто-нибудь знает эквивалент git clone --filter=blob:noneдля git fetch, мы можем сэкономить еще несколько мегабайт. (Чтение справочной страницы git-rev-listтакже намекает, что есть что-то вроде--filter=sparse:path=… , но у меня это тоже не получилось.

(Все пробовали с помощью git 2.20.1 от Debian Buster.)

Аксель Бекерт
источник
1
Интересная обратная связь. Upvoted. Я тоже не знаю --filter=sparse:path=….
VonC
3

Я новичок в git, но кажется, что если я делаю git checkout для каждого каталога, то это работает. Кроме того, файл sparse-checkout должен иметь косую черту после каждого каталога, как указано. Кто-то еще опыт, пожалуйста, подтвердите, что это будет работать.

Интересно, что если вы извлекаете каталог, которого нет в файле sparse-checkout, это, похоже, не имеет значения. Они не отображаются в состоянии git и git read-tree -m -u HEAD не приводит к его удалению. git reset --hard также не вызывает удаление каталога. Кто-нибудь более опытный хочет прокомментировать, что git думает о каталогах, которые извлекаются, но которых нет в файле разреженного извлечения?

dromodel
источник
1

В git 2.27 похоже, что git sparse checkout эволюционировал. Решение в этом ответе не работает точно так же (по сравнению с git 2.25)

git clone <URL> --no-checkout <directory>
cd <directory>
git sparse-checkout init --cone # to fetch only root files
git sparse-checkout set apps/my_app libs/my_lib # etc, to list sub-folders to checkout
# they are checked out immediately after this command, no need to run git pull

Эти команды работали лучше:

git clone --sparse <URL> <directory>
cd <directory>
git sparse-checkout init --cone # to fetch only root files
git sparse-checkout add apps/my_app
git sparse-checkout add libs/my_lib

Смотрите также: git-clone --sparse и git-sparse-checkout add

nicono
источник
1
Хорошее обновление. Upvoted. Я отредактировал свой собственный ответ соответственно. Я представил эту команду в декабре 2019 года: stackoverflow.com/a/59515426/6309
VonC
0

В моем случае я хочу пропустить Podsпапку при клонировании проекта. Я сделал шаг за шагом, как показано ниже, и это работает для меня. Надеюсь, поможет.

mkdir my_folder
cd my_folder
git init
git remote add origin -f <URL>
git config core.sparseCheckout true 
echo '!Pods/*\n/*' > .git/info/sparse-checkout
git pull origin master

Напоминание: если вы хотите пропустить больше папок, просто добавьте больше строк в файл sparse-checkout.

Эрик Лонг
источник