Обход ошибки "git svn clone" (требуется полная история)

Я хочу преобразовать подкаталог хранилища Subversion (обозначается как module здесь) в репозиторий git с полной историей. Здесь очень много svn copy операций (люди из Subversion называют их ветвями) в истории моего хранилища Subversion. Политика выпуска заключалась в том, что после каждого выпуска или других созданных веток старый URL-адрес остается неиспользованным, а новый URL-адрес заменяет старый для размещения работы.

Оптимально, на мой взгляд, кажется, что это должно сработать:

$ git svn clone --username=mysvnusername --authors-file=authors.txt \
    --follow-parent \
    http://svnserver/svn/src/branches/x/y/apps/module module

(где branches/x/y/ изображает новейшую ветку). Но я получил ошибку, которая выглядит примерно так:

W: Ignoring error from SVN, path probably does not exist: (160013): Filesystem has no item: '/svn/src/!svn/bc/100/branches/x/y/apps/module' path not found
W: Do not be alarmed at the above message git-svn is just searching aggressively for old history.

(Обновление: добавление опции --no-minimize-url к вышесказанному не удаляет сообщение об ошибке.)

Каталог module создать и заполнить, но история Subversion мимо новейших svn copy commit не импортируется (созданный репозиторий git в итоге имеет только два коммита, когда я ожидал сотни).

Вопрос в том, как экспортировать полную историю Subversion при наличии такой ситуации?

