Подтвердить что ты не робот

Обход для отказа "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, не импортируется (созданный репозиторий git заканчивается тем, что имеет только два коммита, когда я ожидал сотни).

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Per 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 okay
rm -Rf .git/refs/remotes

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

Ответ 2

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

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

--no-minimize-url 

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

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

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

Ответ 3

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

Ответ 4

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

Я могу подтвердить, что его решение работает для проблемы, с которой он (и я) столкнулся, вызванный пробелами в пути. У меня были такие же требования (клонирование одного модуля из 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 вообще не выдают ошибок. Спасибо Джеффу!

Ответ 5

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

Мне это не нравится, но я закончил тем, что 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, поскольку значение "trunk" для git-svn похоже в основном имеет значение git HEAD (понятия Subversion для туловища, ветвей, тегов не имеют глубокой технической основы, они являются предметом социально согласованного соглашения).

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

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

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

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

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