Как повторно подключить репозиторий 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
    
  • Если у вас много ветвей и тегов, повторите те же шаги для них относительно указанного выше отображения:

    • branch/foo = > refs/remotes/foo

    • tags/1.0 = > refs/remotes/tags/1.0

  • Последний шаг - восстановить отображение в каталоге .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 заменить, но это может быть плохая идея.