Обход ошибки "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 при наличии такой ситуации?
Возможная причина
В поисках сообщения об ошибке я обнаружил следующее: анонимная проверка 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.Джефф Фэрли в своем ответе указывает, что пробелы в Subversion URL также могут вызывать это сообщение об ошибке (подтверждено пользователем Оуэном). Посмотрите на его решение, чтобы увидеть, как он раскрыл дело, если ваш
git svn clone
терпит неудачу для того же Resson.Дежей Клэйтон в своем ответе показывает, что, если самые глубокие компоненты подкаталогов в ветвях и 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
по внешнему требовалось) похоже что
- Ветви Subversion не имеют какого-либо существенного технического значения (ветви и теги в Subversion являются просто социально согласованными метками для версионной копии файловой системы вместе со "стандартным" или иным образом социально согласованным соглашением, в котором выполняются копии - транк также не имеет технического значения), а также
git svn
Реализация строго предполагает соблюдение социальных соглашений Subversion до некоторой степени (что невозможно, если вы просто хотите перенести подкаталог, а не весь репозиторий Subversion).
ТОДО: Было бы полезно иметь формат .git/config
Файл объяснен здесь, поскольку он относится к git svn
- например, я сейчас (после полутора лет написания оригинального ответа) понятия не имею, что [svn-remote "svn-newest"]
значит выше. Также этот подход можно автоматизировать, написав сценарий, но это выходит за рамки моего текущего интереса к проблеме, и у меня нет доступа к исходному хранилищу Subversion или репликации проблемы.