Недавно я столкнулся с задачей переноса папки с проектом из одного репозитория в другой на github. Звучит примитивно, но если рассмотреть то, что дано и то, что необходимо получить, могут возникнуть некоторые нюансы.
Итак, что дано:
Что необходимо сделать:
В теории можно было бы просто скопировать весь репозиторий со всем содержимым в новое место, а потом просто удалить те папки, которые не нужны. Но такой способ довольно неоптимален и не особо мне понравился, так что я решил поступить иначе.
Я использовал стандартный гитовый filter-branch. За основу я взял следующие статьи:
В этом посте я хочу немного адаптировать процесс для лучшего восприятия.
Предположим для примера, что наш репозиторий называется movement-example
, а та единственная папка, которую мы хотим перенести в отдельный репозиторий – folder-to-move
. Тогда шаги, которые необходимо выполнить для подготовки переноса, выглядят следующим образом:
git clone git@github.com:<user_or_organization>/movement-example.git
git clone <path-to-movement-example>
– это гораздо быстрее (спасибо ZyXI за подсказку). cd movement-example
git remote rm origin
git filter-branch --subdirectory-filter folder-to-move -- --all
folder-to-move
, причем самой папки больше нет – все содержащиеся в ней файлы теперь лежат в текущей директории (в movement_example
).mkdir folder-to-move
mv * folder-to-move
git add .
git commit -m “Preparing to extract folder”
Первая часть готова, а вторая заключается в том, чтобы совершить фактический перенос. Предположим, что новый репозиторий называется просто new-repo
, тогда необходимые шаги выглядят следующим образом:
git clone git@github.com:<user_or_organization>/new-repo.git
cd new-repo
git remote add old-repo-branch <path-to-movement-example-folder>
path-to-movement-example-folder
выглядел бы как ../movement-example
git pull old-repo-branch master
folder-to-move
в локальном репозитории new-repo
, останется только сделать push. Но сначала нужно сделать кое-что еще.git remote rm old-repo-branch
git push origin master
Готово! Теперь в вашем новом репозитории есть только интересующая вас папка вместе со всей историей коммитов. Например, сразу после вышеописанных шагов я увидел следующее в своем новом репозитории:
810 коммитов!
Кстати, вы увидите только 1 бранч – master
. Процедура переносит только один бранч за раз. Если вы хотите перенести dev
, то вам нужно просто сделать git checkout dev
и git pull origin dev
после второго шага на обоих этапах.
Если вам нужно перенести все 50 (60? 100?) бранчей, то данное решение не будет удачным из-за слишком большого количества рутинной работы. Но я считаю, что для переноса достаточно лишь сохранить master и dev бранчи, потому что все feature branches уже должны быть в dev, а новые бранчи вы будете ветвить уже в новом репозитории.
Спасибо fstep за подсказку. Можно просто воспользоваться другой гитовой утилитой – subtree
. Для этого нужно всего ничего:
git clone <path-to-movement-example>
git remote rm origin
git subtree split --prefix folder-to-move master
master
. Эта команда будет долго вычислять значения, но в итоге вернет вам что-то вроде 253f8a5edd9a4dbbb1d72e5837243e93c92ebfcd
git push git@github.com:<user_or_organization>/new-repo.git 253f8a5edd9a4dbbb1d72e5837243e93c92ebfcd:master --force
--force
, потому что new-repo
наверняка будет иметь как минимум readme файл, который вы (вероятно) не захотите пуллить.Ну, а если new-repo
является совсем свежим и не содержит даже readme файла – другими словами, вообще не содержит файлов, то все еще проще:
git subtree push --prefix folder-to-move git@github.com:<user_or_organization>/new-repo.git master
К сожалению, не доступен сервер mySQL