Wie erzähle ich git-svn von einem Remote-Zweig, der nach dem Abrufen des Repos erstellt wurde?

193

Ich arbeite mit git-svndem zentralen Subversion-Repository meines Unternehmens. Wir haben kürzlich einen neuen Feature-Zweig im zentralen Repo erstellt.

Wie erzähle ich Git davon? Wenn ich starte, git branch -rkann ich nur die Zweige sehen, die vorhanden waren, als ich fetchgegen das Subversion-Repo lief, um mein Git-Repo zu initialisieren.

Hank Gay
quelle
Antworten von hier: stackoverflow.com/questions/13376917/… könnten ebenfalls nützlich sein.
Tomasz Gandor

Antworten:

294

Sie können den Remote-Zweig manuell hinzufügen.

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch
Vjangus
quelle
3
Fügen
Sie
1
In .git / config ist leicht zu verstehen, wie Remote-Zweige aus einzelnen / mehreren Repositorys konfiguriert werden können.
Mikael Lepistö
6
Wenn ich das achtmal positiv bewerten könnte, würde ich es tun. Endlich eine Möglichkeit, einen SVN-Zweig hinzuzufügen, der an einem nicht standardmäßigen Speicherort hinzugefügt wurde!
Tim Keating
7
Ich komme fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.zum Git-Checkout-Schritt.
Phpguru
17
@phpguru Versuchen Sie, das Optionsflag -t zu entfernen, damit es zu "git checkout -b local-newbranch newbranch" wird. Vergessen Sie nicht, das Präfix der Fernbedienung für newbranch (z. B. origin / newbranch) anzugeben.
mj1531
96

Wenn Sie ALLE Remote-SVN-Zweige verfolgen möchten, ist die Lösung so einfach wie:

git svn fetch

Dadurch werden ALLE Remote-Zweige abgerufen, die noch nicht abgerufen wurden.

Zusätzlicher Tipp: Wenn Sie zuerst nur den Trunk ausgecheckt haben und später ALLE Zweige verfolgen möchten, bearbeiten Sie ihn .git/configwie folgt und führen Sie ihn erneut aus git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Die wichtigsten Punkte sind urlsollten in das Repository Fußpunkt und die Pfade definiert fetchund branchessollte relativ sein url.

Wenn Sie nur bestimmte Zweige anstelle von ALL abrufen möchten, finden Sie ein schönes Beispiel in git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

Bei älteren Versionen von git-svnkönnen Sie nach Angabe solcher Zweige möglicherweise keine neuen Zweige mehr erhalten git svn fetch. Eine Problemumgehung besteht darin, weitere fetchZeilen wie folgt hinzuzufügen :

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Eine weitere Problemumgehung von @AndyEstes: Bearbeiten .git/svn/.metadataund ändern Sie den Wert von branches-maxRevoder tags-maxRevin eine Revision, bevor neu angegebene Zweige oder Tags erstellt wurden. Führen Sie anschließend git svn fetchden neuen SVN-Remote-Zweig aus , um ihn zu verfolgen.

Janos
quelle
1
Wenn Sie bereits die Revision abgerufen haben, zu der die SVN-Verzweigung durchgeführt wurde, bevor Sie diese Einstellungen vorgenommen haben, möchten Sie möglicherweise den Git-SVN-Reset durchführen.
kcm1700
3
Die Bearbeitung .git/svn/.metadatawar sehr hilfreich! Ich habe zusätzliche Zweige in meinen hinzugefügt .git/config, die git svn fetchnicht aufgegriffen wurden - weil die Versionsnummer der Metadaten "zu weit voraus" war. In einem Fall wurde nur das letzte Commit von einem Zweig abgerufen. Ich habe den fehlerhaften Zweig manuell entfernt (umbenannt .git/svn/refs/remotes/svn/qa/XYZin .git/svn/refs/remotes/svn/qa/XYZ~, hat seine Existenz gelöscht .git/packed-refsusw.) ... habe eine "frühere" Revisionsnummer für die Metadaten ausgewählt ... lief, git svn fetchum endlich einen vollständigen Verlauf mit korrektem, verbundenem Diagramm zu erhalten.
Starlocke
8
Dies sollte die akzeptierte Antwort sein! @janos, du hast mir gerade Stunden Kopfschmerzen erspart! Wenn Sie jemals nach Indien kommen, nehme ich Sie mit auf ein Bier!
Roopesh Shenoy
1
Oder : git svn fetch --all.
Kenorb
1
Diese Antwort ist erstaunlich, weil sie ungefähr 7 Fragen beantwortet, auf die ich keine Antworten finden konnte, und dies ohne eine 6-seitige Erzählung zu schreiben.
Droj
53

