2010-08-05 2 views
5

Как подмножество вопроса detach-subdirectory, уже сделанное до и учитывая тот факт, что, несмотря на то, что было много вопросов о процессе разделения и слияния репозиториев git, я не мог найти тот, который касается предмета расщепления при наличии подмодулей.Разбиение подкаталога с подмодулями в отдельный репозиторий git

Таким образом, в следующем сценарии:

.git/ 
.gitmodules 
folder/ 
    data/ 
    content/ 
     other_data/ 
     submoduleA/ 
     submoduleB/ 

Я хотел бы получить два хранилища со следующей структурой:

.git/ 
data/ 

и

.git/ 
.gitmodules 
content/ 
    other_data/ 
    submoduleA/ 
    submoduleB/ 

Первый случай не является и может быть легко решена с помощью метода, описанного в detach-subdirectory.

Второе не так много. Существование подмодулей и тот факт, что .gitmodules содержит полный путь для folder/content/submoduleA и folder/content/submoduleB, заставляет часть истории быть несовместимой, поскольку .gitmodules ссылается на несуществующую структуру каталогов (после использования ветви фильтра).

Так что я хотел бы знать, есть ли способ сделать это, не вызывая непоследовательной истории.

ответ

1

Я подозреваю (не проверял), что у второго git filter-branch будет возможность изменить содержимое .gitmodules для каждой фиксации нового репо.

На самом деле git submodule split command was in discussion early 2009.

Предлагаемое использование:

git submodule split [--url submodule_repo_url] submodule_dir \ 
    [alternate_dir...] 

Заменить submodule_dir с вновь созданной подмодуль, сохраняя всю историю submodule_dir.
Эта команда также перезаписывает каждую фиксацию в истории текущего репозитория, чтобы включить правильную ревизию sumodule_dir и соответствующие записи .gitmodules.

Однако я не вижу его в latest what's cooking.
Скрипт в предлагаемом патче может дать вам представление о том, какой тип перезаписи дерева необходим для обновления файла .gitmodules.

+0

Используя вторую команду мерзавец фильтр-филиальную я смог переписать .gitmodules с SED команды, однако фактическое подмодульные папки по-прежнему остаются нетронутыми (как с индексным фильтром, так и с древовидным фильтром). Только подкаталог-фильтр смог их изменить, но затем удаляется .gitmodules. Команда разделения подмодуля git, похоже, делает именно то, что я намереваюсь, но, читая поток, у меня сложилось впечатление, что у него есть несколько проблем, поэтому я не чувствую себя комфортно, используя его. – Unode

+0

@Unode: Я понимаю. Я не думаю, что этот конкретный патч находится в активном развитии прямо сейчас. – VonC

5

У меня была точно такая же проблема, как Unode и удалось решить с помощью следующей процедуры:

git clone [email protected]:kdeldycke/kev-code.git 
cd kev-code 
git filter-branch --tree-filter "test -f ./.gitmodules && mv ./.gitmodules ./cool-cavemen/gitmodules || echo 'No .gitmodules file found'" -- --all 
git filter-branch --force --prune-empty --subdirectory-filter cool-cavemen --tag-name-filter cat -- --all init..HEAD 
git filter-branch --force --tree-filter "test -f ./gitmodules && mv ./gitmodules ./.gitmodules || echo 'No gitmodules file found'" -- --all 
git filter-branch --force --tree-filter "test -f ./.gitmodules && sed -i 's/cool-cavemen\///g' ./.gitmodules || echo 'No .gitmodules file found'" -- --all 
git remote rm origin 
rm -rf .git/refs/original/ 
git reflog expire --all 
git gc --aggressive --prune 
git remote add origin [email protected]:kdeldycke/cool-cavemen.git 
git push -u origin master --force --tags 

Как вы видите, фокус в том, чтобы временно переименовать файл .gitmodules и использовать sed переписать его содержимое. Вы можете получить все подробности и context of this procedure on my blog.

+0

Вы можете включить опцию '--tag-name-filter cat' во всех командах фильтрации-ветвей для сохранения тегов после фильтрации. – kolyuchiy

+0

Спасибо, что зарегистрировали это. Две вещи, которые я должен был настроить, чтобы заставить это работать. Во-первых, я думаю, вы предполагаете, что начальная команда помечена как 'init' для диапазона' init..HEAD'. Во-вторых, мне пришлось добавить '-e' в команду sed, т. Е .:' sed -i -e 's/cool-cavemen \ /// g' ./. Gitmodules' – Von

0

Чтобы подробно остановиться на ответе Кевина: предполагается, что подмодулы никогда не существовали вне cool/cavemen - папка, отделяемая (в противном случае более сложное редактирование.gitmodules будет необходимо, чтобы удалить эти дополнительные секции), это может быть достигнуто много быстрее и в одном шаге с помощью index-filter:

$ git filter-branch --subdirectory-filter cool/cavemen --index-filter $' 
hash=$(git rev-parse --verify $GIT_COMMIT:.gitmodules 2>/dev/null) && 
git update-index --add --cacheinfo 100644 $(git cat-file -p $hash | 
sed \'s/cool\\/cavemen\\///g\' | git hash-object -w --stdin) .gitmodules || 
true' --tag-name-filter cat --prune-empty -- --all 

В качестве дополнительного преимущества, если cool/cavemen не существует в каждой ревизии или ответвлении только те пересмотры или филиалы, которые содержали cool/cavemen, будут рассмотрены.

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

$ git for-each-ref --format='%(refname)' | 
grep -vF "$(git for-each-ref --format='%(refname)' refs/original | 
sed 's/refs\/original\///g')" | xargs -n 1 git update-ref -d