Разделение подкаталого с подмодулями в отдельный репозиторий Git
-
25-09-2019 - |
Вопрос
Как подмножество вопроса детеч-подкаталог Уже сделано раньше и учитывая тот факт, что даже много вопросов было сделано о процессе разделения и слияния репозиториев Git, я не мог найти, что касается субъекта расщепления, когда присутствуют подмодулы.
Так что в следующем сценарии:
.git/
.gitmodules
folder/
data/
content/
other_data/
submoduleA/
submoduleB/
Я хотел бы получить два репозитория со следующей структурой:
.git/
data/
а также
.git/
.gitmodules
content/
other_data/
submoduleA/
submoduleB/
Первый случай не является проблемой и может быть легко решена с помощью метода, описанного в детеч-подкаталог.
Второй не так много. Существование подмодулей и тот факт, что .Gitmodules содержит полный путь для folder/content/submoduleA
а также folder/content/submoduleB
Приводит к тому, что часть истории должна быть противоречивой, поскольку. Гитмодул относится к несуществующей структуре каталогов (после использования фильтра-ветви).
Поэтому я хотел бы знать, есть ли способ сделать это, не вызывая непоследовательной истории.
Решение
Я подозреваю (не проверен), что второе git filter-branch
будет возможность изменить .gitmodules
Содержание для каждого превышения нового репо.
Но на самом деле А. git submodule split
Команда была обсуждена в начале 2009 года.
Предлагаемое использование:
git submodule split [--url submodule_repo_url] submodule_dir \
[alternate_dir...]
Заменять
submodule_dir
с недавно созданным подмодулем, сохраняя все историюsubmodule_dir
.
Эта команда также переписывает каждый коммит в истории текущей репозитории, чтобы включить правильную пересмотрsumodule_dir
и подходящий.gitmodules
Записи.
Тем не менее, я не вижу это в Последнее какое приготовление.
Сценарий в предлагаемом патче может дать вам представление о том, что перезаписи дерева, необходимого для обновления .gitmodules
хоть файл.
Другие советы
У меня была точно такая же проблема, как без унций и удалось разрешить ее со следующей процедурой:
git clone git@github.com: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 git@github.com:kdeldycke/cool-cavemen.git
git push -u origin master --force --tags
Как видите, трюк временно переименовать .gitmodules
Файл и использовать sed
переписать его контент. Вы можете получить все детали и контекст этой процедуры в моем блоге.
Чтобы уточнить ответ Кевина: предполагая, что никакие подмодулы когда-либо не существовали снаружи cool/cavemen
- Папка отсоединена (в противном случае потребуется более сложное редактирование .гитмодулей, чтобы удалить эти дополнительные разделы), это может быть достигнуто много быстрее и за один шаг, используя 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