Як клонувати підкаталог лише у сховищі Git?


1409

У мене є сховище Git, яке в корені має два підкаталоги:

/finisht
/static

Коли це було у SVN , /finishtйого перевіряли в одному місці, тоді /staticяк перевіряли в іншому місці:

svn co svn+ssh://admin@domain.com/home/admin/repos/finisht/static static

Чи є спосіб це зробити з Git?



1
Для користувача 2014 року, яка git cloneнайпростіша команда ?? Я використав цю просту відповідь . Якщо є щось більш просте, будь ласка, прокоментуйте
Пітер Краусс

Для тих, хто намагається клонувати вміст сховища (не створюючи кореневу папку), це дуже просте рішення: stackoverflow.com/questions/6224626/…
Marc

@JoachimBreitner: Це питання стосується перевірки підкаталогів у Git (що легко), тоді як це питання про клонування підкаталогів у Git (що неможливо).
Йорг W Міттаг

@ NickSergeant: Що стосується Git 2.19, що вийшов 3 тижні тому, це, нарешті, можливо, як це можна побачити у цій відповіді: stackoverflow.com/a/52269934/2988 Подумайте про прийняття цього зараз. Примітка: у Git 2.19 реалізована лише підтримка на стороні клієнта, підтримка на стороні сервера все ще відсутня, тому вона працює лише під час клонування локальних сховищ. Також зауважте, що великі хостери Git, наприклад, GitHub насправді не використовують сервер Git, вони використовують власну реалізацію, тому навіть якщо підтримка з’являється на сервері Git, це не означає автоматично, що вона працює на хостерах Git. (OTOH, вони могли б реалізувати це швидше.)
Jörg W Mittag

Відповіді:


612

EDIT : Станом на Git 2.19, це, нарешті, можливо, як видно з цієї відповіді .

Подумайте про відкликання цієї відповіді.

Примітка: у Git 2.19 реалізована лише підтримка на стороні клієнта, підтримка на стороні сервера все ще відсутня, тому вона працює лише під час клонування локальних сховищ. Також зауважте, що великі хостери Git, наприклад, GitHub, насправді не використовують сервер Git, вони використовують власну реалізацію, тому навіть якщо підтримка з’являється на сервері Git, це не означає автоматично, що вона працює на хостерах Git. (OTOH, оскільки вони не використовують сервер Git, вони могли його швидше реалізувати у власних реалізаціях, перш ніж він з’явиться на сервері Git.)


Ні, це неможливо в Git.

Впровадження подібного в Git було б значним зусиллям, і це означало б, що цілісність сховища клієнтів вже не може бути гарантована. Якщо ви зацікавлені, шукайте дискусії про "рідкий клон" та "рідкий збір" у списку розсилки git.

Загалом, консенсус спільноти Git полягає в тому, що якщо у вас є кілька каталогів, які завжди перевіряються незалежно, то це справді два різні проекти і вони повинні жити у двох різних сховищах. Ви можете склеїти їх назад, використовуючи підмодулі Git .


6
Залежно від сценарію, можливо, ви хочете використовувати піддерево git замість підмодулю git. Дивіться alumnit.ca/~apenwarr/log/?m=200904#30
C Пірат

9
@StijndeWitt: Рідкі виписки трапляються протягом git-read-tree, що вже пізніше get-fetch. Питання полягало не в тому, щоб перевірити лише підкаталог, а про клонування лише підкаталогу. Я не бачу, як мізерні каси могли це зробити, оскільки git-read-treeпрацює після того, як клон вже завершений.
Йорг W Міттаг

9
Замість цього "заглушки" ви хочете, щоб я видалив цю відповідь, щоб "Хроніал" міг плисти на вершину? Ви не можете видалити його самостійно, оскільки це прийнято, але модератор може. Ви б зберегли репутацію, яку ви заробили від цього, оскільки вона така стара. (Я натрапив на це тому, що хтось позначив це як "лише посилання". :-)
Коді Грей

