git-svn: что эквивалентно `svn switch --relocate`? - PullRequest
86 голосов
/ 06 ноября 2008

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

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

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

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

Ответы [ 8 ]

59 голосов
/ 06 ноября 2008

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

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

Я клонировал по протоколу file:// и хотел переключиться на протокол http://.

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

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

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

34 голосов
/ 31 октября 2010

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

  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>

21 голосов
/ 15 ноября 2011

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

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

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

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

2 голосов
/ 22 августа 2013

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 голос
/ 22 августа 2013

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

      • Ваши пульты git-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 голосов
/ 26 февраля 2015

Основываясь на некоторых других ответах на этот вопрос, я придумал скрипт 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.

0 голосов
/ 02 января 2014

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

  1. Клонировать старый репозиторий SVN в git repo old и новый SVN в репозиторий git new
  2. Извлечение old в new
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Перебазировка 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 (отрегулируйте удаленную ссылку в зависимости от того, как вы клонировали, например, это может быть refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info
...