Как повторно подключить репозиторий git с репозиторией svn?
Я использовал git svn
для импорта существующего репозитория Subversion в git. Затем я нажал на git repo на сервере git. За последние несколько месяцев изменения в программном обеспечении были сделаны как в хранилищах Subversion, так и в репозиториях git. К сожалению, моя локальная копия со ссылками между svn и git была удалена.
Я попытался снова создать локальную копию с помощью git svn
, но когда я делаю попытку с сервера git, он жалуется warning: no common conflicts
, и я заканчиваю слияние двух отдельных ветвей с теми же самыми коммитами в начале, Вот так:
F
|\
| \
E D
| |
C C
| |
B B
| |
A A
Как я могу заставить его обрабатывать изменения svn, как они произошли на ветке из исходного репо?
F
|\
| \
E D
| /
|/
C
|
B
|
A
Ответы
Ответ 1
По умолчанию git-svn
хранит сопоставление между версиями SVN и Git фиксирует сообщения фиксации. Вы видите эти строки git-svn-id
для более старых коммитов в вашем исходном репозитории Git? Здесь я имею в виду, что репозиторий Git размещен на сервере Git, а не тот, который вы недавно выбрали из SVN.
Если это так, вы фактически не потеряли никаких ссылок, и git -svn должен иметь возможность восстановить необходимые данные из истории. Хотя из-за некоторых проблем совместимости между различными версиями git -svn это может быть немного сложнее:
-
Скопируйте исходный репозиторий Git:
$ git clone $GIT_SERVER repo
$ cd repo
-
Обновить конфигурацию git -svn в .git/config:
$ git config svn-remote.svn.url $SVN_URL
$ git config svn-remote.svn.fetch trunk:refs/remotes/trunk
$ git config svn-remote.svn.branches branches/*:refs/remotes/*
$ git config svn-remote.svn.tags tags/*:refs/remotes/tags/*
-
Теперь вам нужно обновить refs/remotes/* refs до последней фиксации с помощью строки git -svn-id:
$ git log --first-parent refs/heads/master
commit d566edf5f77ae0a2f7418c40949757e75ef8e83c
D
commit 4df9f21346526c6505a954d8310637864710308d
C
git-svn-id: $SVN_URL .../[email protected]
commit 116a6760d3e278aa4d54f5bb22e531d30d731661
B
git-svn-id: $SVN_URL .../[email protected]
commit d8bb201c6fd55ea5e645f2d8a07248593d177910
A
git-svn-id: $SVN_URL .../[email protected]
Как вы можете видеть, у фиксации D нет строки git -svn-id, но commit C имеет один, и эта строка относится к trunk, поэтому вам нужно обновить refs/remotes/trunk для фиксации C:
$ git update-ref refs/remotes/trunk 4df9f21346526c6505a954d8310637864710308d
-
Если у вас много ветвей и тегов, повторите те же шаги для них относительно указанного выше отображения:
-
Последний шаг - восстановить отображение в каталоге .git/svn:
$ git svn fetch
Migrating from a git-svn v1 layout...
Data from a previous version of git-svn exists, but
.git/svn
(required for this version (X.Y.Z) of git-svn) does not exist.
Done migrating from a git-svn v1 layout
Rebuilding .git/svn/refs/remotes/trunk/.rev_map.694389ff-b137-4359-84f9-4d1a25628e89...
r1 = d8bb201c6fd55ea5e645f2d8a07248593d177910
r2 = 116a6760d3e278aa4d54f5bb22e531d30d731661
r3 = 4df9f21346526c6505a954d8310637864710308d
Done rebuilding .git/svn/refs/remotes/trunk/.rev_map.694389ff-b137-4359-84f9-4d1a25628e89
Последняя команда также извлекает новые версии с сервера SVN. После выполнения команды у вас есть git -svn клон репозитория Subversion. История в этом репозитории расходилась, поэтому вам нужно синхронизировать изменения между SVN и репозиториями Git, как обычно:
$ git svn rebase
$ git svn dcommit
Надеюсь, что это поможет.
Ответ 2
Сначала я проверил вывод команды git svn info
. Вы видите там какие-то странные вещи?
Во-вторых, дело в том, что не рекомендуется использовать git svn
со вторичным репозиторием git, отличным от вашего локального.
Причина в том, что после каждого git svn dcommit
git автоматически перезаписывает все сделанные вами коммиты: сначала он возвращает их обратно в svn, а затем добавляет номер версии svn для фиксации (в уникальный идентификатор git-svn-id
).
Это должно быть что-то вроде этого в репозитории, где вы создали новый dcommit
:
$ git log -1
commit 1234abc...
Author: ...
Date: ...
Some commit message
git-svn-id: http://your.svn.repo/svn/[email protected] 1234abc
О деталях, вот раздел из книги ProGit.
Сообщение об ошибке, которое вы написали, вероятно, warning: no common commits
(не conflicts
, как вы писали в вопросе), и мое впечатление, что git не переместил эти метаданные в удаленное репо.
Я думаю, вы можете поднять эту ссылку SVN из мертвых, но будьте осторожны, сделайте это на отдельном клоне репо и внимательно прочитайте документацию о том, какие метаданные ему нужны. В git вы можете сделать много вещей с помощью сантехнических инструментов, взгляните на них.
Btw не можете ли вы просто клонировать удаленный репозиторий git и использовать его?
Надеюсь, что это поможет, или, по крайней мере, даст вам несколько идей, в которых вы можете начать поиск решения.
Ответ 3
Из графика фиксации
F
|\
| \
E D
| |
C1 C2
| |
B1 B2
| |
A1 A2
используйте следующую команду
git checkout <SHA1-B1>
git checkout -b new
git cherry-pick <SHA1-C2> <SHA1-D>
git checkout <SHA1-F>
git checkout -b position_f
git merge new
Готово. Во всяком случае, я еще не пробовал. Сначала создайте резервную копию своего репозитория.
Ответ 4
Простейшим решением является подталкивание локальных ветвей git -svn к вашему серверу git, например:
git push <git-server> <branch-name>:<branch-name>
Он переопределит ветки git -сервера с вашими локальными.
Сделайте это, только если вы уверены, что в ветвях git -svn есть все коммиты, которые имеет сервер git.
Ответ 5
Как насчет этого:
- Сделайте резервную копию!
- Повторно импортируйте историю svn в git
- Получите свою старую ветку и новую ветку в те же репо
- Перемотайте ветку на фиксацию до
F
- Восстановите все изменения в своей ветке с вашего
C
поверх нового svn-импортированного C
- Повторите попытку слияния
Если это не сработает, вы можете попробовать Git заменить, но это может быть плохая идея.