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

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

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

Как это сделать, используя git -svn?

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

Ответ 1

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

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

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

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

  • Переключите параметр svn-remote url в новое имя.
  • Запустите git svn fetch. Это нужно, чтобы получить хотя бы одну новую ревизию из svn!
  • Измените параметр svn-remote url на исходный URL.
  • Запустите git svn rebase -l, чтобы выполнить локальную переадресацию (с изменениями, внесенными с последней операцией выборки).
  • Измените параметр svn-remote url на новый URL-адрес.
  • Теперь git svn rebase должен снова работать.

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

Ответ 2

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

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

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

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

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

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

Ответ 3

К сожалению, большинство ссылок в этих ответах не работают, поэтому я собираюсь дублировать информацию из 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/path

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

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

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

Исходная информация была найдена здесь.

Ответ 4

Git svn сильно зависит от URL-адреса svn. Каждая фиксация, импортированная из svn, имеет git-svn-id, которая включает URL-адрес svn.

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

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

Ответ 5

git filter-branch

Этот script, взятый из запись в блоге, работал у меня. Поставьте старый и новый 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

Ответ 6

git_fast_filter

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

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

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

  • Удалите .git/svn.
  • Сделайте git-svn осведомленным о сопоставлении новых номеров версий

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

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

    • Удалите фальшивую ветвь refs/remotes/git-svn, она будет воссоздана git-svn

  • Синхронизировать, вызывая 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()

Ответ 7

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

  • Клонировать старый SVN-репо в git repo old и новый SVN в git repo new
  • Извлечь old в new
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  • Rebase new поверх old (должен преуспеть, потому что деревья в корне new и кончик old идентичны)
    • git checkout master (Предполагается, что ветвь master указывает на голову SVN.Это будет иметь место с чистым клоном, иначе dcommit перед запуском.)
    • git rebase --root --onto old
  • Восстановить метаданные 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

Ответ 8

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

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

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

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

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

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

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