Es scheint, ich musste es nur tun git svn fetch; Irgendwie hatte ich mich davon überzeugt, dass das gesamte Repo statt nur der Änderungen abgerufen werden würde.

Hank Gay
quelle
7
@mitjak Warum ist es nicht die richtige Antwort, wenn es die Lösung ist? Ich verstehe die Subtilität der Antwort nicht.
Rholmes
'eine Lösung' vielleicht nicht 'die Lösung'
slf
1
@rholmes: Ich bin mir ziemlich sicher, dass Mitjak bedeutet, dass dies die Lösung für Ihr Problem ist, aber nicht die Antwort auf die Frage, die Sie gestellt haben. (Weil Sie die falsche Frage gestellt haben; als Sie das Problem zu der Zeit falsch interpretiert haben.)
Mike Nelson
Dies funktioniert, wenn zu dem Zeitpunkt, als Sie das SVN-Repository in Git geklont haben, ein Zweig vorhanden war. Es funktioniert nicht, wenn danach eine Verzweigung im SVN-Repository erstellt wurde.
Petr Gladkikh
3
Es funktioniert gut, wenn der Zweig nach dem Klon erstellt wurde. Ich mache es die ganze Zeit.
Tim Gautier
15

Vielleicht habe ich es irgendwie vermasselt, aber ich habe die Anweisungen in Vjangus 'Antwort befolgt und es hat fast funktioniert. Das einzige Problem war, dass Newbranch nicht vom Stamm abgezweigt zu sein schien. In gitk war es eine Art "Schweben" für sich allein; es hatte keinen gemeinsamen Vorfahren mit dem Stamm.

Die Lösung dafür war:

  1. Suchen Sie den SHA1 des letzten Commits, der auf dem Trunk stattgefunden hat, bevor der Zweig erstellt wurde.
  2. Suchen Sie den SHA1 des ersten Commits für den neuen Zweig (die Nachricht lautet wahrscheinlich "Neuer Zweig erstellt, von Trunk @ 12345 kopiert" oder so).
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- Es sollte keine Ausgabe erfolgen. Wenn eine Ausgabe erfolgt, haben Sie möglicherweise die falschen Commits ausgewählt.
  4. git checkout local-newbranchdann git rebase <sha1 from step 1>. Dies wird local-newbranchauf den neuen Baum zurückgesetzt, aber remotes/newbranchimmer noch getrennt.
  5. Gehen Sie zu der Datei .git/refs/remotes/newbranchund bearbeiten Sie sie so, dass sie den vollständigen SHA1 des neuen Commits (auf dem neu basierten newbranch) enthält, der dem alten Commit entspricht, auf das er gerade zeigt. (Oder vielleicht verwenden git-update-ref refs/remotes/newbranch <new-SHA>. Danke Inger.)
  6. Wenn Sie das nächste Mal git svn dcommitdazu kommen newbranch, erhalten Sie eine Reihe von Nachrichten darüber, wie Sie ein Protokoll aktualisieren. Das ist normal, denke ich.

Ich empfehle, gitk --alldie ganze Zeit offen zu bleiben und es häufig zu aktualisieren, um zu verfolgen, was Sie tun. Ich bin noch ein bisschen neu bei git und git svn, also schlagen Sie bitte Verbesserungen für diese Methode vor.

MatrixFrog
quelle
2
Danke, das klingt nützlich. Ungefähr 5. Wahrscheinlich ist 'git-update-ref refs / remotes / newbranch <new-SHA>' die sicherere Option.
Inger
Ich habe es gerade noch einmal mit Vjangus versucht und es hat perfekt funktioniert. Ich werde das hier sowieso lassen, da es für jemanden wertvoll sein könnte ...
MatrixFrog
1
Die vjangus-Lösung erstellt immer den neuen Zweig, der vom Trunk getrennt ist. Ich gehe davon aus, dass dies daran liegt, dass SVN selbst keine Ahnung hat, wie der eigentliche Inhalt kopiert wird.
Bogdan.mustiata
Meine Erfahrung mit einem großen Git-SVN-Repo ist, dass SVN-Zweige immer in Git erstellt werden, das vom Stamm getrennt ist. Es sollte einen Weg geben, sie zu verbinden, aber ich habe mir nicht die Zeit genommen, es herauszufinden. AFAIK, Sie können den Git-Zweig, der mit dem SVN-Zweig verbunden ist, nicht neu gründen, da dies die Dcommit-Logik durcheinander bringt. Wir haben gerade gelernt, damit zu leben.
Spencer
7

Eine Vereinfachung der Antwort von Vjangus:

Wenn Sie das Standardlayout in SVN verwenden und den üblichen svn-Init ausgeführt haben, übernimmt git-svn die Konfiguration für Sie. Gerade:

  1. Suchen Sie nach einer Überarbeitung der Zweigkopie in SVN
  2. Holen Sie sich diese Revision mit git-svn
  3. Erstellen Sie eine neue lokale Zweigstellenverfolgungsfernbedienung

Ein Beispiel. SVN URL ist svn+ssh://[email protected]/repo. SVN-Zweig, den ich suche, ist newbranch. Lokaler Git-Zweig (Tracking-Fernbedienung newbranch) wird sein git-newbranch.

Schritt 1: Suchen Sie die Zweigkopie-Revision

    # svn log --stop-on-copy svn + ssh: //[email protected]/repo/branches/newbranch | Schwanz -4
    r7802 | jemand | 2014-03-21 18:54:58 +0000 (Fr, 21. März 2014) | 1 Zeile

    KOPF nach Newbranch verzweigen
    -------------------------------------------------- ----------------------

Der Verzweigungspunkt in SVN ist also Revision 7802.

Schritt 2: Holen Sie sich die Revision

    # git svn fetch -r 7802
    Möglicher Verzweigungspunkt gefunden: svn + ssh: //[email protected]/repo/trunk => svn + ssh: //[email protected]/repo/branches/newbranch, 7801
    Gefundener übergeordneter Zweig: (refs / remotes / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Folgender Elternteil mit do_switch
    Erfolgreich gefolgt Eltern
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / remotes / newbranch)

git-svn hat die ganze Arbeit gemacht und weiß jetzt über die Fernbedienung Bescheid:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / remotes / newbranch

Schritt 3: Erstellen Sie Ihren neuen lokalen Zweig, der den entfernten Zweig verfolgt:

    # git checkout -b git-newbranch -t newbranch
    Dateien auschecken: 100% (413/413), fertig.
    Zweigstelle git-newbranch eingerichtet, um lokale Ref-Refs / Fernbedienungen / Newbranch zu verfolgen.
    Wechsel zu einer neuen Filiale 'git-newbranch'
Gil Hamilton
quelle
Danach konnte ich endlich verstehen ( show-refist von unschätzbarem Wert)! Für alle, die nicht in der Lage sind, Remote-Zweige falsch zu referenzieren, können Sie diese löschen (ich musste das Referenzverzeichnis git branch -d newbranchentfernen und dann erzwingen .git/svn/refs/remotes/newbranch) und dann bei Schritt 2 (oben) von vorne beginnen.
TutuDajuju
5

Ich habe keine Dokumentation zu dieser Funktion gefunden, aber es sieht so aus, als ob die git svn-Konfiguration mehrere Abrufeinträge unterstützt. Auf diese Weise können Sie Zweige auch separat hinzufügen, ohne dass Sie Ihrer Konfiguration einen weiteren Remote-SVN-Repository-Eintrag hinzufügen oder Platzhalter verwenden müssen, um alle Zweige eines bestimmten Verzeichnisses abzurufen.

Angenommen, Ihr SVN-Baum ist wirklich böse und hat viele Verzweigungen ohne Logik, wie sie sich befinden, z. B. Verzweigungen und Unterverzeichnisse mit mehr Verzweigungen.

dh

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

und Sie möchten nur einige der Zweige auswählen, die in Ihr Git-Repository aufgenommen werden sollen.

Sie können Ihr Repository zunächst nur mit Trunk ohne zusätzliche Zweige starten:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

Danach sollten Sie folgende Konfiguration sehen:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

