git-svn: что эквивалентно `svn switch --relocate`?


88

Репозиторий svn, который я зеркалирую через git-svn, изменил URL.

В vanilla svn вы бы просто сделали svn switch --relocate old_url_base new_url_base.

Как я могу это сделать с помощью git-svn?

Простое изменение URL-адреса svn в файле конфигурации не выполняется.


Вам следует попробовать и, возможно, принять этот ответ: stackoverflow.com/a/4061493/1221661
Фриц

Самый последний ответ: stackoverflow.com/a/40523789/537554 . Тот же вопрос, но задан с точки зрения пользователя Git.
ryenus

Ответы:


61

Это хорошо справляется с моей ситуацией:

https://git.wiki.kernel.org/index.php/GitSvnSwitch

Я клонировал с помощью file://протокола и хотел перейти на этот http://протокол.

Заманчиво изменить urlнастройку в [svn-remote "svn"]разделе .git/config, но само по себе это не работает. Как правило, вам необходимо выполнить следующую процедуру:

  1. Измените urlнастройку svn-remote на новое имя.
  2. Беги git svn fetch. Для этого необходимо получить хотя бы одну новую ревизию из svn!
  3. Измените urlнастройку svn-remote на исходный URL-адрес.
  4. Выполнить git svn rebase -lлокальную перебазировку (с изменениями, внесенными при последней операции выборки).
  5. Измените urlнастройку svn-remote на новый URL-адрес.
  6. Теперь git svn rebaseдолжно снова работать.

Любители приключений могут захотеть попробовать --rewrite-root.


2
честно говоря, это на самом деле не удалось для меня, и я снова клонировал репо. Когда каталог svn переименован, трудно заставить git справиться с этим.
Грегг Линд,

Я бы предпочел принять более подробную рецензию, но, честно говоря, я приму ее, пока не появится новый ответ.
kch

2
Вот еще одно описание этой процедуры: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray 03

ссылка, представленная в принятом ответе, устарела, а новая на данный момент: git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html Я следил за "общим случаем ", и это было просто и действительно работал нормально.
TcMaster

2
@TcMaster: у меня тоже сработало ... но именно поэтому ответы не должны содержать только ссылки, они устаревают и становятся бесполезными ... Я собираюсь добавить ответ сообщества вики.
UncleZeiv

37