1
@CodyGray: Хронічна відповідь все ще клонує все сховище, а не лише підкаталог. (Останній абзац навіть прямо говорить про це.) Клонування лише підкаталогу в Git неможливе . Мережевий протокол не підтримує його, формат зберігання не підтримує його. Кожна відповідь на це питання завжди закриває все сховище. Питання є простим питанням "Так / Ні", а відповідь - два символи: Ні. Якщо взагалі, моя відповідь зайво довга , не коротка.
Йорг W Міттаг

1
@ JörgWMittag: Відповідь Циро Сантілі, здається, суперечить вам.
Дан Даскалеску

1524

Те, що ви намагаєтеся зробити, називається розрідженим замовленням , і ця функція була додана в 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"

Зауважте, що це все одно завантажить весь репозиторій із сервера - лише розмір каси зменшений. На даний момент неможливо клонувати лише одну директорію. Але якщо вам не потрібна історія сховища, ви можете принаймні заощадити на пропускній здатності, створивши неглибокий клон. Дивіться відповідь udondan нижче для отримання інформації про те, як поєднати дрібний клон та розріджений замовлення.


Станом на git 2.25.0 (січень 2020 р.) В 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

14
в Apple периметр '-f' не працює. просто зробіть git remote add origin <url> без -f
Anno2001

135
Це вдосконалення, але все-таки потрібно завантажити та зберегти повну копію віддаленого сховища за походженням, чого, можливо, хотілося б взагалі уникати, якщо його цікавлять лише частини кодової бази (або якщо є папки з документацією, як у моєму випадку )
a1an

56
Чи є спосіб клонувати вміст потрібного каталогу (а не сам каталог) прямо в моє сховище? Наприклад, я хочу клонувати вміст https://github.com/Umkus/nginx-boilerplate/tree/master/srcправо в/etc/nginx
мак

25
@Chronial, @ErikE: ви обоє правильно / неправильно: P git remote addКоманда не передбачає отримання, але git remote add -f, як тут використовується, це робить! Ось що -fозначає.
ntc2

21
Використовуючи це, --depth=1я клонував Chromium Devtools в 338 Мб замість 4,9 ГБ повного джерела Blink + історії. Відмінно.
Rudie

443

git clone --filter від Git 2.19

Цей параметр фактично пропустить отримання серверу непотрібних об'єктів. Також, включаючи --filter=tree:0Git 2.20 і --filter=combineскладений фільтр, доданий у Git 2.24, ми закінчуємо:

git clone \
  --depth 1 \
  --filter=combine:blob:none+tree:0 \
  --no-checkout \
  "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

До віддаленого протоколу Git було розширено, щоб підтримати цю функцію v2.19.0і фактично пропустити отримання непотрібних об'єктів, але на даний момент немає підтримки сервера. Але це вже можна перевірити на місцях.

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

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

Документи з дерева Git:

Перевірте це

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

GitHub вище за течією .

Вихід у 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 , вони відображаються у списку відсутніх файлів.

Я маю мрію

Ця особливість може революціонізувати Гіт.

Уявіть, що ви маєте всю кодову базу свого підприємства в одному репо, без потворних сторонніх інструментівrepo .

Уявіть, що зберігаєте величезні краплі прямо у репо, без потворних сторонніх розширень .

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

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


Як не дивно, на macOS з git версії 2.20.1 (Apple Git-117) він скаржиться, що "декілька специфікацій фільтрів не можна поєднувати"
muru

1
На жаль, не пощастило з версією macOS git. fatal: invalid filter-spec 'combine:blob:none+tree:0'Все одно, дякую! Можливо, це буде працювати з новішими версіями.
муру

1
Це не вдається при спробі його в Windows 10 за допомогою GIT 2.24.1 (викидає тонни "не вдається прочитати файл sha1 з .." + "Відключення файлу xxx не вдалося."). Працював як шарм із тією ж версією в Linux.
Ойвінд

1
@Ciro Santilli Це все ще не вдається "не вдається прочитати файл sha1 з ..." у версії git 2.26.1.Windows.1. Я відкрив звіт про помилку: github.com/git-for-windows/git/isissue/2590
nharrer

1
@nharrer дякую за інформацію!
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

405