Wann immer Sie einen neuen Zweig von MyRepo abrufen möchten, können Sie der Konfiguration einfach neue Abrufeinträge hinzufügen, indem Sie:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

Oder Sie können dieselbe Konfiguration in .git / config bearbeiten

Um die neuen Zweige nach dem Hinzufügen zur Konfiguration abzurufen, führen Sie einfach Folgendes aus:

git svn fetch -r 10000:HEAD

[Bearbeiten] Manchmal scheint es notwendig zu sein, fetch mit dem Parameter --all auszuführen, um neu hinzugefügte Zweige abzurufen:

git svn fetch --all -r 10000:HEAD
Mikael Lepistö
quelle
4

Anstatt sich mit den Macken von git-svn zu befassen, können Sie SubGit ausprobieren .

Man muss SubGit im Subversion-Repository installieren. Danach kann man den Standard-Git-Workflow verwenden, anstatt spezielle git-svn-Befehle zu verwenden:

  1. Neue Commits vorantreiben:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Eingehende Änderungen abrufen

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Neuen Zweig erstellen:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

Weitere Informationen finden Sie in der SubGit-Dokumentation .

vadishev
quelle
1
SubGit hat den Nachteil, dass es zwei Repositorys erstellt - ein SVN- und ein "Shadow" -Git-Repository. Dies könnte ein Problem für große SVN-Repositories sein ...
Udo
@Udo Wenn das SVN-Repository einige Projekte enthält, kann man nur eines davon angeben und es mit dem Git-Repository synchronisieren. In diesem Fall muss das gesamte Subversion-Repository nicht in Git konvertiert werden. Wenn sich jedoch ein großes SVN-Projekt in diesem Repository befindet, wird möglicherweise nicht der gesamte Verlauf dieses Repositorys konvertiert, sondern der Verlauf ab einer minimalen Überarbeitung. Dies ermöglicht es, die Größe des übersetzten Git-Repositorys zu verringern.
Vadishev
1
@Udo - Jedes Unternehmen, das nicht bereit ist, seinem Repository-Server eine Festplatte zu kaufen, hat seine Prioritäten durcheinander gebracht. Aber die meisten Orte mit riesigen Repositorys nehmen ihre Repositorys ziemlich ernst, und der Speicherplatzbedarf für Repositorys ist im Allgemeinen kein großes Problem, selbst für Unternehmen mit jahrzehntelanger Geschichte und zig Millionen Codezeilen und Hunderttausenden von Revisionen. Es ist die konkreteste Form des Unternehmens für sein geistiges Kernvermögen, und der Speicherplatz ist ziemlich kostengünstig. Es könnte die Notwendigkeit eines Upgrades eines RAID-Controllers auslösen, aber dennoch der Produktivitätsgewinn ...
Bob Kerns
@ Bob Kerns - Der Punkt ist, dass "Größe weise" SVN und Git und nicht kompatibel. Es geht nicht um Speicherplatz oder so. Sie können jedoch mit einem riesigen SVN-Repository arbeiten, da Sie normalerweise nur wenige Dateien / Projekte auschecken müssen. Aber du kannst kein riesiges Git-Repository klonen - es macht zumindest keinen Spaß ;-) Mit "riesig" meine ich mehrere Gigs.
Udo
2

Um die Antwort von vjangus zu ergänzen, die mir geholfen hat, fand ich es auch nützlich, Git-Transplantate hinzuzufügen, um die Zweige an der entsprechenden Stelle an den Stamm zu binden - damit Git den Verlauf sehen und Zusammenführungen korrekt durchführen kann.

Dies ist einfach ein Fall des Hinzufügens einer Zeile .git/info/graftsmit den Hashes:

<initial branch commit> <parent commit in trunk>

z.B.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Gutschrift an http://evan-tech.livejournal.com/255341.html

(Ich würde dies als Kommentar hinzufügen, aber ich habe nicht genug Ruf.)

Haddon CD.
quelle
0

Wenn Sie nicht mit einem gültigen Layout auschecken, können Sie keinen Remote-Zweig auschecken.

Das ist was ich mache:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

Danach können Sie zu einem Remote-Zweig wechseln:

git checkout --track -b branch_name branch_name

Dann werden Sie automatisch zu Ihrer Filiale gewechselt.

MikeHoss
quelle