Вы можете увидеть, работает ли следующее:

  1. Если svn-remote.svn.rewriteRootне существует в файле конфигурации ( .git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Если svn-remote.svn.rewriteUUIDне существует в файле конфигурации:

    git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
    

    Его currentRepositoryUUIDможно получить из .git/svn/.metadata.

  3. git config svn-remote.svn.url <newRepositoryURL>


Потрясающе - спасибо, у меня отлично сработало (клонировано через file://, переключиться на svn+ssh); просто обратите внимание на то, что этой процедуре не нужно "получать хотя бы одну новую ревизию из svn"; также ./.git/svn/.metadataпосле first svn rebaseсодержит <newRepository>as reposRoot- но этого недостаточно, чтобы удалить rewrite*ключи .git/config; таким образом, эти ключи должны храниться там постоянно, насколько я понимаю.
sdaau

1
На меня это тоже подействовало, как чары. OP должен попробовать это и получить правильный ответ.
Rafareino

Отлично. У меня был большой проект с тысячами коммитов в истории, поэтому новый клон уничтожил бы историю (или это заняло бы очень много времени для проверки). Я использую, svn+ssh://и наш svn-сервер только что изменил домен с .seна, .comчтобы очистить наше внутреннее именование.
UlfR 01

Получил удовольствие для меня. Если было репо двухлетней давности с 1000 коммитов, репо было перемещено на новый хост, поэтому это позволило избежать (ужасного) полного клона svn.
Дэвид Виктор

21

К сожалению, большинство ссылок в этих ответах не работают, поэтому я собираюсь продублировать небольшую информацию из git wiki для дальнейшего использования.

Это решение сработало для меня:

  • Отредактируйте svn-remote url(или fetchпуть), .git/configчтобы указать на новый домен / URL / путь

  • Запустите git git svn fetch. Для этого необходимо получить хотя бы одну новую ревизию из svn!

  • Если вы попытаетесь git svn rebaseсейчас, вы получите такое сообщение об ошибке:

    Unable to determine upstream SVN information from working tree history
    

    Я думаю, это потому, что вас git svnсмущает тот факт, что ваша последняя фиксация перед выборкой будет git-svn-idуказывать на старый путь, который не соответствует пути, найденному в .git/config.

  • В качестве обходного пути измените svn-remote url(или fetchпуть) обратно на исходный домен / URL / путь

  • Теперь запустите git svn rebase -lснова, чтобы выполнить локальную перебазировку с изменениями, внесенными при последней операции выборки. На этот раз он будет работать, по- видимому , потому , что git svnне следует путать с тем , что git-svn-idновым главой не совпадает с найденным в .git/config.

  • Наконец, измените svn-remote url(или fetchпуть) обратно на новый домен / URL / путь

  • На этом этапе git svn rebaseдолжно снова работать!

Первоначальная информация была найдена здесь .


3

Git svn сильно зависит от URL-адреса svn. Каждый коммит, импортированный из svn, имеет git-svn-idURL-адрес svn.

Допустимая стратегия перемещения - вызвать git-svn cloneновый репозиторий и объединить изменения с этим новым закрытием. Более подробную процедуру можно найти в этой статье:

http://www.sanityinc.com/articles/relocating-git-svn-repositories


2

git filter-branch

Этот сценарий , взятый из записи в блоге , работал у меня. Укажите старый и новый URL-адреса репо в качестве параметра, как для svn switch --relocate.

Сценарий вызывает git filter-branchзамену URL-адресов Subversion в git-svn-idсообщениях фиксации, обновлениях .git/config, а также обновляет git-svnметаданные, воссоздавая их с помощью git svn rebase. Хотя git svn cloneэтот filter-branchподход может быть более надежным решением, он работает намного быстрее для огромных репозиториев (часы против дней).

#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]
then
  echo "Please invoke this script with two command-line arguments (old and new SVN URLs)."
  exit $E_NO_ARGS
fi

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub("[\\\.]", "\\\\\\\&");print}'`
newUrl=`echo $2 | awk '{gsub("[\\\&]", "\\\\\\\&");print}'`

filter="sed \"s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\""
git filter-branch --msg-filter "$filter" -- --all

sed -i.backup -e "s|$oldUrl|$newUrl|g" .git/config

rm -rf .git/svn
git svn rebase

1

git_fast_filter

Тем не менее, быстрее, чем git-filter-branch(то есть минуты вместо часов), но похожий по духу, это использовать git_fast_filter. Однако для этого требуется немного больше кода, и не существует аккуратного готового решения. В отличие от git-filter-branch, это создаст новое репо из старого . Предполагается, что это masterуказывает на последнюю фиксацию SVN.

  1. Клон git_fast_filterиз репо Gitorious.
  2. Создайте скрипт Python в том же каталоге, где вы клонировали git_fast_filterна основе этого Gist , установите исполняемый бит, используя chmod +x. Адаптируйте старые и новые пути к репозиторию. (Содержание скрипта тоже вставлено ниже.)
  3. Инициализируйте новый целевой репозиторий, используя git init, измените рабочий каталог на это новое репозиторий .
  4. Выполните следующую трубу:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Скопируйте .git/configи, возможно, другие соответствующие файлы .git/infoиз старого репо в новое репо.

  6. Удалить .git/svn.
  7. Обратите внимание git-svnна новое сопоставление номеров ревизий

    1. Выполнить git branch refs/remotes/git-svn master

      • Ваш ГИТ-SVN пультов ДУ можно было бы назвать иначе , чем refs/remotes/git-svn, консультации .git/config, svn-remoteсекции
    2. Выполнить git svn info. Если эта команда зависает, что-то не так. Он должен перестроить отображение номера ревизии.

    3. Удалите поддельную ветку refs/remotes/git-svn, она будет воссозданаgit-svn

  8. Синхронизируй по звонку git svn rebase.

Ниже приведено содержимое commit_filter.py, замените значения IN_REPOи OUT_REPOпри необходимости:

#!/usr/bin/python

from git_fast_filter import Commit, FastExportFilter
import re
import sys

IN_REPO = "https://svn.code.sf.net/p/matsim/code"
OUT_REPO = "https://svn.code.sf.net/p/matsim/source"

IN_REPO_RE = re.compile("^git-svn-id: %s" % re.escape(IN_REPO), re.M)
OUT_REPO_RE = "git-svn-id: %s" % OUT_REPO

def my_commit_callback(commit):
  commit.message = IN_REPO_RE.sub(OUT_REPO_RE, commit.message)
  sys.stderr.write(".")

filter = FastExportFilter(commit_callback = my_commit_callback)
filter.run()

0

Вышеупомянутое git svn rebase -lрешение не сработало для меня. Я решил пойти другим путем:

  1. Клонировать старый репозиторий SVN в репозиторий git, oldа новый SVN - в репозиторий gitnew
  2. Получить oldвnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newна вершине old(должно быть успешным, потому что деревья в корне newи на вершине oldидентичны)
    • git checkout master(Предполагается, что masterветвь указывает на головку SVN. Так будет с чистым клоном; в противном случае dcommit перед началом.)
    • git rebase --root --onto old
  4. Восстановите метаданные git-svn newдля учета перебазирования
    • git update-ref --no-deref refs/remotes/git-svn master(отрегулируйте удаленный ref в зависимости от того, как вы клонировали, например, это могло быть refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info

1. Вы начинаете со свежего клона новой локации в новую? Если да, то почему вы еще не закончили? 2. Если вы переустанавливаете новый на старый, все ли ваши старые коммиты упоминают старый URL в своей записи журнала фиксации svn-id? 3. Есть ли какая-нибудь документация, позволяющая удалить .git / svn? (3b: какая команда восстанавливает метаданные git-svn, git svn info?)
Миша Виденманн,

0

Основываясь на некоторых других ответах на этот вопрос, я придумал сценарий Ruby, который обрабатывает перемещение git-svn. Вы можете найти его на https://gist.github.com/henderea/6e779b66be3580c9a584 .

Он обрабатывает перемещение, не проверяя другую копию, и даже обрабатывает случай, когда в одной или нескольких ветвях есть не отправленные изменения (поскольку это нарушает обычную логику). Он использует материал из ответа git filter-branch (для основной логики) и ответ о копировании ветвей из одного экземпляра репо в другой (для копирования ветвей с неопталкиваемыми изменениями).

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

Сценарий дает вам возможность создать копию репо перед внесением каких-либо изменений, поэтому вы можете использовать эту опцию для создания резервной копии. Создание копии требуется, если у вас есть неопубликованные изменения в каких-либо ветвях.

Скрипт не использует гемов или других библиотек, не включенных в обычную установку MRI Ruby. Он действительно использует библиотеки readline и fileutils, включенные в MRI.

Надеюсь, мой сценарий окажется полезным для кого-то еще. Не стесняйтесь вносить изменения в сценарий.

ПРИМЕЧАНИЕ. Я тестировал этот сценарий только с git 2.3.0 / 2.3.1 и Ruby 2.2.0 на OS X 10.10 Yosemite (поскольку это среда, которую я использую), но я ожидаю, что он будет работать и в других средах. Однако никаких гарантий насчет Windows.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.