git разделение репозитория по подпапкам и сохранение всех старых ветвей
у меня есть git repo с 2 каталогами и несколькими ветвями, я хочу разделить их и создать все ветви
`-- Big-repo
|-- dir1
`-- dir2
Branches : branch1, branch2, branch3 ...
что я хочу!--8-->
Я хочу разделить dir1 и dir2 как два отдельных репозитория и сохранить ветви branch1, branch2 ... в обоих репозиториях.
dir1
Branches : branch1, branch2, branch3 ...
dir2
Branches : branch1, branch2, branch3 ...
что я пробовал:
Я могу разделить их на 2 РЕПО, используя
git subtree split -P dir1 -b dir1-only
git subtree split -P dir2 -b dir2-only
но, он не создает никаких ветвей после разделение.
всех подразделений:
git checkout branch1 (in Big-repo)
git subtree split -p dir1 -b dir1-branch1
git checkout branch2 (in Big-repo)
git subtree split -p dir1 -b dir1-branch2
And push these branches to newly created repo.
это требует больше ручного усилия, и я уверен, что может быть быстрый способ достичь этого?
какие идеи???
2 ответов
короткий ответ:
git filter-branch
предоставляет именно ту функциональность, которую вы хотите. С вы можете создать новый набор коммитов, где содержание subDirectory
находятся в корне каталога.
git filter-branch --prune-empty --subdirectory-filter subDirectory -- --branches
прохождение
ниже приведен пример, чтобы выполнить это безопасным способом. Вы должны выполнить это для каждого подкаталога, который будет изолирован в свое собственное РЕПО, в этом случае dir1
.
первый клонируйте свой репозиторий, чтобы изолировать изменения:
git clone yourRemote dir1Clone
cd dir1Clone
чтобы подготовить клонированный репозиторий, мы воссоздадим все удаленные ветви как локальные. Мы пропускаем тот, который начинается с *
так как это текущая ветвь, которая в этом случае будет читать (no branch)
так как мы находимся в безголовом состоянии:
# move to a headless state
# in order to delete all branches without issues
git checkout --detach
# delete all branches
git branch | grep --invert-match "*" | xargs git branch -D
чтобы воссоздать все удаленные ветви локально, мы проходим через результаты git branch --remotes
. Мы пропускаем те, которые содержат ->
так как это не ветви:
# get all local branches for remote
git branch --remotes --no-color | grep --invert-match "\->" | while read remote; do
git checkout --track "$remote"
done
# remove remote and remote branches
git remote remove origin
наконец-то запустить . Это создаст новые коммиты со всеми коммитами, которые касаются dir1
поддиректории. Все ветви, которые также касаются этого подкаталога, будут обновлены. На выходе будут перечислены все ссылки, которые где не обновлены, что имеет место для ветвей, которые не касаются dir1
на всех.
# Isolate dir1 and recreate branches
# --prune-empty removes all commits that do not modify dir1
# -- --all updates all existing references, which is all existing branches
git filter-branch --prune-empty --subdirectory-filter dir1 -- --all
после этого у вас будет новый набор коммитов, которые dir1
в корне репозитория. Просто добавьте свой удаленный для нажатия новых коммитов или использования их в качестве нового репозитория.
в качестве дополнительного последнего шага, если вы заботитесь о размере репозитория:
даже если все ветви, в которых обновлен ваш репозиторий, по-прежнему будут иметь все объекты исходного репозитория, то они доступны только через ref-журналы. Если вы хотите бросить эти читать как мусор собирать совершает
дополнительные ресурсы:
этот скрипт делает всю работу за меня:
#!/bin/bash
set -e
if [ -z "" ]; then
echo "usage: /full/path/to/repository path/to/splitfolder/from/repository/root new_origin"
exit
fi
repoDir=
folder=
newOrigin=
cd $repoDir
git checkout --detach
git branch | grep --invert-match "*" | xargs git branch -D
for remote in `git branch --remotes | grep --invert-match "\->"`
do
git checkout --track $remote
git add -vA *
git commit -vam "Changes from $remote" || true
done
git remote remove origin
git filter-branch --prune-empty --subdirectory-filter $folder -- --all
#prune old objects
rm -rf .git/refs/original/*
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune
#upload to new remote
git remote add origin $newOrigin
git push origin master
for branch in `git branch | grep -v '\*'`
do
git push origin $branch
done