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.