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


у меня есть репозиторий Git, который в корне имеет два подкаталога:

/finisht
/static

когда это было в SVN,/finisht было проверено в одном месте, в то время как /static был проверен в другом месте, вот так:

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

есть ли способ сделать это с помощью Git?

11 1047

11 ответов:

нет, это невозможно в Git.

реализация чего-то подобного в Git будет значительным усилием, и это будет означать, что целостность репозитория на стороне клиента больше не может быть гарантирована. Если вам интересно, найдите обсуждения по "sparse clone" и "sparse fetch" в почтовом списке git.

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

то, что вы пытаетесь сделать, называется неполное извлечение, и эта функция была добавлена в git 1.7.0 (Feb. 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 в вашей файловой системе (с этими путями все еще), и никаких других путей нет.

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

как a функция:

function git_sparse_clone() (
  rurl="" localdir="" && 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 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.

таким образом, вы все еще сможете push, что невозможно с 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/ С '/ствол.'/

как bash-скрипт:

git-download(){
    folder=${@/tree\/master/trunk}
    folder=${folder/blob\/master/trunk}
    svn export $folder
}

Примечание Этот метод загружает папку, не клонирует/не извлекает ее. Вы не можете вернуть изменения обратно в репозиторий. С другой стороны-это приводит к меньшей загрузке по сравнению с редкой проверкой или мелкой проверкой.

Git 1.7.0 имеет "редкие проверки". Видеть "сердечник.sparseCheckout" в git config manpage, "Редкий выезд" в git read-tree manpage, и "Skip-worktree бит" в git update-index manpage.

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

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

этой выглядит гораздо проще:

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

невозможно клонировать подкаталог только с помощью 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. включить :

    git config core.sparseCheckout true
    
  3. указать папка(ы) для разреженной проверки (без пробел в конце):

    echo "trunk/public_html/*"> .git/info/sparse-checkout
    

    или редактировать .git/info/sparse-checkout.

  4. проверка филиала (например master):

    git checkout master
    

теперь вы должны были выбрать папки в текущем каталоге.

вы можете рассмотреть символические ссылки, если у вас слишком много уровней каталогов или ветви фильтрации вместо этого.


Я просто написал скрипт на GitHub.

использование:

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

вот сценарий оболочки, который я написал для случая использования одного подкаталога sparse checkout

coSubDir.sh

localRepo=
remoteRepo=
subDir=


# 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 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 поддержка сервера отсутствует, но ее уже можно протестировать локально.

TODO:--filter=blob:none пропускает все капли, но все равно извлекает все объекты дерева. Но в обычном РЕПО это должно быть крошечным по сравнению с самими файлами, так что это уже достаточно хорошо. Спросил по адресу:https://www.spinics.net/lists/git/msg342006.html разработчики ответили a --filter=tree:0 находится в работе, чтобы сделать это.

помните, что --depth 1 подразумевает --single-branch Смотрите также: как клонировать одну ветку в git?

file://$(path) требуется преодолеть git clone протокол махинаций: как мелко клонировать локальный репозиторий git с относительным путем?

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

Docs on git tree: