[Git] Merge mit einem Commit
-
Wie kann ich mit Git einen Merge durchführen, bei dem
- nur ein Commit entsteht (d.h. die Commits des zu mergenden Branches werden zusammengefasst)
- das Ganze als Merge und nicht nur als normaler Commit erkannt wird (d.h. z.B. Graphen werden entsprechend gezeichnet)
Bei
git merge --squash
ist der zweite Punkt leider nicht erfüllt.
-
Raumgitter schrieb:
Wie kann ich mit Git einen Merge durchführen, bei dem
- nur ein Commit entsteht (d.h. die Commits des zu mergenden Branches werden zusammengefasst)
- das Ganze als Merge und nicht nur als normaler Commit erkannt wird (d.h. z.B. Graphen werden entsprechend gezeichnet)
Wie stellst du dir das vor? Einerseits willst du nicht die Historie der Branch, daher nur ein Commit, aber anzeigen soll es Git trotzdem noch als einzelne Commits, oder wie?
-
Du solltest dir im Fall von Git einen Commit nicht als eine Menge von Unterschieden zum Elterncommit vorstellen. In Git ist ein Commit die vollständige Information über den Inhalt der Branch zum Commit-Zeitpunkt(*). In so fern ist ein Merge genau das was du möchtest. Es entsteht genau ein Commit, in dem der Zustand nach dem Merge aufgezeichnet ist und damit natürlich auch alles was aus deinem gemergeten Branch kam. Der Unterschied zu einem normalen Commit ist hier lediglich, das es nun zwei Elterncommits gibt, auf die gezeigt wird. Auch das ist genau das was du willst.
(*) Natürlich wird im Hintergrund dafür gesorgt, dass gleiche Objekte über alle Branches und Commits hinweg nur einmal gespeichert und dann geshared werden, das hat aber mit der Commit-Hiostorie nichts zu tun. Auch werden besagte Objekte unter Umständen, um noch mehr Platz zu sparen, in Form eines Diffs zu einem beliebigen anderen Objekt gespeichert. Aber auch hier muss das Zielobjekt nicht zwingend irgendeine Beziehung zum Ausgangsobjekt haben, hauptsache ist, dass es relativ ähnlich ist.
-
Danke für die Verdeutlichung der Terminologie.
Vielleicht etwas zum Hintergrund: Der andere Branch stellt eine externe Bibliothek dar, deren Änderungen von Zeit zu Zeit mittels Subtree Merge in den Master-Branch übernommen werden. Da diese Änderungen den Benutzer normalerweise nicht interessieren, sollen deren Commitmessages auch nicht den Master-Branch belegen. Dennoch fände ich es praktisch, wenn die Zusammenführungsaktion auch tatsächlich als Merge dargestellt würde, da man so bei Interesse die Version der anderen Bibliothek zurückverfolgen und die Änderungen im Detail anschauen kann.
Könnte man sowas mit Rebase bewerkstelligen?
Übrigens: Ich weiss, dass es auch Submodules gibt, allerdings scheint das Konzept nicht ausgereift zu sein. Ein paar Dinge gefallen mir nicht (Löschen super-umständlich, Submodule werden nicht automatisch geklont).
-
du könntest in dem zu mergenden branch zunächst mit rebase alle commit squashen. dann hast du nur noch einen commit. den kannst du dann mergen. du müsstest beim mergen aber darauf achten, dass er keinen fast-forward macht, sonst ist der graph in der history dahin (kein merge-commit). afaik kann man aber fast-forward auch unterbinden.
wenn du aber schon irgendwas gepusht hast, solltest du rebase umbedingt vermeiden. sonst machst du dich nur unbeliebt beim rest des teams.
-
Kennst du git subtree? Falls nicht such das mal auf github und schau dir das mal an. Das ist eine Alternative zu git submodule und soll besser funktionieren. Bin selber aber auch noch nicht dazu gekommen es auszuprobieren.
-
Raumgitter schrieb:
Vielleicht etwas zum Hintergrund: Der andere Branch stellt eine externe Bibliothek dar, deren Änderungen von Zeit zu Zeit mittels Subtree Merge in den Master-Branch übernommen werden. Da diese Änderungen den Benutzer normalerweise nicht interessieren, sollen deren Commitmessages auch nicht den Master-Branch belegen. Dennoch fände ich es praktisch, wenn die Zusammenführungsaktion auch tatsächlich als Merge dargestellt würde, da man so bei Interesse die Version der anderen Bibliothek zurückverfolgen und die Änderungen im Detail anschauen kann.
submodule liefert dir genau das. Die commit-messages im submodule erscheinen nicht im master-branch des Haupt-Repositories, aber bei Interesse kann man die Versionen des submodules zurückverfolgen und die Änderungen im Detail anschauen. git clone clont inzwischen übrigens auch automatisch alle submodules, wenn du git clone --recursive nimmst.
-
lolhehe schrieb:
du könntest in dem zu mergenden branch zunächst mit rebase alle commit squashen. dann hast du nur noch einen commit.
Dann ist aber der zu mergende Branch wieder dezimiert
Ich möchte im Prinzip sowas:
#---#---#---# <- zu mergender Branch \ \ <- Merges #---#---#---#---# <- Master-Branch
Gitler schrieb:
Kennst du git subtree?
Ja,
merge -s subtree
verwende ich momentan.Christoph schrieb:
submodule liefert dir genau das. Die commit-messages im submodule erscheinen nicht im master-branch des Haupt-Repositories, aber bei Interesse kann man die Versionen des submodules zurückverfolgen und die Änderungen im Detail anschauen. git clone clont inzwischen übrigens auch automatisch alle submodules, wenn du git clone --recursive nimmst.
Das wusste ich nicht, dann schau ich mir Submodules vielleicht doch nochmals an. Vielen Dank!
-
Raumgitter schrieb:
Gitler schrieb:
Kennst du git subtree?
Ja,
merge -s subtree
verwende ich momentan.Alter, ich rede davon.
-
Was ich an Submodules überhaupt nicht mag, ist dass sie nicht automatisch geklont/gepullt werden. Der Benutzer muss von den Submodules wissen, obwohl sie ein Implementation-Detail sind. Das Rekursiv-Flag geht aber schnell vergessen... Dazu kommt, dass GitHub scheinbar keine Submodules in .zip-Archive einbindet, was letztere effektiv nutzlos macht.
Wenn ich hingegen Subtrees verwende, verhält sich das Repository ganz normal und hält keine Überraschungen bereit. Der einzige Nachteil ist, dass bei einem Merge nicht automatisch ein Verweis auf den Commit des Sub-Repositorys erstellt wird (weiss jemand zufällig gerade, wie man sowas bei GitHub macht?)
Aber eigentlich würde es mir schon reichen, das ursprüngliche Problem zu lösen, d.h. beim Merge nur eine Commitmessage (und zwar eine als "Merge from Commit XY" gekennzeichnete) zu haben.
Gitler schrieb:
Alter, ich rede davon.
Danke, sieht noch interessant aus.
-
Ich verwende jetzt git-subtree, vielen Dank für den Vorschlag.
Nun habe ich nur noch 2 Commitmessages bei einem Update der externen Bibliothek (1 Squash aller externen Commits + 1 Merge). Ich nehme an, das liegt in der Natur von Git, dass zusätzlich zur Merge-Message mindestens ein Commit mit den Änderungen erstellt wird.
Oder gibt es eine Möglichkeit, die beiden zu kombinieren (aber immer noch eine Merge-Message zu haben)?
-
Raumgitter schrieb:
Oder gibt es eine Möglichkeit, die beiden zu kombinieren (aber immer noch eine Merge-Message zu haben)?
Einen merge-commit erkennt git daran, dass er zwei parent commits hat. Überleg dir, was die beiden parents sein sollen, dann weißt du die Antwort.