Ви можете комбінувати рідкісні каси та дрібні функції клонування . У дрібному клон відріже історію і розрідженій перевірка тягне тільки файли , які відповідають вашій моделі.

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.


21
Це корисно і, можливо, є найкращою доступною відповіддю, але він все ще клонує вміст, який вас не хвилює (якщо він знаходиться на гілці, яку ви тягнете), хоча він не відображається в касі.
nobar

1
Яка ваша версія git? Згідно довідки git, чи доступний варіант глибини?
удандан

2
не працює для мене, коли остання команда не є, git pull --depth=1 origin masterале git pull --depth=1 origin <any-other-branch>. це так дивно, дивіться моє запитання тут: stackoverflow.com/questions/35820630/…
Shuman

5
У Windows для другого-останнього рядка потрібно опустити лапки, або витяг не вдасться.
nateirvin

4
Це все ще завантажує всі дані! Знайшов це рішення, використовуючи svn: stackoverflow.com/a/18324458/2302437
electronix384128

157

Для інших користувачів, які просто хочуть завантажити файл / папку з 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
}

Примітка Цей метод завантажує папку, не клонує її та не перевіряє. Ви не можете перенести зміни назад у сховище. З іншого боку - це призводить до меншої завантаження порівняно з розрідженою касою або неглибокою замовою.


9
Єдина версія, яка працювала для мене з github. Команди git перевірили> 10k файли, SVN експортує лише 700, які я хотів. Дякую!
Крістофер Льоркен

4
Спробував це зробити, https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacityале отримав svn: E170000: URL 'https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/trunk/udacity' doesn't existпомилку :(
zthomas.nc

9
@ zthomas.nc Вам потрібно видалити 'стовбур', що передує udacity, а замість нього замінити / tree / master / with / trunk /.
Швидкий

2
Ця команда працювала для мене! Я просто хотів отримати копію файлу від репо, щоб я міг її змінити локально. Добрий старий СВН на допомогу!
Майкл Дж

3
це працює, але здається повільним. потрібно трохи почати, а потім файли відносно повільно згортаються
Aryeh Beitz

73

Якщо ви ніколи не плануєте взаємодіяти з сховищем, з якого ви клонувались, ви можете зробити повний клон git і переписати своє сховище за допомогою git filter-branch --subdirectory-filter . Таким чином збережеться принаймні історія.


11
Для людей, які не знають команди, цеgit filter-branch --subdirectory-filter <subdirectory>
Хайме Хаблутцель

9
Перевага цього методу полягає в тому, що обраний вами підкаталог стає коренем нового сховища, який, як буває, саме те, що я хочу.
Ендрю Шульман

Це, безумовно, найкращий і найпростіший підхід у використанні. Ось одномоментна команда з використанням підкаталогу-фільтрgit clone https://github.com/your/repo_xx.git && cd repo_xx && git filter-branch --subdirectory-filter repo_xx_subdir
Алекс

66

Це виглядає набагато простіше:

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

17
Коли я роблю це на github, я отримую фатальний результат: Операція не підтримується протоколом. Несподіваний кінець командного потоку
Майкл Фокс,

1
Помилка протоколу може бути через HTTPS або: у URL-репо репо. Це може бути також через відсутність ключа ssh.
Умаїр А.

2
Якщо ви використовуєте github, ви можете використовувати svn exportзамість цього
Milo Wielondek,

2
Не працюватиме Github -> Неправильна команда: 'git-upload-archive' xxx / yyy.git '' Ви, здається, використовуєте ssh для клонування git: // URL. Переконайтесь, що параметр настройки core.gitProxy та змінна середовища GIT_PROXY_COMMAND НЕ встановлені. фатально: Віддалений кінець повісив несподівано
Nianliang

3
Причина, чому це не працює з GitHub: "Ми не підтримуємо використання git-архіву для витягування архіву безпосередньо з GitHub. Ви можете або клонувати локально репо, і запустити git-архів, або натиснути кнопку Завантажити ZIP на сторінка репо. " github.com/xuwupeng2000/capistrano-scm-gitcopy/isissue/16
Донн Лі

