Как мне клонировать только подкаталог Git-репозитория?
У меня есть мой Git-репозиторий, в корне которого есть два подкаталога:
/finisht
/static
Когда это было в SVN, /finisht
был проверен в одном месте, в то время как /static
был проверен в другом месте, вот так:
svn co svn+ssh://admin@domain.com/home/admin/repos/finisht/static static
Есть ли способ сделать это с помощью Git?
32 ответа
РЕДАКТИРОВАТЬ: Начиная с Git 2.19, это наконец возможно, как можно увидеть в этом ответе: /questions/47669957/kak-mne-klonirovat-tolko-podkatalog-git-repozitoriya/47669972#47669972.
Подумайте об этом ответе.
Примечание: в Git 2.19 реализована только поддержка на стороне клиента, поддержка на стороне сервера по-прежнему отсутствует, поэтому она работает только при клонировании локальных репозиториев. Также обратите внимание, что крупные хосты Git, например GitHub, на самом деле не используют сервер Git, они используют свою собственную реализацию, поэтому даже если поддержка появляется на сервере Git, это не означает, что она автоматически работает на хостах Git. (OTOH, поскольку они не используют Git-сервер, они могли бы реализовать его быстрее в своих собственных реализациях, прежде чем он появится на Git-сервере.)
Нет, это невозможно в Git.
Внедрение чего-то подобного в Git было бы существенным усилием, и это означало бы, что целостность клиентского репозитория больше не может быть гарантирована. Если вам интересно, поищите обсуждения "sparse clone" и "sparse fetch" в списке рассылки git.
В целом, в сообществе Git единодушно то, что если у вас есть несколько каталогов, которые всегда извлекаются независимо, то это действительно два разных проекта, которые должны находиться в двух разных репозиториях. Вы можете склеить их вместе, используя Git Submodules.
То, что вы пытаетесь сделать, называется разреженной проверкой, и эта функция была добавлена в git 1.7.0 (февраль 2012 г.). Шаги для разреженного клона следующие:
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/dir
а также another/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"
Обратите внимание, что при этом все хранилище будет загружено с сервера - только размер извлечения уменьшается. На данный момент невозможно клонировать только один каталог. Но если вам не нужна история хранилища, вы можете по крайней мере сэкономить на пропускной способности, создав мелкий клон. См . Ответ Удондана ниже для получения информации о том, как объединить мелкий клон и редкую проверку.
git clone --filter
из Git 2.19
Эта опция фактически пропускает выборку ненужных объектов с сервера:
git clone --depth 1 --no-checkout --filter=blob:none \
"file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mydir/
Сервер должен быть настроен с:
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
Начиная с версии v2.19.0 сервер не поддерживается, но его уже можно локально протестировать.
СДЕЛАТЬ: --filter=blob:none
пропускает все BLOB-объекты, но по-прежнему выбирает все объекты дерева. Но в обычном репо это должно быть крошечным по сравнению с самими файлами, так что это уже достаточно хорошо. На вопрос: https://www.spinics.net/lists/git/msg342006.html Разработчики ответили --filter=tree:0
находится в работе, чтобы сделать это.
Помни что --depth 1
уже подразумевает --single-branch
Смотрите также: Как мне клонировать одну ветку в Git?
file://$(path)
требуется преодолеть git clone
Протокол Shenanigans: Как отмелить клонирование локального репозитория git с относительным путем?
Формат --filter
задокументировано man git-rev-list
,
Для поддержки этой функции было сделано расширение к протоколу Git remote.
Документы по дереву Git:
- https://github.com/git/git/blob/v2.19.0/Documentation/technical/partial-clone.txt
- https://github.com/git/git/blob/v2.19.0/Documentation/rev-list-options.txt
- https://github.com/git/git/blob/v2.19.0/t/t5616-partial-clone.sh
Проверьте это
#!/usr/bin/env bash
set -eu
list-objects() (
git rev-list --all --objects
echo "master commit SHA: $(git log -1 --format="%H")"
echo "mybranch commit SHA: $(git log -1 --format="%H")"
git ls-tree master
git ls-tree mybranch | grep mybranch
git ls-tree master~ | grep root
)
# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'
rm -rf server_repo local_repo
mkdir server_repo
cd server_repo
# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet
# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet
# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet
echo "# List and identify all objects"
list-objects
echo
# Restore master.
git checkout --quiet master
cd ..
# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo
# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo
echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo
echo "# Git checkout fetches the missing directory from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/
echo
echo "# Missing objects after checking out d1"
git rev-list --all --quiet --objects --missing=print
Выход в Git v2.19.0:
# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root
# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63
# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
# Missing objects after checking out d1
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
Выводы: все капли снаружи d1/
не хватает. Например 0975df9b39e23c15f63db194df7f45c76528bccb
, который d2/b
нет там после проверки d1/a
,
Обратите внимание, что root/root
а также mybranch/mybranch
также отсутствуют, но --depth 1
скрывает это от списка отсутствующих файлов. Если вы удалите --depth 1
Затем они отображаются в списке отсутствующих файлов.
Вы можете объединить функции " Редкий заказ" и " Мелкий клон". Мелкий клон отсекает историю, а редкая проверка извлекает только файлы, соответствующие вашим шаблонам.
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
,
Для других пользователей, которые просто хотят загрузить файл / папку с github, просто используйте:
svn export <repo>/trunk/<folder>
например
svn export https://github.com/lodash/lodash.com/trunk/docs
(да, это svn здесь. по-видимому, в 2016 году вам все еще нужно svn, чтобы просто загрузить некоторые файлы github)
Вежливость: загрузите одну папку или каталог из репозитория GitHub
Важно - убедитесь, что вы обновили URL-адрес github и заменили /tree/master/
с '/trunk/'.
Как скрипт bash:
git-download(){
folder=${@/tree\/master/trunk}
folder=${folder/blob\/master/trunk}
svn export $folder
}
Примечание. Этот метод загружает папку, а не клонирует / извлекает ее. Вы не можете отправить изменения обратно в хранилище. С другой стороны - это приводит к меньшей загрузке по сравнению с редкой проверкой или мелкой проверкой.
2022 Ответ
Я не уверен, почему так много сложных ответов на этот вопрос. Это можно легко сделать, выполнив разреженное клонирование репо в нужную папку.
- Перейдите в папку, в которую вы хотите клонировать подкаталог.
- Открыть
cmd
и выполните следующие команды. -
git sparse-checkout add %subdirectory-to-be-cloned%
-
cd %your-subdirectory%
Вуаля! Теперь вы клонировали только тот подкаталог, который хотите!
Объяснение. Что на самом деле делают эти команды?
git clone --filter=blob:none --sparse %your-git-repo-url%
В приведенной выше команде
-
--filter=blob:none
=> Вы говорите git, что хотите клонировать только файлы метаданных. Таким образом, git собирает основные сведения о ветке и другие метаданные с удаленного сервера, что гарантирует, что ваши будущие проверки из источника будут гладкими. -
--sparse
=> Сообщите 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%
Если вы никогда не планируете взаимодействовать с репозиторием, из которого вы клонировали, вы можете сделать полный клон git и переписать свой репозиторий, используя git filter-branch --subdirectory-filter. Таким образом, по крайней мере, история будет сохранена.
Это выглядит намного проще:
git archive --remote=<repo_url> <branch> <path> | tar xvf -
Git 1.7.0 имеет "редкие проверки". См. "Core.sparseCheckout" на справочной странице git config, "Sparse checkout" на справочной странице git read-tree и "Skip-worktree bit" на справочной странице git update-index.
Интерфейс не так удобен, как в SVN (например, нет способа сделать редкую проверку во время первоначального клона), но теперь доступна базовая функциональность, на которой могут быть построены более простые интерфейсы.
Невозможно клонировать подкаталог только с помощью Git, но ниже приведено несколько обходных путей.
Ветвь фильтра
Вы можете переписать хранилище так, чтобы оно выглядело как trunk/public_html/
был корнем проекта, и откажитесь от всей другой истории (используя filter-branch
), попробуйте на уже оформленную ветку:
git filter-branch --subdirectory-filter trunk/public_html -- --all
Примечания: --
который отделяет параметры ветви фильтра от параметров ревизии, и --all
переписать все ветки и теги. Вся информация, включая исходное время фиксации или информацию о слиянии, будет сохранена. Эта команда отличием .git/info/grafts
файл и ссылки в refs/replace/
пространство имен, так что если у вас есть какие-либо трансплантаты или замена refs
После запуска этой команды они станут постоянными.
Предупреждение! Переписанная история будет иметь разные имена объектов для всех объектов и не будет сходиться с исходной ветвью. Вы не сможете легко перемещать и распространять переписанную ветвь поверх оригинальной ветки. Пожалуйста, не используйте эту команду, если вы не знаете всех последствий, и избегайте ее использования в любом случае, если для решения вашей проблемы будет достаточно простого коммита.
Редкий заказ
Вот простые шаги с подходом разреженного извлечения, который будет редко заполнять рабочий каталог, так что вы можете указать Git, какие папки или файлы в рабочем каталоге стоит проверить.
Репозиторий клонов как обычно (
--no-checkout
необязательно):git clone --no-checkout git@foo/bar.git cd bar
Вы можете пропустить этот шаг, если ваш репозиторий уже клонирован.
Подсказка: для больших репо рассмотрим мелкий клон (
--depth 1
) оформить только последнюю версию или / и--single-branch
только.включить
sparseCheckout
опция:git config core.sparseCheckout true
Укажите папку (и) для разреженной проверки (без пробела в конце):
echo "trunk/public_html/*"> .git/info/sparse-checkout
или редактировать
.git/info/sparse-checkout
,Оформить заказ в филиале (например,
master
):git checkout master
Теперь вы должны были выбрать папки в вашем текущем каталоге.
Вы можете рассмотреть символические ссылки, если у вас слишком много уровней каталогов или фильтрующих веток.
Я только что написал скрипт для GitHub.
Использование:
python get_git_sub_dir.py path/to/sub/dir <RECURSIVE>
Это клонирует конкретную папку и удаляет всю историю, не связанную с ней.
git clone --single-branch -b {branch} git@github.com:{user}/{repo}.git
git filter-branch --subdirectory-filter {path/to/folder} HEAD
git remote remove origin
git remote add origin git@github.com:{user}/{new-repo}.git
git push -u origin master
вот что я делаю
git init
git sparse-checkout init
git sparse-checkout set "YOUR_DIR_PATH"
git remote add <REMOTE_NAME> https://github.com/AUTH/REPO.git
git pull --depth 1 Github <SHA1_or_BRANCH_NAME>
Простая заметка
git sparse-checkout init
многие статьи скажут вам установитьgit sparse-checkout init --cone
Если я добавлю--cone
получу файлы, которые мне не нужны.git sparse-checkout set "..."
установит.git\info\sparse-checkout
содержимое файла как...
Предположим, вы не хотите использовать эту команду. Вместо этого вы можете открыть
git\info\sparse-checkout
а затем отредактируйте.
Пример
Предположим, я хочу получить 2 папки с полным размером репо >10 ГБ ↑ (включая git) , как показано ниже, общий размер <2 МБ
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 Github 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 "Github"]
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 Github 2d4a97f1ed2dd875557849b4281c599a7ffaba03
// or
// git pull --depth 1 Github master
partialclonefilter = blob:none
Я знаю, что нужно добавить эту строку, потому что знаю:
git clone --filter=blob:none
он напишет эту строку. поэтому я имитирую.
версия git:
git version 2.29.2.windows.3
У меня это сработало (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>
Используете 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
Чтобы прояснить некоторые из отличных ответов здесь, шаги, описанные во многих ответах, предполагают, что у вас уже есть удаленный репозиторий.
Дано: существующий репозиторий git, напримерgit@github.com:some-user/full-repo.git
, с одним или несколькими каталогами, которые вы хотите извлечь независимо от остальной части репозитория, например, каталоги с именемapp1
а также app2
Предполагая, что у вас есть репозиторий git, как указано выше...
Затем: вы можете выполнить следующие шаги, чтобы извлечь только определенные каталоги из этого большего репо:
mkdir app1
cd app1
git init
git remote add origin git@github.com:some-user/full-repo.git
git config core.sparsecheckout true
echo "app1/" >> .git/info/sparse-checkout
git pull origin master
Я ошибочно подумал, что параметры разреженной проверки должны быть установлены в исходном репозитории: это не так. Вы определяете, какие каталоги хотите локально, до того, как получить их с пульта. Надеюсь, это разъяснение поможет кому-то другому.
Вот сценарий оболочки, который я написал для сценария использования единственного подкаталога разреженной проверки
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
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>
Пример клонирования только папки Jetsurvey из этого репозитория
git init MyFolder
cd MyFolder
git remote add origin git@github.com:android/compose-samples.git
git config core.sparsecheckout true
echo "Jetsurvey/*" >> .git/info/sparse-checkout
git pull --depth=1 origin main
Ответ @Chronial больше не применим к последним версиям, но это был полезный ответ, поскольку он предложил сценарий.
Учитывая информацию, которую я собрал, и тот факт, что я хотел проверить только подкаталог ветки, я создал следующую функцию оболочки. Он получает поверхностную копию только самой последней версии ветки для указанных каталогов.
function git_sparse_clone_branch() (
rurl="$1" localdir="$2" branch="$3" && shift 3
git clone "$rurl" --branch "$branch" --no-checkout "$localdir" --depth 1 # limit history
cd "$localdir"
# git sparse-checkout init --cone # fetch only root file
# Loops over remaining args
for i; do
git sparse-checkout set "$i"
done
git checkout "$branch"
)
Итак, пример использования:
git_sparse_clone_branch git@github.com:user/repo.git localpath branch-to-clone path1_to_fetch path2_to_fetch
В моем случае клон был «всего» 23 МБ против 385 МБ для полного клона.
Протестировано с git версии 2.36.1.
Здесь много замечательных отзывов, но я хотел добавить, что использование кавычек вокруг имен каталогов не помогло мне в Windows Sever 2016. Файлы просто не загружались.
Вместо
"mydir/myfolder"
Мне пришлось использовать
mydir/myfolder
Кроме того, если вы хотите просто загрузить все подкаталоги, просто используйте
git sparse-checkout set *
Я написал .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
Если вас действительно интересуют только файлы последней версии каталога, Github позволяет вам загрузить репозиторий в виде Zip-файла, который не содержит истории. Так что загрузка происходит намного быстрее.
(расширяя этот ответ )
Клонирование подкаталога в определенном теге
Если вы хотите клонировать определенный подкаталог определенного тега, вы можете выполнить следующие шаги.
Я клонирую подкаталог репозитория 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/
подкаталог репозитория cxfcxf 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/
degit делает копии репозиториев git. Когда вы запускаете degit some-user/some-repo, он находит последнюю фиксацию на https://github.com/some-user/some-repo и загружает связанный tar-файл в ~/.degit/some-user/some-repo/commithash.tar.gz, если он еще не существует локально. (Это намного быстрее, чем использование git clone, потому что вы не загружаете всю историю git.)
degit <https://github.com/user/repo/subdirectory> <output folder>
Узнайте больше https://www.npmjs.com/package/degit
Хотя я ненавижу использовать svn при работе с репозиториями git:/ Я использую это все время;
function git-scp() (
URL="$1" && shift 1
svn export ${URL/blob\/master/trunk}
)
Это позволяет копировать URL-адрес github без изменений. Применение;
--- /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/
Вы все еще можете использовать
svn
:
svn export https://admin@domain.com/home/admin/repos/finisht/static static --force
к "
git clone
"подкаталог, а затем"
git pull
"этот подкаталог.
(Он не предназначен для фиксации и нажатия.)
Выше много хороших идей и скриптов. Я ничего не мог с собой поделать и объединил их в сценарий bash с помощью и проверкой ошибок:
#!/bin/bash
function help {
printf "$1
Clones a specific directory from the master branch of a git repository.
Syntax:
$(basename $0) [--delrepo] repoUrl sourceDirectory [targetDirectory]
If targetDirectory is not specified it will be set to sourceDirectory.
Downloads a sourceDirectory from a Git repository into targetdirectory.
If targetDirectory is not specified, a directory named after `basename sourceDirectory`
will be created under the current directory.
If --delrepo is specified then the .git subdirectory in the clone will be removed after cloning.
Example 1:
Clone the tree/master/django/conf/app_template directory from the master branch of
git@github.com:django/django.git into ./app_template:
\$ $(basename $0) git@github.com:django/django.git django/conf/app_template
\$ ls app_template/django/conf/app_template/
__init__.py-tpl admin.py-tpl apps.py-tpl migrations models.py-tpl tests.py-tpl views.py-tpl
Example 2:
Clone the django/conf/app_template directory from the master branch of
https://github.com/django/django/tree/master/django/conf/app_template into ~/test:
\$ $(basename $0) git@github.com:django/django.git django/conf/app_template ~/test
\$ ls test/django/conf/app_template/
__init__.py-tpl admin.py-tpl apps.py-tpl migrations models.py-tpl tests.py-tpl views.py-tpl
"
exit 1
}
if [ -z "$1" ]; then help "Error: repoUrl was not specified.\n"; fi
if [ -z "$2" ]; then help "Error: sourceDirectory was not specified."; fi
if [ "$1" == --delrepo ]; then
DEL_REPO=true
shift
fi
REPO_URL="$1"
SOURCE_DIRECTORY="$2"
if [ "$3" ]; then
TARGET_DIRECTORY="$3"
else
TARGET_DIRECTORY="$(basename $2)"
fi
echo "Cloning into $TARGET_DIRECTORY"
mkdir -p "$TARGET_DIRECTORY"
cd "$TARGET_DIRECTORY"
git init
git remote add origin -f "$REPO_URL"
git config core.sparseCheckout true
echo "$SOURCE_DIRECTORY" > .git/info/sparse-checkout
git pull --depth=1 origin master
if [ "$DEL_REPO" ]; then rm -rf .git; fi
Если ты хочешь
clone
git clone --no-checkout <REPOSITORY_URL> cd <REPOSITORY_NAME>
- Теперь установите конкретный файл/каталог, который вы хотите перенести в рабочий каталог:
- После этого вы должны жестко сбросить свой рабочий каталог до коммита, который вы хотите получить.
Например, мы сбросим его на значение по умолчанию.
origin/master
коммит HEAD.git reset --hard HEAD
Если ты хочешь
git init
а потомremote add
git init git remote add origin <REPOSITORY_URL>
- Теперь установите конкретный файл/каталог, который вы хотите перенести в рабочий каталог:
git sparse-checkout set <PATH_TO_A_SPECIFIC_DIRECTORY_OR_FILE_TO_PULL>
- Вытащите последний коммит:
git pull origin master
- Теперь установите конкретный файл/каталог, который вы хотите перенести в рабочий каталог:
ПРИМЕЧАНИЕ:
Если вы хотите добавить еще один каталог/файл в свой рабочий каталог, вы можете сделать это следующим образом:
git sparse-checkout add <PATH_TO_ANOTHER_SPECIFIC_DIRECTORY_OR_FILE_TO_PULL>
Если вы хотите добавить весь репозиторий в рабочий каталог, сделайте это так:
git sparse-checkout add *
Если вы хотите очистить рабочий каталог, сделайте это так:
git sparse-checkout set empty
Если вы хотите, вы можете просмотреть статус указанных вами отслеживаемых файлов, выполнив:
git status
Если вы хотите выйти из разреженного режима и клонировать весь репозиторий, вы должны запустить:
git sparse-checkout set *
git sparse-checkout set init
git sparse-checkout set disable
Я не знаю, удалось ли кому-нибудь вытащить конкретный каталог, вот мой опыт: git clone --filter=blob:none --single-branch <repo>, немедленно отменить при загрузке объектов, войти в репо, затем git checkout origin/master <каталог>, игнорировать ошибки (sha1), ввести каталог, повторить проверку (используя новый каталог) для каждого подкаталога. Мне удалось быстро получить исходные файлы таким образом
просто.
git clone <repo>
mv <repo-folder>/path/to/folder <new-name>
rm -rf <repo-folder>