Ретроактивный импорт svn в git

Вот моя проблема:

  1. Некоторое время я использовал Subversion, пока не перешел на Git. Прошло еще какое-то время.
  2. Не было импорта истории из Subversion в Git. Это была строгая проверка, удаление директорий .svn, затем git init. Не умный ход.
  3. Теперь, спустя тысячи коммитов git, я нахожу резервную копию репозитория Subversion, сделанную во время первой фиксации git. Ага!

Я хотел бы откатить репозиторий git до дня 0, правильно импортировать репозиторий svn, затем повторно применить все изменения git, исправив тем самым то, что не было сделано в первый раз.

Кто-нибудь пытался это сделать? Как бы я это сделал? Похоже на мать всех ребазов.


10
2 330
2

Ответы:

Я никогда не пробовал то, что вы хотите, но я делаю нечто подобное с CVS.

В принципе, я бы предложил:

  1. Создайте новый репозиторий git с историей из svn
  2. В этом новом репозитории git fetch все из репозитория git (общих коммитов не будет)
  3. Затем git branch remote/branch branch-last и git rebase --onto svn-last remote/branch-first branch-last, где remote/branch-first - это первая фиксация вашего импортированного репозитория git и т. д.

Если у вас больше веток, все будет сложнее. Думаю, можно повторить шаг 3, но лучше попробовать самому. Если в вашей истории git есть слияния, вам может понадобиться git rebase -i -p .... Помните, преимущество git в том, что вы в принципе ничего не можете напортачить (особенно, если вы работаете в отдельном репозитории).


Решено

Похоже на работу для git grafts. Документация по этому поводу немного отрывочна, но в основном вы хотите сделать следующее:

  1. Получите git-svn копию svn в своем репо. Самый простой способ сделать это - git svn clone in, а затем получить svn clone в существующем репозитории.
  2. Выясните, какая базовая фиксация должна следовать за svn-фиксацией. Так что у вас, вероятно, есть где-то git root («Последняя версия SVN»), который должен следовать за последней актуальной версией SVN. Это голова клона git-svn, который вы только что получили.
  3. Создайте файл .git / info / grafts и поместите два sha в одну строку. Первый - это первый коммит git, затем пробел, затем последний коммит svn. Это говорит git, что git-коммит не является родительским, но фактически имеет последний svn-коммит в качестве родительского.
  4. Теперь вы можете проверить с помощью gitk / gitx / независимо от того, что два репозитория подключены
  5. Чтобы сделать изменение постоянным, запустите git filter-branch. Вы, вероятно, захотите сначала прочитать его справочную страницу.

Вы, конечно, можете выполнить шаг 3 и для всех своих веток. Проблема с подходом jpalecek заключается в том, что rebase сгладит вашу историю, поэтому, если у вас были какие-либо слияния, rebase потеряет их. Подход с фильтром-ветвью сохраняет вашу историю нетронутой.