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

StackOverflow https://stackoverflow.com/questions/3411364

  •  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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top