Возможная причина

  1. В поисках сообщения об ошибке я обнаружил следующее: анонимная проверка git-svn завершается с помощью -s, которая связана с этой проблемой Subversion: http://subversion.tigris.org/issues/show_bug.cgi?id=3242

    Что я понимаю по чтению, что-то в Subversion 1.5 изменилось в том, как клиент получает доступ к хранилищу. С более новой Subversion, если нет доступа для чтения к некоторому суперкаталогу пути URL (верно для меня, svn ls http://svnserver/svn не удается с 403 Forbidden), то мы потерпим неудачу с некоторыми операциями Subversion.

  2. Джефф Фэрли в своем ответе указывает, что пробелы в Subversion URL также могут вызывать это сообщение об ошибке (подтверждено пользователем Оуэном). Посмотрите на его решение, чтобы увидеть, как он раскрыл дело, если ваш git svn clone терпит неудачу для того же Resson.

  3. Дежей Клэйтон в своем ответе показывает, что, если самые глубокие компоненты подкаталогов в ветвях и URL-адресах тегов svn имеют одинаковые имена (например, .../tags/release/1.0.0 а также .../branches/release-candidates/1.0.0) тогда эта ошибка может произойти.

5 ответов

Решение

Я столкнулся с этой проблемой, когда у меня были подкаталоги с одинаковыми именами в ветвях или тегах.

Например, у меня были теги candidates/1.0.0 а также releases/1.0.0, и это вызвало документированную ошибку, потому что подкаталог 1.0.0 появляется в обоих candidates а также releases,

В git-svn docs:

При использовании нескольких --branches или --tags, git svn не обрабатывает автоматически конфликты имен (например, если две ветви из разных путей имеют одинаковое имя или если ветвь и тег имеют одинаковое имя). В этих случаях используйте init для настройки вашего Git-репозитория, затем перед первой загрузкой отредактируйте файл $GIT_DIR/config так, чтобы ветви и теги были связаны с различными пространствами имен.

Таким образом, в то время как следующая команда не выполнена из-за candidates а также releases теги:

git svn clone --authors-file=../authors.txt --no-metadata \
    --trunk=/trunk --branches=/branches --tags=/candidates \
    --tags=/releases --tags=/tags -r 100:HEAD \
    --prefix=origin/ \
    svn://example.com:3692/my-repos/path/to/project/

сработала следующая последовательность команд:

git svn init --no-metadata \
    --trunk=/trunk --branches=/branches --tags=/tags \
    --prefix=origin/ \
    'svn://example.com:3692/my-repos/path/to/project/'

git config --add svn-remote.svn.tags \
    'path/to/project/candidates/*:refs/remotes/origin/tags/Candidates/*'

git config --add svn-remote.svn.tags \
    'path/to/project/releases/*:refs/remotes/origin/tags/Releases/*'

git svn fetch --authors-file=../authors.txt -r100:HEAD

Обратите внимание, что это работает только потому, что не было никаких других конфликтов внутри branches а также tags, Если бы они были, мне пришлось бы их решить аналогичным образом.

После успешного клонирования SVN-репозитория я выполнил следующие шаги для: превращения SVN-тегов в GIT-теги; очередь trunk в master; превращать другие ссылки в ветки; и переместить удаленные пути:

# Make tags into true tags
cp -Rf .git/refs/remotes/origin/tags/* .git/refs/tags/
rm -Rf .git/refs/remotes/origin/tags

# Make other references into branches
cp -Rf .git/refs/remotes/origin/* .git/refs/heads/
rm -Rf .git/refs/remotes/origin
cp -Rf .git/refs/remotes/* .git/refs/heads/ # May be missing; that's okay
rm -Rf .git/refs/remotes

# Change 'trunk' to 'master'
git checkout trunk
git branch -d master
git branch -m trunk master

Не полный ответ, но, возможно, фрагмент, который вам не хватает (я также заинтересован в миграции, поэтому я нашел эту часть головоломки).

Когда вы посмотрите на документацию git-svn, вы найдете следующую опцию:

--no-minimize-url 

При отслеживании нескольких каталогов (с использованием параметров --stdlayout, --branches или --tags) git svn будет пытаться подключиться к корню (или максимально допустимому уровню) хранилища Subversion. Это значение по умолчанию позволяет лучше отслеживать историю, если целые проекты перемещаются в хранилище, но может вызвать проблемы в хранилищах, где установлены ограничения на чтение. Передача --no-minimal-url позволит git svn принимать URL-адреса как есть, не пытаясь подключиться к каталогу более высокого уровня. Эта опция отключена по умолчанию, когда отслеживается только один URL/ ветвь (это мало что даст).

Это соответствует вашей ситуации, так что git svn не пытается прочитать более высокий уровень дерева каталогов (который будет заблокирован).

По крайней мере, вы можете попробовать...

Недавно я перенес длинный список SVN-репозиториев в Git и в конце столкнулся с этой проблемой. Наша структура SVN была довольно небрежной, поэтому мне пришлось использовать --no-minimize-url немного. Обычно я запускаю такую ​​команду:

$ git svn clone http://[url]/svn/[repo]/[path-to-code] \
            -s --no-minimize-url \
            -A authors.txt

Последние несколько миграций, которые я выполнял, имели место в URL. Я не знаю, было ли это место или что-то еще, но я получал ту же ошибку, которую вы видели. Я не хотел вносить изменения в конфигурационные файлы, если бы мне это не нужно, и, к счастью, в итоге я нашел решение. Я пропустил -s --no-minimize-url варианты в пользу явного объявления путей по-разному.

$ git svn clone http://[url]/svn/[repo]/ \
            --trunk="/[path-to-code]/trunk" \
            --branches="/[path-to-code]/branches" \
            --tags="/[path-to-code]/tags" \
            -A authors.txt \
            --follow-parent
  • Обратите внимание, что я добавил --follow-parent из вашего примера, но я также не уверен, что это имело какое-либо значение.
  • Помните, что в этих репозиториях были пробелы, поэтому "" вокруг ствола / ветки / метки дорожек.

[ Я понимаю, что это должен быть комментарий к ответу Джеффа Фэрли, но у меня нет репутации, чтобы публиковать его как таковой. Так как оригинальный постер просил подтверждения, подход сработал, и я привожу его в качестве ответа. ]

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

Я попытался несколько вариантов предоставления полного пути к модулю в URL (например, используя --no-minimise-url, указав --trunk или же --stdlayout безуспешно Для меня результатом обычно было git-репо с полным журналом истории, но без каких-либо файлов. Это может быть, а может и не быть той же проблемой, с которой столкнулся FooF (нет доступа на чтение в SVN), но это, безусловно, было вызвано наличием пробела в пути к моему модулю.

Попытка еще раз с использованием только базы репо SVN в качестве URL и пути к моему модулю в --trunk работал без нареканий. После этого мой.git/config выглядит так:

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        loggallrefupdates = true
        symlinks = false
        ignorecase = true
        hideDotFiles = dotGitOnly
[svn-remote "svn"]
        url = https://[url]/svn/[repo]
        fetch = trunk/[path-to-code]:refs/remotes/trunk
[svn]
        authorsfile = ~/working/authors-transform.txt

и последующее git а также git svn Команды не выдают ошибок вообще. Спасибо, Джефф!

[Это оригинальный постер, говорящий письменно. Нижеследующее раньше было обновлением вопроса, но, поскольку оно решило проблему - хотя и неудовлетворительно на мой вкус - я опубликую ее как ответ, в котором отсутствует лучшее решение.]

Мне не нравится это, но я закончил тем, что делал clone разделен на init а также fetch с некоторым редактированием .git/config между (repopath=apps/module, gitreponame=module):

$ git svn init--username=mysvnusername \
            --branches=/src/branches/ \
            --trunk=/src/trunk/${repopath} \
            --tags=/src/tags/ \
            http://svnserver/svn/src ${gitreponame}
$ cd ${gitreponame}
$ sed -i.bak "s|*:|*/${repopath}:|" .git/config
$ git svn fetch --authors-file=../authors.txt --follow-parent

Я не мог найти, как указать ветви для миграции подкаталога с git svn - следовательно, редактирование .git/config файл. Следующий унифицированный diff иллюстрирует эффект редактирования с sed:

 [svn-remote "svn"]
        url = http://svnserver/svn/src
        fetch = trunk/apps/module:refs/remotes/trunk
-       branches = branches/*:refs/remotes/*
-       tags = tags/*:refs/remotes/tags/*
+       branches = branches/*/apps/module:refs/remotes/*
+       tags = tags/*/apps/module:refs/remotes/tags/*

Как фактическое желаемое HEAD был в другом URL, я закончил просто добавив еще один [svn-remote] раздел к .git/config:

+ [svn-remote "svn-newest"]
+       url = http://svnserver/svn/src
+       fetch = branches/x/y/apps/module:refs/remotes/trunk
+       branches = branches/*/apps/module:refs/remotes/*
+       tags = tags/*/apps/module:refs/remotes/tags/*

(в эксперименте из реальной жизни я также добавил сюда несколько веток, которые не были обнаружены при первой загрузке), и загрузку снова:

$ git svn fetch --authors-file=../authors.txt --follow-parent svn-newest

Таким образом, я закончил миграцию полной истории Subversion во вновь созданный git-репозиторий.

Примечание-1: я, вероятно, мог бы просто сказать, что мой "ствол" branches/x/y/apps/module как значение "ствол" для git-svn кажется, в основном имеет значение мерзавец HEAD (Понятия Subversion для ствола, ветвей, меток не имеют глубокой технической основы, они являются предметом социально согласованной конвенции).

Примечание-2: возможно --follow-parent не требуется для git svn fetch, но у меня нет способа узнать или экспериментировать сейчас.

Примечание-3: При более раннем чтении svn2git, который выглядит как обертка git-svn Я не смог понять мотивацию, но, увидев грязное представление тегов, я как бы понял это сейчас. я бы попробовал svn2git в следующий раз, если бы мне пришлось попробовать сделать это снова.

PS Это довольно неловкий способ сделать операцию. Вторичная проблема здесь (почему редактирование .git/config по внешнему требовалось) похоже что

  1. Ветви Subversion не имеют какого-либо существенного технического значения (ветви и теги в Subversion являются просто социально согласованными метками для версионной копии файловой системы вместе со "стандартным" или иным образом социально согласованным соглашением, в котором выполняются копии - транк также не имеет технического значения), а также
  2. git svn Реализация строго предполагает соблюдение социальных соглашений Subversion до некоторой степени (что невозможно, если вы просто хотите перенести подкаталог, а не весь репозиторий Subversion).

ТОДО: Было бы полезно иметь формат .git/config Файл объяснен здесь, поскольку он относится к git svn - например, я сейчас (после полутора лет написания оригинального ответа) понятия не имею, что [svn-remote "svn-newest"] значит выше. Также этот подход можно автоматизировать, написав сценарий, но это выходит за рамки моего текущего интереса к проблеме, и у меня нет доступа к исходному хранилищу Subversion или репликации проблемы.

Другие вопросы по тегам