Meine Motivation, git-svn auszuprobieren, ist das mühelose Zusammenführen und Verzweigen. Dann bemerkte ich, dass Mann git-svn (1) sagt:
Das Ausführen von Git-Merge oder Git-Pull wird NICHT für einen Zweig empfohlen, von dem aus Sie einen Commit durchführen möchten. Subversion stellt keine Zusammenführungen in angemessener oder nützlicher Weise dar; Daher können Benutzer, die Subversion verwenden, keine von Ihnen vorgenommenen Zusammenführungen sehen. Wenn Sie einen Git-Zweig zusammenführen oder daraus ziehen, der ein Spiegel eines SVN-Zweigs ist, wird dcommit möglicherweise auf den falschen Zweig festgeschrieben.
Bedeutet dies, dass ich keinen lokalen Zweig aus svn / trunk (oder einem Zweig) erstellen, weghacken, wieder in svn / trunk zusammenführen und dann dcommit kann? Ich verstehe, dass SVN-Benutzer das gleiche Durcheinander sehen werden, das in SVN vor 1.5.x zusammengeführt wurde, aber gibt es noch andere Nachteile? Dieser letzte Satz macht mir auch Sorgen. Tun Menschen solche Dinge routinemäßig?
--mergeinfo=<mergeinfo>
Option, mit der Zusammenführungsinformationen möglicherweise an den SVN übergeben werden können. Ich bin mir nicht sicher, wie es verwendet werden soll.Antworten:
Eigentlich habe ich mit der
--no-ff
Option zum Zusammenführen von Git einen noch besseren Weg gefunden . All diese Squash-Technik, die ich zuvor verwendet habe, ist nicht mehr erforderlich.Mein neuer Workflow lautet jetzt wie folgt:
Ich habe einen „Master“ Zweig, der der einzige Zweig ist , dass ich aus und das Klon der SVN - Repository dcommit (
-s
vorausgesetzt , dass Sie haben ein Standard - SVN - Layout im Repositorytrunk/
,branches/
undtags/
):Ich arbeite an einer lokalen Niederlassung "Arbeit" (
-b
erstellt die Niederlassung "Arbeit")Commit lokal in den Zweig "work" (
-s
um Ihre Commit-Nachricht abzumelden). In der Folge gehe ich davon aus, dass Sie 3 lokale Commits gemacht habenJetzt möchten Sie sich auf den SVN-Server festlegen
Verstecken Sie [eventuell] die Änderungen, die auf dem SVN-Server nicht festgeschrieben werden sollen (häufig haben Sie Code in der Hauptdatei kommentiert, nur weil Sie die Kompilierung beschleunigen und sich auf eine bestimmte Funktion konzentrieren möchten).
Basis des Hauptzweigs mit dem SVN-Repository neu erstellen (zum Aktualisieren vom SVN-Server)
Gehen Sie zurück zum Arbeitszweig und starten Sie den Master erneut
Stellen Sie sicher, dass alles in Ordnung ist, zum Beispiel:
Jetzt ist es an der Zeit, alle drei Commits aus dem Zweig "work" mit dieser wunderbaren
--no-ff
Option in "master" zusammenzuführenSie können den Status der Protokolle feststellen:
Jetzt möchten Sie wahrscheinlich
amend
das letzte Commit für Ihre SVN-Typen bearbeiten ( ) (andernfalls wird nur ein einziges Commit mit der Meldung "Zweig 'Arbeit' zusammenführen" angezeigt.Zum Schluss auf dem SVN-Server festschreiben
Machen Sie sich wieder an die Arbeit und stellen Sie schließlich Ihre versteckten Dateien wieder her:
quelle
--no-ff
Option erstellen Sie explizit ein Zusammenführungs-Commit (ein Commit mit zwei übergeordneten Elementen) anstelle eines schnellen Vorlaufs. Um sicherzustellen, dass alle Commits im SVN-Tracking-Zweig Single-Parent-Commits sind, müssen alle Merges entweder schnell vorgespult werden (--ff-only
kann dabei helfen) oder, wenn sich der Trunk hinter Ihrem Rücken geändert hat, a--squash
, richtig?git svn dcommit
das von Ihnen angegebene Git-Commit neu schreiben. Dies bedeutet, dass Sie das andere übergeordnete Element verlieren und Ihr Git-Repo jetzt keinen Datensatz mehr hat, in den Sie diesen Zweig jemals zusammengeführt habenmaster
. Dies kann auch dazu führen, dass Ihr Arbeitsverzeichnis in einem inkonsistenten Zustand bleibt.git merge --no-ff work -m "commit message"
anstelle eines zusätzlichengit commit --amend
SchrittesDas Erstellen lokaler Filialen ist mit git-svn definitiv möglich. Solange Sie nur lokale Zweige für sich selbst verwenden und nicht versuchen, git zum Zusammenführen zwischen vorgelagerten SVN-Zweigen zu verwenden, sollte es Ihnen gut gehen.
Ich habe einen "Master" -Zweig, mit dem ich den SVN-Server verfolge. Dies ist der einzige Zweig, aus dem ich mich verpflichte. Wenn ich etwas arbeite, erstelle ich einen Themenzweig und arbeite daran. Wenn ich es festschreiben möchte, mache ich Folgendes:
Ich habe auch eine andere Situation, in der ich einige lokale Änderungen (zum Debuggen) beibehalten muss, die niemals auf svn übertragen werden sollten. Dafür habe ich den oben genannten Hauptzweig, aber auch einen Zweig namens "Arbeit", in dem ich normalerweise arbeite. Themenzweige werden von der Arbeit abgezweigt. Wenn ich dort Arbeit festschreiben möchte, checke ich den Master aus und verwende Cherry-Pick, um die Festschreibungen aus dem Arbeitszweig auszuwählen, den ich für svn festschreiben möchte. Dies liegt daran, dass ich vermeiden möchte, die drei lokalen Änderungs-Commits festzuschreiben. Dann verlasse ich mich von der Hauptniederlassung und stütze alles neu.
Es lohnt sich,
git svn dcommit -n
zuerst zu laufen , um sicherzustellen, dass Sie genau das festlegen, was Sie festlegen möchten. Im Gegensatz zu Git ist es schwierig, die Geschichte in SVN neu zu schreiben!Ich bin der Meinung, dass es einen besseren Weg geben muss, die Änderung in einem Themenzweig zusammenzuführen, während diese lokalen Änderungszusagen übersprungen werden, als Cherry Pick zu verwenden. Wenn also jemand Ideen hat, wäre er willkommen.
quelle
Einfache Lösung: Entfernen Sie nach dem Zusammenführen den Zweig "Arbeit"
Kurze Antwort: Sie können git verwenden, wie Sie möchten (siehe unten für einen einfachen Workflow), einschließlich Zusammenführen. Stellen Sie einfach sicher, dass Sie jeder ' Git Merge Work ' mit ' Git Branch -d Work ' folgen , um den temporären Arbeitszweig zu löschen.
Hintergrunderklärung: Das Problem beim Zusammenführen / Festschreiben besteht darin, dass der Zusammenführungsverlauf dieses Zweigs immer dann, wenn Sie einen Zweig "git svn dcommit" ausführen, "abgeflacht" wird: git vergisst alle Zusammenführungsvorgänge, die in diesen Zweig ausgeführt wurden: Nur der Dateiinhalt bleibt erhalten. Die Tatsache, dass dieser Inhalt (teilweise) aus einem bestimmten anderen Zweig stammt, geht jedoch verloren. Siehe: Warum verliert git svn dcommit die Historie der Zusammenführungs-Commits für lokale Niederlassungen?
(Hinweis: Es gibt nicht viel, was git-svn dagegen tun könnte: svn versteht die viel leistungsstärkeren Git-Zusammenführungen einfach nicht. Daher können diese Zusammenführungsinformationen im svn-Repository in keiner Weise dargestellt werden.)
Aber das ist das ganze Problem. Wenn Sie den Zweig 'work' löschen, nachdem er mit dem Zweig 'master' zusammengeführt wurde, ist Ihr Git-Repository zu 100% sauber und sieht genauso aus wie Ihr SVN-Repository.
Mein Workflow: Natürlich habe ich zuerst das Remote-SVN-Repository in ein lokales Git-Repository geklont (dies kann einige Zeit dauern):
Alle Arbeiten finden dann im "lokalen Verzeichnis" statt. Wann immer ich Updates vom Server erhalten muss (wie 'svn update'), mache ich:
Ich mache alle meine Entwicklungsarbeiten in einem separaten Zweig 'Arbeit', der wie folgt erstellt wird:
Natürlich können Sie so viele Zweige für Ihre Arbeit erstellen, wie Sie möchten, und sie zusammenführen und neu erstellen, wie Sie möchten (löschen Sie sie einfach, wenn Sie damit fertig sind - wie unten beschrieben). In meiner normalen Arbeit verpflichte ich mich sehr häufig:
Der nächste Schritt (git rebase -i) ist optional - es wird nur der Verlauf bereinigt, bevor er auf svn archiviert wird: Sobald ich einen stabilen Meilenstein erreicht habe, den ich mit anderen teilen möchte, schreibe ich den Verlauf dieser 'Arbeit' neu. Verzweigen und bereinigen Sie die Commit-Nachrichten (andere Entwickler müssen nicht alle kleinen Schritte und Fehler sehen, die ich unterwegs gemacht habe - nur das Ergebnis). Dafür mache ich
und kopieren Sie den sha-1-Hash des letzten Commits, der im svn-Repository aktiv ist (wie durch eine git-svn-id angegeben). Dann rufe ich an
Fügen Sie einfach sha-1 Hash unseres letzten svn Commits anstelle von meinem ein. Weitere Informationen finden Sie in der Dokumentation mit 'git help rebase'. Kurz gesagt: Dieser Befehl öffnet zuerst einen Editor, der Ihre Commits präsentiert ---- Ändern Sie einfach 'pick' in 'squash' für alle Commits, die Sie mit vorherigen Commits quetschen möchten. Natürlich sollte die erste Zeile als "Auswahl" bleiben. Auf diese Weise können Sie Ihre vielen kleinen Commits zu einer oder mehreren sinnvollen Einheiten zusammenfassen. Speichern Sie den Editor und beenden Sie ihn. Sie werden von einem anderen Editor aufgefordert, die Commit-Protokollnachrichten neu zu schreiben.
Kurz gesagt: Nachdem ich das 'Code-Hacken' beendet habe, massiere ich meinen 'Arbeits'-Zweig, bis er so aussieht, wie ich ihn den anderen Programmierern präsentieren möchte (oder wie ich die Arbeit in ein paar Wochen sehen möchte, wenn ich den Verlauf durchsuche). .
Um die Änderungen in das SVN-Repository zu übertragen, gehe ich wie folgt vor:
Jetzt sind wir wieder im alten 'Master'-Zweig, der mit allen Änderungen aktualisiert wurde, die in der Zwischenzeit im svn-Repository vorgenommen wurden (Ihre neuen Änderungen sind im' Arbeits'-Zweig versteckt).
Wenn es Änderungen gibt, die mit Ihren neuen "Arbeits" -Änderungen in Konflikt geraten können, müssen Sie diese lokal auflösen, bevor Sie Ihre neue Arbeit verschieben können (siehe Details weiter unten). Dann können wir unsere Änderungen auf svn übertragen:
Hinweis 1: Der Befehl 'git branch -d work' ist ziemlich sicher: Er ermöglicht nur das Löschen von Zweigen, die Sie nicht mehr benötigen (da diese bereits in Ihrem aktuellen Zweig zusammengeführt sind). Wenn Sie diesen Befehl versehentlich ausführen, bevor Sie Ihre Arbeit mit dem Zweig 'master' zusammenführen, wird eine Fehlermeldung angezeigt.
Hinweis 2: Stellen Sie sicher, dass Sie Ihren Zweig mit 'git branch -d work' zwischen Zusammenführen und dcommit löschen: Wenn Sie versuchen, den Zweig nach dcommit zu löschen, wird eine Fehlermeldung angezeigt: Wenn Sie 'git svn dcommit' ausführen, vergisst git dies Ihr Zweig wurde mit 'master' zusammengeführt. Sie müssen es mit 'git branch -D work' entfernen, das die Sicherheitsüberprüfung nicht durchführt.
Jetzt erstelle ich sofort einen neuen 'Arbeits'-Zweig, um ein versehentliches Hacken des' Master'-Zweigs zu vermeiden:
Integrieren Ihrer 'Arbeit' in Änderungen an svn: Folgendes mache ich, wenn 'git svn rebase' zeigt, dass andere das svn-Repository geändert haben, während ich an meinem Zweig 'Arbeit' gearbeitet habe:
Es gibt leistungsfähigere Lösungen: Der vorgestellte Workflow ist simpel: Er nutzt die Möglichkeiten von git nur in jeder Runde von 'update / hack / dcommit' - lässt jedoch die langfristige Projekthistorie genauso linear wie das svn-Repository. Dies ist in Ordnung, wenn Sie Git-Merges nur in kleinen ersten Schritten in einem älteren SVN-Projekt verwenden möchten.
Wenn Sie mehr vertraut mit git Verschmelzung werden, können Sie andere Workflows erkunden: Wenn Sie wissen , was Sie tun, Sie können git verschmilzt mit svn verschmilzt mischen ( git-svn (oder ähnlich) nur mit svn merge zu helfen? )
quelle
git merge --squash work
, warum nicht? Ich kann sehen, wie Squash-Commits in der Verzweigung vor dem Zusammenführen ausgeführt werden, wenn Sie mehr als eine Auswahl erstellen (sagen wir, Sie haben 8 Commits und verwandeln jedes von 4 Commits in 1 und führen 2 Commits zum Master zusammen). Auch wenn ich meinen 'rebase
Greg Hewgill Antwort oben ist nicht sicher! Wenn zwischen den beiden "git svn rebase" neue Commits im Trunk angezeigt werden, erfolgt die Zusammenführung nicht schnell.
Dies kann sichergestellt werden, indem das Flag "--ff-only" für die Git-Zusammenführung verwendet wird. Normalerweise führe ich jedoch nicht "git svn rebase" in der Verzweigung aus, sondern nur "git rebase master" (vorausgesetzt, es handelt sich nur um eine lokale Datei) Ast). Danach ist ein "git merge thebranch" garantiert schnell vorwärts.
quelle
Ein sicherer Weg, um svn-Zweige in git zusammenzuführen, ist die Verwendung von git merge --squash. Dadurch wird ein einzelnes Commit erstellt und das Hinzufügen einer Nachricht gestoppt.
Angenommen, Sie haben einen Themen-SVN-Zweig namens SVN-Zweig.
Zu diesem Zeitpunkt haben Sie alle Änderungen aus dem SVN-Zweig in einem Commit zusammengefasst, das im Index wartet
quelle
Setzen Sie den lokalen Git-Zweig auf den Master-Git-Zweig und dann auf dcommit um. Auf diese Weise haben Sie anscheinend alle diese Commits nacheinander ausgeführt, sodass SVN-Benutzer ihn linear sehen können, wie sie es gewohnt sind. Angenommen, Sie haben einen lokalen Zweig namens Thema, den Sie tun könnten
Das wird dann Ihre Commits über den Hauptzweig abspielen, damit Sie sie festschreiben können
quelle