git-svn: Was entspricht "svn switch --relocate"?

87

Ein SVN-Repository, das ich über git-svn spiegele, hat die URL geändert.

In Vanilla SVN würden Sie einfach tun svn switch --relocate old_url_base new_url_base.

Wie kann ich das mit git-svn machen?

Das einfache Ändern der SVN-URL in der Konfigurationsdatei schlägt fehl.

kch
quelle
Sie sollten versuchen, diese Antwort möglicherweise zu akzeptieren: stackoverflow.com/a/4061493/1221661
Fritz
Aktuellste Antwort: stackoverflow.com/a/40523789/537554 . Dieselbe Frage, aber aus der Sicht eines Git-Benutzers gestellt.
Ryenus

Antworten:

61

Das geht ziemlich gut mit meiner Situation um:

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

Ich habe mit dem file://Protokoll geklont und wollte zum http://Protokoll wechseln .

Es ist verlockend, die urlEinstellung im [svn-remote "svn"]Abschnitt von zu bearbeiten .git/config, aber allein funktioniert dies nicht. Im Allgemeinen müssen Sie wie folgt vorgehen:

  1. Schalten Sie die urlEinstellung svn-remote auf den neuen Namen um.
  2. Ausführen git svn fetch. Dies muss mindestens eine neue Revision von svn abrufen!
  3. Ändern Sie die urlEinstellung von svn-remote wieder in die ursprüngliche URL.
  4. Führen Sie git svn rebase -ldiese Option aus, um eine lokale Rebase durchzuführen (mit den Änderungen, die beim letzten Abruf vorgenommen wurden).
  5. Ändern Sie die urlEinstellung von svn-remote wieder in die neue URL.
  6. Jetzt git svn rebasesollte wieder funktionieren.

Abenteuerlustige möchten es vielleicht versuchen --rewrite-root.

kch
quelle
2
Um fair zu sein, ist dies für mich tatsächlich gescheitert und ich habe das Repo neu geklont. Es ist schwierig, git dazu zu bringen, damit umzugehen, wenn das svn-Verzeichnis umbenannt wird.
Gregg Lind
Ich würde es vorziehen, eine detailliertere Beschreibung zu akzeptieren, aber fairerweise werde ich sie akzeptieren, bis eine neue Antwort kommt.
kch
2
Hier ist eine weitere Beschreibung dieses Verfahrens: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray
Der in der akzeptierten Antwort angegebene Link ist veraltet und der neue lautet ab sofort: git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html Ich bin dem "Allgemeinen Fall" gefolgt und es war einfach und wirklich hat gut funktioniert.
TcMaster
2
@TcMaster: hat auch für mich funktioniert ... aber deshalb sollten Antworten nicht nur Links enthalten , sie werden veraltet und unbrauchbar ... Ich werde eine Community-Wiki-Antwort hinzufügen.
Onkel Zeiv
36

Sie können sehen, ob Folgendes in Ordnung ist:

  1. Wenn svn-remote.svn.rewriteRootin config file ( .git/config) nicht vorhanden :

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Wenn svn-remote.svn.rewriteUUIDin der Konfigurationsdatei nicht vorhanden:

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

    Die currentRepositoryUUIDerhalten Sie von .git/svn/.metadata.

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

