git-svn: що еквівалентно `svn switch --relocate`?


88

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

У ванільному свн ви б просто зробили 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. Переключіть налаштування 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.


2
чесно кажучи, це насправді не вдалося для мене, і в підсумку я перекланував репо. Важко отримати git для обробки, коли каталог svn перейменовано.
Gregg Lind

Я волів би прийняти більш детальну інформацію, але досить справедливо, я прийму її, поки не з’явиться нова відповідь.
kch

2
Ось ще один опис цієї процедури: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray

посилання, надане у прийнятій відповіді, застаріле, а новим на даний момент є: 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після того, як вперше svn rebaseмістить <newRepository>як reposRoot- але цього недостатньо, щоб видалити rewrite*ключі з .git/config; отже, ці ключі слід постійно зберігати там, наскільки я розумію.
sdaau

1
Це спрацювало і на мене, як на шарм. ОП повинен спробувати цей і отримати його як правильну відповідь.
Рафарейно,

Ідеально У мене був великий проект з тисячами комітів в історії, тому новий клон знищив би історію (або зайняв би справді багато часу). Я використовую, svn+ssh://і наш svn-сервер щойно змінив домен з .seна .comдля дезінфекції нашого внутрішнього іменування.
UlfR

Працював для мене частуванням. Якби було 2-річне репо з 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-idяке включає URL-адресу 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 repo oldі нове SVN в git reponew
  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

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

0

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

Він обробляє переїзд, не перевіряючи іншу копію, і навіть обробляє випадок, коли в одній або декількох гілках відбуваються непроштовхувані зміни (оскільки це порушує звичайну логіку). Він використовує речі з відповіді на фільтр-гілку git (для основної логіки) та відповідь про копіювання гілок з одного екземпляра репо в інший (для копіювання гілок із ненадаленими змінами).

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

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

Сценарій не використовує дорогоцінних каменів та інших бібліотек, не включених до звичайної установки МРТ Ruby. Він використовує бібліотеки readline та fileutils, включені до МРТ.

Сподіваюся, мій сценарій виявиться корисним комусь іншому. Не соромтеся вносити зміни в сценарій.

ПРИМІТКА: Я протестував цей сценарій лише з 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.