Самый простой способ воспроизведения коммитов в новом git-репозитории - PullRequest
18 голосов
/ 17 марта 2011

Я использую git-svn, и недавно у меня возникали ошибки при попытке зафиксировать (я думаю, это связано с ошибкой в ​​libneon, но это выходит за рамки этого вопроса). Решением было повторно клонировать мой git-репозиторий, используя git svn clone. Тем не менее, у меня есть изменения в основной ветке в моем старом git-репозитории, которые я не смог зафиксировать в svn, используя git svn dcommit. Я хотел бы воспроизвести эти изменения в новом репозитории, клонированном с помощью git svn. Я думаю, что я мог бы экспортировать набор патчей, используя git format-patch, а затем воспроизвести эти изменения в новом хранилище, но я не совсем уверен, как это сделать, и мне интересно, есть ли еще более простой или более элегантный способ выполнить это.

Ответы [ 2 ]

45 голосов
/ 17 марта 2011

Из вашего нового репозитория добавьте удаленную ссылку на ваш старый репозиторий:

git remote add temp file:///path/to/old/repo/on/your/machine

Выборка из старого репозитория:

git fetch temp

Извлечение вашей основной ветки из старого репозитория:

git checkout temp/master -b wip

(wip обозначает незавершенное производство)

Перебазировать изменения поверх содержимого в вашем текущем хранилище:

git rebase master

Обновление мастерауказать на ваш новый HEAD:

git checkout master
git merge wip

Удалите удаленную ссылку на ваше старое репо и ветку wip, которую вы использовали:

git branch -d wip
git remote rm temp

Что вы на самом деле делаете:

Во-первых, добавляя удаленную ссылку и выбирая, вы извлекаете коммиты из вашего предыдущего репозитория, которых у вас еще нет в вашем текущем репозитории.Git знает, как это сделать, потому что, независимо от того, где и как это было сделано, один и тот же коммит везде выглядит одинаково.Это хэш SHA1 нескольких хорошо известных фрагментов информации, включая дерево каталогов, коммиттер, метку времени, ...

Поэтому, когда вы создаете новый репозиторий Git, основанный на том же репозитории SVN, всекоммиты имели одинаковые суммы SHA1.В результате новые коммиты, которые вы загрузили в ваш текущий репозиторий , продолжали указывать на нужные вещи .Это очень круто, и важно помнить.

Затем вы переключились на верхушку ветки master и сказали, чтобы она перебазировалась на ваш текущий master.Перебазировка, возможно, была ненужной, поскольку мастер из SVN, возможно, не отошел от мастера в вашем старом репо, но лучше было быть в безопасности.

Перебазировка находит ближайшую точку соприкосновения между двумя коммитамиработая в обратном направлении через свои истории, пока они оба не укажут на один родительский коммитЗатем он переключается на название ветви, которое вы ему дали (в данном случае master), и вишня выбирает каждый из коммитов, отсутствующих в его истории, из вашей исходной ветви.После завершения он указывает ветвь, в которой вы находились, когда вы начали последний примененный коммит.

Наконец, слияние мастера с wip было просто для быстрой перемотки мастера до конца.Поскольку это была прямая линия, это было просто ускоренное движение вперед.Вы могли бы так же легко сделать ребаз или сброс --hard;любой из них изменил бы основную ветвь так, чтобы она указывала на правильное местоположение.Слияние было только самым безопасным из них, потому что, если бы случилось что-то странное, это дало бы вам понять, что это не просто перемотка вперед.

9 голосов
/ 17 марта 2011

Вы можете:

  • добавить свое старое репо в качестве удаленного нового репо (git remote)
  • получить старую ветку
  • перебазировать детальинтересующей вас старой ветки поверх вашей текущей master.

См. Как выбрать диапазон коммитов и объединить их в другую ветку :

# go to your current but incomplete new master branch
git checkout master

# mark your current master HEAD as branch 'tmp'
git checkout -b tmp

# reset your master to the old one
git branch -f master oldrepo/master

# replay the right commits on top of 'tmp' (which was your master HEAD)
git rebase --onto tmp first_SHA-1_of_old_master_to_replay~1 master

# remove tmp branch, 
# your master HEAD is now on top of tmp, with the right commits replayed
git branch -d tmp

Это решение будет работать, даже если SHA1 отличается от вашей старой master истории, а ваш новый мастер - от вашей второй git-svn clone.
Именно поэтому я рекомендую rebase --onto: историю обоихmaster s может не иметь ничего общего, если по какой-либо причине второй git-svn clone не генерирует точно того же SHA1.

...