63

У Git 1.7.0 є "рідкісні каси". Дивіться «core.sparseCheckout» в мерзотник конфігурації станиці керівництво «розрідженій перевірці» в мерзотникові читання дерева довідкової сторінки , і «Skip-worktree біт» в мерзотник оновленні індексу- сторінці керівництві .

Інтерфейс не настільки зручний, як SVN (наприклад, немає можливості зробити розрядний замовлення під час початкового клонування), але тепер доступна базова функціональність, на якій можна було б побудувати більш прості інтерфейси.


37

Клонувати підкаталог не можна лише за допомогою 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
    cd bar
    

    Ви можете пропустити цей крок, якщо ваш сховище вже клоновано.

    Підказка: для великих репостів розгляньте дрібний клон ( --depth 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
    

Тепер вам слід було вибрати вибрані папки у вашому поточному каталозі.

Ви можете розглянути символічні посилання, якщо натомість у вас занадто багато рівнів каталогів або відділення фільтрації.



Чи дозволить вам ще відділення фільтруpull ?
сам

2
@sam: ні. filter-branchпереписав би батьківські коміти, щоб вони мали різні ідентифікатори SHA1, і, отже, ваше відфільтроване дерево не матиме спільного з віддаленим деревом. git pullне знав би, звідки спробувати злитися.
Пітер Кордес

Цей підхід здебільшого відповідає моїй справі.
Абас

10

Я щойно написав сценарій для GitHub .

Використання:

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

11
FYI, це лише для GitHub .
Sz.

9
І, мабуть, це для завантаження каталогу, а не клонування фрагмента репо з усіма його метаданими ... правда?
LarsH

5
Ви повинні вказати свій код тут, а не деінде.
jww

urllib2.HTTPError: помилка HTTP 403: перевищено ліміт швидкості
дієїзм

9

Це дозволить клонувати певну папку та видалити всю історію, не пов’язану з нею.

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-filter-branch мають досить довгий список попереджень.
Ойвінд

6

Ось сценарій оболонки, який я написав для випадку використання єдиного розрідженого замовлення підкаталогів

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

2
Хороший сценарій, лише те, що має бути зафіксовано, є посилання, ln -s ./.$localRepo/$subDir $localRepoа не замістьln -s ./.$localRepo$subDir $localRepo
valentin_nasta

2

Я написав .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

Чому це працює L=${1##*/} L=${L%.git}:? Чи космічний оператор?
Gulzt

2

Використовуєте 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

1

Просто для пояснення деяких чудових відповідей тут, кроки, викладені у багатьох відповідях, передбачають, що ви вже десь маєте віддалений сховище.

Дано: наявне сховище 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

Я помилково подумав, що параметри обмеженої перевірки повинні бути встановлені в оригінальному сховищі: це не так. Перед тим, як витягнути з пульта, ви визначаєте, які каталоги ви бажаєте локально. Сподіваюся, що це уточнення допомагає комусь іншому.


0

Хоча я ненавиджу насправді використовувати svn при роботі з git repos: / я використовую це постійно;

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

Це дозволяє копіювати з urth 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/

0

Якщо ви насправді зацікавлені в останніх редакційних файлах каталогу, Github дозволяє завантажувати сховище у вигляді Zip-файлу, який не містить історії. Тому завантаження відбувається набагато швидше.


0

Тож я спробував усе в цьому протекторі, і для мене нічого не вийшло ... Виявляється, що у версії 2.24 Git (тієї, що поставляється із cpanel на момент отримання цієї відповіді), вам цього не потрібно робити

echo "wpm/*" >> .git/info/sparse-checkout

все, що вам потрібно - це назва папки

wpm/*

Отже, коротше ви це зробите

git config core.sparsecheckout true

потім ви редагуєте .git / info / sparse-checkout і додаєте імена папок (по одному на рядок) разом з / *, щоб отримати підпапки та файли

wpm/*

Збережіть і запустіть команду оформлення замовлення

git checkout master

Результатом стала очікувана папка від мого репо і нічого іншого оновлення, якщо це працювало для вас

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.