Ich versuche, zwei Zweige mit Binärdateien in Git zu haben – einen “Entwicklung” und einen “Stabil”. Der Entwicklungszweig kann mehrere Änderungen dieser Dateien haben, bevor ich sie für den Stable-Zweig “freigeben” möchte (und der Stable-Zweig hat diese Dateien umbenannt, falls dies relevant ist).
Ich könnte eine normale Zusammenführung durchführen, dies funktioniert gut, bewahrt aber zu viel Verlauf – wenn der Zweig “stabil” gezogen wird, werden alle Zwischen-Commits aus dem Zweig “Entwicklung” ebenfalls gezogen (weil sie übergeordnete Commits sind). Aber wir sprechen von Binärdateien, die keine vernünftige Zusammenführungsstrategie haben (außer ihrer/unserer), also ist die tatsächliche Geschichte der Dateien im Entwicklungszweig nutzlos. Wenn ich den “Stable”-Zweig ziehe, bekomme ich Folgendes:
X-------------------G stable
/ /
a---b---c---d---e---f---g development
Da G ein übergeordnetes Element im Entwicklungszweig hat, bekomme ich die gesamte Historie des Entwicklungszweigs (Datenobjekte für c, d, e, f und g) in meinem Repository, was mich nicht interessiert (X ist dasselbe wie b, mit einigen angewendeten Dateiumbenennungen).
Also versuchte ich es git merge --squash wechselt vom Development-Zweig zum Stable-Zweig. Das erste derartige Merge und Commit verlief OK, die Ergebnisse waren wie erwartet (nettes Änderungsprotokoll in der Commit-Nachricht, kein Bezug zum Entwicklungszweig):
X-------------------G stable
/
a---b---c---d---e---f---g development
Nachdem ich diesen gequetschten stabilen Zweig gezogen habe, bekomme ich das in mein Repository, was ich will:
a---b---X---G
Aber die zweite Zusammenführung schlug fehl (weil Git keine Möglichkeit hatte zu wissen, wie viel ich bereits zusammengeführt hatte und verwirrt war).
Ist es möglich, die Zusammenführung irgendwie aufzuzeichnen, ohne einen “Merge-Commit” mit zwei Eltern zu erstellen?
Oder ist es möglich, Git anzuweisen, nur einen bestimmten “Bereich” von Revisionen zusammenzuführen, wie in SVN?
Oder ist es möglich, eine normale Zusammenführung durchzuführen, ohne beim Pullen alle Refs aus dem anderen Zweig herunterladen zu müssen?
Oder sollte ich einen benutzerdefinierten Merge-Treiber für die betreffenden Dateien bereitstellen, der einfach “ihre” Version in “unsere” umbenennt und dadurch die Konflikte löst? Das befürchte ich immer noch --squash Ich werde immer versuchen, die gesamte Geschichte bis zum gemeinsamen Elternteil zusammenzuführen und damit nur die Hälfte meines Problems zu lösen.
Update: Rebasing
Wenn ich das Rebasing richtig verstehe, komme ich auf Folgendes:
X stable
/
a---b---c---d---e---f---g development
Dadurch bekomme ich alle Daten, die mich nicht interessieren (c, d, e, f) und als Bonus verliere ich die Information, dass b eine stabile Version im Zweig war.
Jede Entwicklungsrevision fügt der Repository-Größe etwa 5 MB hinzu (und das Neupacken des gesamten Repos schrumpft es nur um etwa 10 %), der “stable”-Zweig ist fast kostenlos (die Daten sind bereits vorhanden). Ich möchte eine einzelne neue Revision aus dem Stable-Zweig ziehen, um nur die neuen 5 MB zu ziehen, aber stattdessen lädt ein Update von X auf G 25 MB herunter, weil ich irgendwie nicht sagen kann, dass mir der Inhalt von c, d egal ist , e und f.
Beginnen mit
X stable
/
a---b---c---d---e---f---g development
Sie können die folgenden Schritte verwenden, um den letzten Commit von Ihrem Entwicklungszweig in Ihren stabilen Zweig zu kopieren:
git checkout development@{0} # get working tree from "development", detach HEAD
git reset --soft stable # reposition detached HEAD on "stable"
git commit # enter the appropriate commit message
git branch temp # create a temporary branch "temp" at HEAD
git checkout temp # get on the new temporary branch
git branch -M stable # rename "temp" to "stable"
so landest du bei:
X-------------------G stable
/
a---b---c---d---e---f---g development
Wenn Sie an “Entwicklung” weiterarbeiten, z.
X-------------------G stable
/
a---b---c---d---e---f---g---h---i---j development
Sie können dieselben Git-Befehle wie oben wiederholen und erhalten Folgendes:
X-------------------G-----------J stable
/
a---b---c---d---e---f---g---h---i---j development
Das sieht gut aus, aber ich verstehe nicht genau, warum es erforderlich ist, einen temporären Zweig zu erstellen und ihn dann umzubenennen. Liegt es daran, dass Sie nach dem Commit immer noch losgelöst sind?
– Kim Sullivan
5. Januar 2011 um 14:53 Uhr
Außerdem: Sie können Laufen finden git log --graph --oneline --all --decorate und git status an jedem Punkt entlang dieser Reihe von Befehlen informativ sein. Und/oder Betrachten des Inhalts verschiedener Dateien in .git/, vielleicht mit grep . .git/HEAD .git/refs/heads/*
– Linde
16. Februar 2011 um 21:57 Uhr
Ich liege vielleicht falsch, aber … Zurücksetzen (--soft) zu stable wird die Auswirkungen rückgängig machen X. Das richtige Ziel ist der gemeinsame Vorfahre von stable und development (git merge-base stable development).
– cYrus
30. Oktober 2011 um 19:22 Uhr
Es scheint, dass die Antwort auf meinen vorherigen Kommentar ja ist
– Herr_und_Frau_D
18. Juli 2013 um 20:31 Uhr
@cYrus: Sie liegen falsch anscheinend: “Wenn Sie sich im getrennten HEAD-Zustand befinden, bewegt git reset nur HEAD.” – HEAD wird also nach stable verschoben, aber weil --soft ausgegeben wird, bleiben der Arbeitsbaum/Index unverändert
– Herr_und_Frau_D
18. Juli 2013 um 22:44 Uhr
Artagnon
Dies ist nicht der richtige Ort, um es zu verwenden merge --squash. Ein guter Ort, um es zu verwenden, ist ein Wegwerf-Themenzweig, den Sie mit Ihrem Hauptzweig zusammenführen und dann loswerden. Die gesamte Entwicklung, die im Themenzweig durchgeführt wurde, wird als ein Commit im Hauptzweig angezeigt. In Ihrer Situation sollten Sie normalerweise aus dem Entwicklungszweig zusammenführen und dann verwenden git-rebase --interactive um die gewünschten Commits zu quetschen.
Ist es möglich, die Zusammenführung irgendwie aufzuzeichnen, ohne einen “Merge-Commit” mit zwei Eltern zu erstellen?
Wenn ich die Frage richtig verstehe, nein. Absolut nicht.
Ist es möglich, Git anzuweisen, nur einen bestimmten “Bereich” von Revisionen zusammenzuführen, wie in SVN?
Jawohl. git merge [commit hash]
Oder ist es möglich, eine normale Zusammenführung durchzuführen, ohne beim Pullen alle Refs aus dem anderen Zweig herunterladen zu müssen?
Siehe Antwort auf vorherige Frage.
Oder sollte ich einen benutzerdefinierten Merge-Treiber für die betreffenden Dateien bereitstellen, der einfach “ihre” Version in “unsere” umbenennt und dadurch die Konflikte löst? Ich befürchte immer noch, dass –squash immer versuchen wird, die gesamte Geschichte bis hin zum gemeinsamen Elternteil zusammenzuführen und nur die Hälfte meines Problems zu lösen.
Nein! Nur nicht verwenden git merge --squash. Dies ist nicht der richtige Ort, um es zu verwenden!
Danke für deine Antwort! Ich bin mir nicht sicher, ob eine Umbasierung das ist, was ich brauche. Ich muss etwas Verlauf im “stable”-Zweig aufzeichnen, damit ich zwischen “Releases” hin und her gehen kann. Das ist, was ich will: ` D -> SD | D | D -> SD | D -> S` Aber ich brauche nur die Historie aus dem S-Zweig – die Historie aus dem D-Zweig ist mir egal. Das Problem, das ich lösen muss, ist, wie ich den S-Zweig ziehen kann, ohne alle übergeordneten Refs aus dem D-Zweig zu ziehen (wenn ich es richtig verstehe, werden durch das Rebasing alle vorherigen S-Commits entfernt, was nicht das ist, was ich will). ` D -> x DDD -> x DD -> S`
– Kim Sullivan
23. September 2009 um 10:23 Uhr
Ja, ich verstehe, dass Sie den vorhandenen Verlauf aus dem S-Zweig beibehalten müssen. Nein, Rebasing löscht nicht alle vorherigen S-Commits; Beachten Sie vor dem Zusammenführen von development in stable die [commit hash] und dann git rebase -i [commit hash] – dann werden Sie effektiv nur die Commits quetschen, die Sie gerade zusammengeführt haben. Was Releases betrifft, warum nicht einfach bestimmte Commits als Releases markieren?
– artagnon
23. September 2009 um 11:43 Uhr
Es tut mir leid, dass ich Ihr D -> SD | nicht ganz verstehe D-Diagramm zu gut. Ich hoffe, mein vorheriger Kommentar hat alles klargestellt.
– artagnon
23. September 2009 um 11:44 Uhr
Ich wusste nicht, dass Kommentare keine Formatierung unterstützen, ich werde meine Frage aktualisieren.
– Kim Sullivan
23. September 2009 um 12:48 Uhr
“Aber je mehr ich darüber nachdenke, desto mehr wird mir klar, dass Git dafür einfach nicht entwickelt wurde” — Genau. Eine plausible Lösung: Entfernen Sie S. Erstellen Sie diskrete Flat-File (Tarball?)-Releases aus Tags in D. Git war nie dafür gedacht, Binärdateien zu verarbeiten.
– artagnon
23. September 2009 um 14:48 Uhr
gestrickt
Du könntest benutzen git rebase -i (interaktiver Modus), um alle Ihre Änderungen zu sqashen, ändern Sie einfach die Zeilen in m oder meld (Aktualisierung: für neuere Git-Releases type s oder squash)
Sie haben dann einen einzigen Commit, den Sie zusammenführen können. Wenn Sie möchten, dass jeder Schritt von Ihnen reserviert ist, müssen Sie einen weiteren Zweig in Ihrem Hacking-Zweig erstellen, bevor Sie die Rebase durchführen. Dies ist möglich git branch small-dirty-changes-i-don’t-want-anybody-to-see
all dies muss getan werden, bevor versucht wird zu fusionieren; Schritt für Schritt:
# on branch "hacking": hack commit hack commit hack commit
# create a reference to your history
$ git branch dirty-history
# sqash your commits by setting all lines to "meld"
$ git rebase -i
# checkout master or the branch you want to merge to
$ git checkout master
# merge your squashed commit
$ git merge hacking
# or: $ git pull hacking
Hm, ich könnte die Änderungen wahrscheinlich hin und wieder auf den Entwicklungszweig (“dirty”) umbasieren (eigentlich vor dem Mergen zu Stable und Release), also habe ich nicht all diese Zwischenbinärdateien, die mir nicht viel ausmachen. Das einzig Wichtige zwischen Stable-Releases ist der Hash und die Commit-Meldungen… Der Hash ist wichtig zum Testen (welcher Build getestet wurde und welcher nicht). Ich muss noch etwas darüber nachdenken.
– Kim Sullivan
24. September 2009 um 7:50 Uhr
gute Antwort, ich denke, “meld” bedeutet heutzutage “Squash” (Ihre Antwort stammt von 2009!)
– R Yoda
3. Dezember 2017 um 17:15 Uhr
Ja, es ist jetzt s/squash.
– Strickl
3. Dezember 2017 um 17:21 Uhr
Raghu Dodda
Die am besten bewertete Antwort unterscheidet effektiv den Stable- und den Development-Zweig und wendet alle im Stable fehlenden Änderungen als einen Commit an. Es gibt eine alternative Möglichkeit, dies zu tun:
Vor dem Festschreiben können Sie die bereitgestellten Dateien überprüfen. Wenn Sie den Vorgang abbrechen möchten, nachdem Sie den Diff angewendet haben, können Sie einfach grundlegende Befehle verwenden, um Änderungen aus dem Index und dem Arbeitsverzeichnis zu entfernen.
$ git reset --hard
Sie können den Vorgang beliebig oft wiederholen, da Sie jedes Mal, wenn Sie zusammenführen müssen, effektiv nur die Spitzen beider Zweige unterscheiden.
Beachten Sie, dass hier eine Annahme gilt, die auch für die andere Antwort gilt: Es gibt keine anderen Commits im stabilen Zweig als diejenigen, die aus dem Entwicklungszweig stammen. Wenn dieselbe Zeile unabhängig voneinander in beiden Zweigen geändert würde, würde dieser Ansatz im Gegensatz zu einer regulären Zusammenführung keinen Konflikt verursachen. Stattdessen würde es einfach die Änderungen im Stable-Zweig mit denen in der Entwicklung überschreiben.
Wenn Sie sich darüber Sorgen machen, können Sie jedes Mal, wenn Sie auf Stable festschreiben, den zusammengeführten Entwicklungs-Hash-Bereich in die Commit-Nachricht einfügen. Auf diese Weise haben Sie eine Aufzeichnung, falls Sie jemals zurückgehen müssen.
Ich bin neu bei git, aber es scheint, als ob –squash das ist, was Sie wollen, Sie müssen nur den Zweig anders handhaben.
$ git merge --squash development
$ git branch -d development
$ git checkout -b development
# continue work on development branch
Dies würde im Wesentlichen die Historie des Entwicklungszweigs abschneiden, und die nächste Zusammenführung wäre nur das, was Sie wollten. Wenn man sich die Manpage ansieht, scheint es so git branch -f development kann dasselbe tun wie das Löschen und Neuerstellen des Zweigs.
Wie gesagt, ich bin ziemlich neu bei Git, daher würde ich mich über Feedback zu dieser Idee freuen.