Редкая проверка в Git 1.7.0?

Благодаря новой функции разреженной проверки в Git 1.7.0 Можно ли просто получить содержимое подкаталога, как в SVN? Я нашел этот пример, но он сохраняет полный каталог структура. Представьте, что мне просто нужно содержимое каталога perl, а не каталог с именем perl.

- ИЗМЕНИТЬ -

Пример:

Мой репозиторий git содержит следующие пути

repo/.git/
repo/perl/
repo/perl/script1.pl
repo/perl/script2.pl
repo/images/
repo/images/image1.jpg
repo/images/image2.jpg
repo/doc/
repo/doc/readme.txt
repo/doc/help.txt

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

repo/.git/
repo/script1.pl
repo/script2.pl

Однако с текущей функцией разреженной проверки кажется, что можно получить только

repo/.git/
repo/perl/script1.pl
repo/perl/script2.pl

что НЕ то, что я хочу.


person davr    schedule 25.02.2010    source источник
comment
наконец-то они это реализовали! здорово!   -  person Mauricio Scheffer    schedule 25.02.2010
comment
Почему? В чем проблема? И почему вы хотите, чтобы в репозитории была другая структура каталогов и другая локально? На первый взгляд, это не имеет особого смысла.   -  person Jiri Klouda    schedule 09.03.2010
comment
@Jiri: у меня есть веб-приложение с кодом actionscript (на стороне клиента) и PHP (на стороне сервера). Файлы тесно связаны, поэтому я хочу поместить их в один репо / ветку. Однако мне не нужны исходные файлы ActionScript на сервере, а нужны только файлы PHP.   -  person davr    schedule 10.03.2010
comment
@davr это не такое уж редкое обстоятельство, я хотел именно то. Жалко, что я еще не могу этого понять.   -  person preinheimer    schedule 07.10.2011
comment
@preinheimer, я тоже кое-что пытаюсь получить. Это значительно упростило бы разработку и тестирование темы, которую я делаю.   -  person apokaliptis    schedule 05.11.2014


Ответы (7)


Вам все равно нужно клонировать весь репозиторий, в котором будут все файлы. Вы можете использовать флаг --depth, чтобы получить только ограниченный объем истории.

После клонирования репозитория уловка с деревом чтения ограничивает ваше «представление» репозитория только теми файлами или каталогами, которые находятся в .git/info/sparse-checkout файле.

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

#!/bin/sh
echo > .git/info/sparse-checkout
for i in "$@"
do
    echo "$i" >> .git/info/sparse-checkout
done
git read-tree -m -u HEAD

Если вы сохраните этот сценарий как git-sparse.sh в путь, указанный при вызове git --exec-path, то вы можете запустить git sparse foo/ bar/ только для «проверки» каталогов foo и bar или git sparse '*', чтобы вернуть все обратно.

person richq    schedule 26.02.2010
comment
Спасибо за помощь, но это, похоже, не отвечает на мой вопрос. См. Мой обновленный вопрос для уточнения. - person davr; 27.02.2010
comment
Да, разреженный - это просто способ отфильтровать реальное дерево, он не может перемещать файлы. Значит, ты не можешь делать то, что хочешь ... - person richq; 27.02.2010

Краткий ответ: нет. Git видит все файлы как единое целое.

Я рекомендую вам разбить репозитории на логические части. Отдельный для perl, изображений и документов. Если вам также необходимо поддерживать стиль uber-репо, вы можете создать репо, состоящее из подмодулей .

person John K    schedule 16.03.2010

Ответ Richq был близок, но он пропустил шаг. Вам необходимо явно включить разреженную проверку:

git config core.sparsecheckout true

В этом сообщении блога четко описаны все шаги:

http://blog.quilitz.de/2010/03/checkout-sub-directories-in-git-sparse-checkouts/comment-page-1/#comment-3146

person PhilYoussef    schedule 07.01.2012
comment
Сообщение в блоге исчезло, так что мы никогда не узнаем. - person trash80; 19.05.2021

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

Чтобы ответить на вопрос - нет, и по уважительной причине. Вся история репо загружается даже при «редкой проверке». Чтобы прояснить, зачем это нужно - иначе отслеживание переименованных файлов было бы головной болью. Представьте, что вы перемещаете файл /repo_root/asd/file1.cpp в /repo_root/fgh/file1.cpp - теперь, если вы загрузили только /repo_root/fgh дельты, вы не узнаете о file1.cpp. Это означает, что вы должны загрузить все дельты. Но тогда у вас есть полный репозиторий; не просто папка, вырезанная из нее, поэтому просто папка /rero_root/fgh не является репо. Это может показаться неважным, когда вы оформляете заказ, но когда вы фиксируете, git может не знать достаточно, чтобы работать нормально.

Обходной путь: если вы действительно хотите, вы можете создать сценарий, который вызывает git-checkout таким образом (для оболочки sh пакет для окон создать несложно):

!/bin/sh
curDir=`pwd`
cd $2
git-checkout $1
cp -R $3/* $4
cd $curDir

Здесь первый аргумент - это ветка для оформления заказа, второй - папка, в которой сейчас находится репо, третий - подкаталог, который вы действительно хотите использовать, а четвертый - место, в которое вы хотите его скопировать.

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

person Ger4ish    schedule 07.08.2011
comment
Наличие всей истории репо - не проблема, это небольшое репо, и у нас достаточно места на диске. Я думаю, что наш конкретный вариант использования не так распространен, поэтому разработчики git никогда не думали добавлять его. Это одна из немногих вещей, которые SVN сработал для нас лучше (git делает 99 других вещей лучше, поэтому мы перешли, но все же) - person davr; 07.08.2011
comment
символические ссылки в окнах - это кошмар - с этим не справиться. - person Alex Brown; 20.03.2013

git filter-branch --subdirectory-filter - это то, что вам нужно, см. Отключить (переместить) подкаталог в отдельный репозиторий Git .

Вот небольшой сценарий на bash для этого.

Это сначала создаст рабочую копию исходного репо, а затем отфильтрует ветвь с помощью фильтра подкаталогов, чтобы вы получили то, что хотите.

#!/bin/bash
#
# git-subdir.sh
#
git clone --no-hardlinks $1 $2

cd $2

git filter-branch --subdirectory-filter $2 --prune-empty --tag-name-filter cat HEAD -- --all

git reset --hard

git remote rm origin

refbak=$(git for-each-ref --format="%(refname)" refs/original/)

if [ -n "$refbak" ];then
    echo -n $refbak | xargs -n 1 git update-ref -d
fi

git reflog expire --expire=now --all

git repack -ad

git gc --aggressive --prune=now

Используйте для примера в вопросе git-subdir.sh repo perl подойдет.

person weynhamz    schedule 01.03.2012

Вы можете попробовать плетение - он отслеживает пульты, сопоставляя их с дорожкой. https://github.com/evilchelu/braid/wiki

person Antoine Toulme    schedule 30.12.2010

Похоже, что вы пытаетесь переименовать дерево каталогов так, чтобы ваши файлы оказывались в другом месте. Мне кажется, что то, что вы просите сделать, является анти-шаблоном для управления кодом / проектом по двум пунктам: категоризация модулей (биты java под узлом java, perl под узлом perl) и наличие проекта с файлами в разных местах откуда разработчик их визуализирует. Поскольку git поддерживает хэши содержимого каталогов, чтобы увидеть, что изменилось, это также нарушает работу git как такового.

Дэмеон Рейделле

person Daemeon    schedule 05.03.2015