H Krishnan
quelle
Fantastisch - danke, das hat bei mir super funktioniert (geklont via file://, wechseln zu svn+ssh); Nur um Folgendes zu beachten: Diese Prozedur muss nicht "mindestens eine neue Revision von svn abrufen"; auch ./.git/svn/.metadatanach dem ersten svn rebaseenthält das <newRepository>as reposRoot- aber dies reicht nicht aus, um die rewrite*Schlüssel von zu entfernen .git/config; Daher sollten diese Schlüssel, soweit ich das verstehe, dauerhaft dort aufbewahrt werden.
Sdaau
1
Es hat auch für mich funktioniert, wie ein Zauber. Das OP sollte dies versuchen und es als die richtige Antwort erhalten.
Rafareino
Perfekt. Ich hatte ein großes Projekt mit Tausenden von Commits in der Geschichte, sodass ein neuer Klon die Geschichte zerstört hätte (oder das Auschecken sehr lange gedauert hätte). Ich verwende svn+ssh://und unser SVN-Server hat gerade die Domain von .seauf geändert .com, um unsere interne Benennung zu bereinigen.
UlfR
Arbeitete eine Belohnung für mich. Hatte ein 2 Jahre altes Repo mit 1.000 Commits, wurde das Repo auf einen neuen Host verschoben, so dass ein (gefürchteter) vollständiger SVN-Klon vermieden wurde.
David Victor
21

Leider funktionieren die meisten Links in diesen Antworten nicht, daher werde ich ein paar Informationen aus dem Git-Wiki duplizieren, um später darauf zurückgreifen zu können.

Diese Lösung hat bei mir funktioniert:

  • Bearbeiten Sie den svn-remote url(oder fetchPfad) in .git/config, um auf die neue Domäne / URL / den neuen Pfad zu verweisen

  • Führen Sie git aus git svn fetch. Dies muss mindestens eine neue Revision von svn abrufen!

  • Wenn Sie es git svn rebasejetzt versuchen , wird folgende Fehlermeldung angezeigt:

    Unable to determine upstream SVN information from working tree history
    

    Ich denke, das liegt daran git svn, dass die Tatsache verwirrt ist, dass Ihr letztes Commit vor dem Abruf git-svn-idauf den alten Pfad verweist, der nicht mit dem in übereinstimmt .git/config.

  • Um dieses Problem zu umgehen, ändern Sie svn-remote url(oder den fetchPfad) zurück zur ursprünglichen Domäne / URL / Pfad

  • Führen Sie nun git svn rebase -lerneut aus, um eine lokale Rebase mit den Änderungen durchzuführen, die beim letzten Abruf vorgenommen wurden. Diesmal war es wird funktionieren, offenbar , weil git svnnicht von der Tatsache verwechselt werden , dass die git-svn-idvon dem neuen Leiter nicht mit vorgefundener passt in .git/config.

  • Schließlich ändern svn-remote url(oder fetchPfad) zurück auf die neue Domain / url / path

  • An dieser Stelle git svn rebasesollte wieder funktionieren!

Die Originalinformationen wurden hier gefunden .

OnkelZeiv
quelle
3

Git svn stützt sich stark auf die svn-URL. Jedes Commit, das aus svn importiert wird git-svn-id, enthält eine , die die svn-URL enthält.

Eine gültige Umzugsstrategie besteht darin, git-svn clonedas neue Repository aufzurufen und die Änderungen in diesem neuen Abschluss zusammenzuführen. Eine ausführlichere Vorgehensweise finden Sie in diesem Artikel:

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

Adam Alexander
quelle
2

git filter-branch

Dieses Skript aus einem Blogeintrag hat für mich funktioniert. Geben Sie die alte und die neue Repo-URL als Parameter an, genau wie für svn switch --relocate.

Das Skript ruft git filter-branchauf, um Subversion-URLs in den git-svn-idCommit-Nachrichten zu ersetzen , aktualisiert .git/configund aktualisiert git-svnMetadaten, indem es sie mithilfe neu erstellt git svn rebase. Während dies git svn clonemöglicherweise die robustere Lösung ist, filter-branchfunktioniert der Ansatz für große Repositorys (Stunden gegenüber Tagen) viel schneller.

#!/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
krlmlr
quelle
1

git_fast_filter

Noch schneller als git-filter-branch(dh Minuten statt Stunden), aber im Geiste ähnlich, ist zu verwenden git_fast_filter. Dies erfordert jedoch etwas mehr Codierung, und es gibt keine saubere, fertig verpackte Lösung. Im Gegensatz git-filter-branchdazu wird dadurch ein neues Repo aus einem alten erstellt . Es wird angenommen, dass dies masterauf das letzte SVN-Commit verweist.

  1. Klon git_fast_filteraus dem Gitorious Repo.
  2. Erstellen Sie ein Python-Skript in demselben Verzeichnis, in das Sie git_fast_filterbasierend auf diesem Gist geklont haben , und setzen Sie das ausführbare Bit mit chmod +x. Passen Sie alte und neue Repository-Pfade an. (Der Inhalt des Skripts wird ebenfalls unten eingefügt.)
  3. Initialisieren Sie ein neues Ziel-Repository mit git initund ändern Sie das Arbeitsverzeichnis in dieses neue Repo.
  4. Führen Sie die folgende Pipe aus:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Kopieren Sie .git/configmöglicherweise andere relevante Dateien .git/infovom alten Repo in das neue Repo.

  6. Entfernen .git/svn.
  7. Beachten Sie git-svndie neue Zuordnung der Revisionsnummern

    1. Ausführen git branch refs/remotes/git-svn master

      • Ihre git-svn Fernbedienungen könnten als genannt unterschiedlich sein refs/remotes/git-svn, konsultieren .git/config, svn-remoteAbschnitte
    2. Ausführen git svn info. Wenn dieser Befehl einfriert, stimmt etwas nicht. Die Zuordnung der Revisionsnummern sollte neu erstellt werden.

    3. Entfernen Sie den gefälschten Zweig refs/remotes/git-svn, er wird von neu erstelltgit-svn

  8. Synchronisieren Sie durch Aufrufen git svn rebase.

Nachfolgend finden Sie den Inhalt von commit_filter.py, ersetzen Sie die Werte von IN_REPOund OUT_REPOgegebenenfalls:

#!/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()
krlmlr
quelle
0

Die obige git svn rebase -lLösung hat bei mir nicht funktioniert. Ich beschloss, es anders zu machen:

  1. Klonen Sie altes SVN-Repo in Git-Repo oldund neues SVN in Git-Reponew
  2. Holen Sie sich oldinnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newoben auf old(sollte erfolgreich sein, da die Bäume in der Wurzel newund der Spitze von oldidentisch sind)
    • git checkout master(Angenommen, der masterZweig zeigt auf den SVN-Kopf. Dies ist bei einem sauberen Klon der Fall. Andernfalls müssen Sie vor dem Start einen Commit durchführen.)
    • git rebase --root --onto old
  4. Erstellen Sie die git-svn-Metadaten von neu new, um die Rebase zu berücksichtigen
    • git update-ref --no-deref refs/remotes/git-svn master(stellen Sie den Remote - ref je nachdem , wie Sie geklont, zum Beispiel könnte es sein refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info
Ben Challenor
quelle
1. Beginnen Sie mit einem neuen Klon des neuen Standorts auf neu? Wenn ja, warum sind Sie zu diesem Zeitpunkt noch nicht fertig? 2. Wenn Sie neu auf alt zurücksetzen, erwähnen Ihre alten Festschreibungen alle die alte URL in ihrem Eintrag für das Festschreibungsprotokoll svn-id? 3. Gibt es eine Dokumentation, die zum Entfernen von .git / svn gespeichert werden kann? (3b: Welcher Befehl erstellt die Git-SVN-Metadaten neu, Git-SVN-Informationen?)
Micha Wiedenmann
0

Basierend auf einigen anderen Antworten auf diese Frage habe ich ein Ruby-Skript entwickelt, das das Verschieben von git-svn behandelt. Sie finden es unter https://gist.github.com/henderea/6e779b66be3580c9a584 .

Es behandelt das Verschieben, ohne eine andere Kopie auszuchecken, und es behandelt sogar den Fall, dass es in einem oder mehreren Zweigen nicht gedrückte Änderungen gibt (da dies die reguläre Logik verletzt). Es werden Inhalte aus der Git-Filter-Zweig-Antwort (für die Hauptlogik) und der Antwort zum Kopieren von Zweigen von einer Instanz des Repos in eine andere (zum Kopieren von Zweigen mit nicht übertragenen Änderungen) verwendet.

Ich habe dies verwendet, um eine Reihe von Git-SVN-Repos zu verschieben, die ich für die Arbeit habe, und diese Version des Skripts (ich habe unzählige Iterationen durchlaufen) scheint für mich zu funktionieren. Es ist nicht superschnell, aber es scheint alle Fälle zu behandeln, auf die ich gestoßen bin, und führt zu einem vollständig verlagerten Repo.

Das Skript bietet Ihnen die Möglichkeit, eine Kopie des Repos zu erstellen, bevor Sie Änderungen vornehmen. Mit dieser Option können Sie ein Backup erstellen. Das Erstellen einer Kopie ist erforderlich, wenn Sie Änderungen in einem Zweig nicht verschoben haben.

Das Skript verwendet keine Edelsteine ​​oder andere Bibliotheken, die nicht in der normalen MRI Ruby-Installation enthalten sind. Es werden die in der MRT enthaltenen Bibliotheken readline und fileutils verwendet.

Hoffentlich wird sich mein Skript für jemand anderen als nützlich erweisen. Fühlen Sie sich frei, Änderungen am Skript vorzunehmen.

HINWEIS: Ich habe dieses Skript nur mit Git 2.3.0 / 2.3.1 und Ruby 2.2.0 unter OS X 10.10 Yosemite getestet (da dies die von mir verwendete Umgebung ist), aber ich würde erwarten, dass es auch in anderen Umgebungen funktioniert. Keine Garantie für Windows.

Eric Henderson
quelle