Branches

Einführung

Im letzten Tutorial haben wir bereits erste Erkenntnisse zu weiterführenden Funktionalitäten von Git gewonnen. In diesem Tutorial wollen wir uns spezifisch dem Umgang mit Branches widmen.

Was sind Branches?

Das Konzept von Branches lässt sich gut durch einen Baum visualisieren. Es gibt einen Stamm, der mit der Erde verwurzelt ist und den ganzen Baum trägt. Aus diesem Stamm wachsen viele verschiedene kleinere Äste heraus, die den Baum vielfältiger machen. In diesem Szenario ist der Hauptstamm unser master-branch. In der Entwicklung für sensitivere Sprache wird dieser inzwischen auch manchmal main-branch, aber da das lokale Erstellen eines Repositories meist master erstellt, bleiben wir erstmal bei der Bezeichnung. Dieser Branch trägt das Hauptprojekt und ist von Beginn an da. Die anderen kleineren Äste sind weitere Branches, die wir zusätzlich erstellen können. Diese sind viele verschiedene Versionen unseres Hauptprojekts und erlauben uns kreativ zu sein.

Für Psycholog/innen kann es zum Beispiel nützlich sein bei Datenanalysen mit Branches zu arbeiten. Sagen wir mal, ihr habt in eurem Hauptprojekt eure Analyse schon fertig, euch fällt aber im Nachhinein auf, dass es vielleicht noch einen besseren und einfacheren Weg gibt. Dann könnt ihr einen neuen Branch zu eurem Hauptprojekt erstellen, an dem ihr euren neuen Weg erstmal testweise ausprobieren könnt. Falls der neue Analyseweg doch nicht so klappt, wie ihr es euch vorgestellt habt, könnt ihr ganz einfach wieder in euer Hauptprojekt wechseln mit der funktionierenden Analyse und da weiterarbeiten.

Wenn ihr jetzt aber den neuen Analyseweg besser findet als den Alten und ihn in euer Hauptprojekt übernehmen wollt, mergt ihr die beiden. Der Ast verwächst also mit dem Baumstamm.

Hier noch ein weiteres Beispiel, warum Branches nützlich sein können. Ihr seid gerade an einer Hausarbeit dran oder sogar eurer Bachelorarbeit und gebt eine erste Version davon ab. Dann könnt ihr zur besseren Dokumentation, für diese Abgabe einen Branch erstellen und diesen dann einfrieren. Das heißt ihr benutzt ihn nicht mehr, sodass er bleibt wie er ist. Dadurch könnt ihr diese “Version” eurer Arbeit speichern, falls ihr sie später nochmal benötigt.

Der Master-Branch

Wir arbeiten weiter mit dem Beispiel-Repository Praktikum, das wir auch in den letzten 4 Tutorials genutzt haben. Dabei werden wir das Tutorial auf die Arbeit mit SmartGit fokussieren, haben aber im Appendix B auch ein paar Terminal-Befehle aufgeführt. In der Ansicht von SmartGit können wir in der Kachel Branches sehen, wie unser lokaler Branch benannt ist.

Der master-Zweig ist wie bereits erwähnt in den meisten Versionen der default-Branch in Git. Dieser wird mit dem Befehl git init automatisch erstellt und die meisten Personen ändern dies nicht. Der master-Branch ist also nicht speziell, sondern einfach nur die Voreinstellung. Wir haben alle unsere Commits bisher auf dem master-Branch gemacht. Damit wir wissen, wo sich der Branch gerade befindet, hat SmartGit in der Kachel Journal einen Zeiger oder Pfeil eingebaut.

Unser aktueller Commit ist der letzte, den wir im vorherigen Tutorial durchgeführt haben. Dabei haben wir Konflikte behoben und er wurde automatisiert als Merge remote-tracking branch… benannt. In der Abbildung sehen wir, dass der grüne Zeiger des master-Branches darauf zeigt. Gleichzeitig ist auch origin an dieser Stelle vermerkt. Das liegt daran, dass wir das Repository mit GitHub verbunden haben und es nach Informationen unseres lokalen SmartGit auf demselben Stand ist.

Einen neuen Branch erstellen

Wir wollen jetzt einen neuen Branch in unserem Ordner “Praktikum” erstellen, um zu testen, ob ein neuer Analyseweg besser ist als das, was wir bisher gemacht haben. Hierzu klicken wir in SmartGit oben in der Leiste auf Branch und dann auf Add Branch. Jetzt gebt ihr einen Namen ein (z.B. “alternativeAnalyse”) und bestätigt, indem wir zunächst auf Add Branch klicken.

Auf SmartGit müssten euch nun unter Local Branches zwei Optionen angezeigt werden: master und alternativeAnalyse.

Woher wissen wir auf welchem Branch wir uns gerade befinden? In SmartGit ist das wie immer ziemlich einfach. Da wird der aktuelle Branch einfach dick gedruckt.

Auf GitHub seht ihr direkt auf der Startseite eures Projekts auf welchem Branch ihr euch befindet. Wenn ihr dort nachschaut werdet ihr sehen, dass der neue Branch auch noch gar nicht existiert. Dazu werden wir gleich kommen.

Branches wechseln

Wir wollen jetzt zu dem Branch alternativeAnalyse wechseln, um dann Änderungen an den Dokumenten vorzunehmen. In der Sprache von Git wird diese Betrachtung eines Branches als checkout bezeichnet. Bei SmartGit muss man einfach nur mit Doppelklick auf den Branch aus der links unten angezeigten Liste gehen, in den man wechseln will. Dann sollte folgendes Fenster angezeigt werden, in dem ihr dann den Vorgang bestätigt.

Nachdem wir nun auf dem richtigen Branch für eine alternative Analyse sind, können wir Dateien verändern (in dem Beispiel nutzen wir die Datei Datenauswertung.R). Stellen wir uns vor, dass wir Statt Summenscores für die Variablen Durchschnittswerte der Items verwenden wollen. Wir wissen aus der Statistik, dass das bei allen möglichen Berechnungen keinen Unterschied machen sollte, aber es ist ein einfaches Beispiel für die Demonstration. Dazu ändern wir erstmal die Datei in RStudio und speichern ab.

Jetzt navigieren wir wieder zurück zu SmartGit und stellen erstmal sicher, dass wir uns immer noch auf dem neuen Branch alternativeAnalyse befinden. Wir führen nun einen Commit auf diesem Branch durch, der die oben aufgeführten Änderungen enthält. Das geht über die gewohnten Befehle und hat zwei interessante Begleiterscheinungen. Zunächst sehen wir im Fenster, dass es nicht möglich ist, Commit & Push auszuwählen. Das liegt daran, dass der neue Branch noch kein äquivalent auf GitHub besitzt. Wir müssen uns also erstmal mit dem Button nur Commit zufrieden geben.

Um nun einen äquivalenten Branch auf GitHub zu erschaffen, wählen wir in der Kachel Branches auf SmartGit mit einem Rechtsklick den Branch aus. Dann wählen wir push und bestätigen das nächste Fenster. In der Kachel erscheint jetzt ein zweiter Branch unter origin, der auch den Namen alternativeAnalyse trägt. Das zeigt uns an, dass auch das online Repository nun aus zwei Branches besteht.

Dies können wir uns auch nochmal bestätigen lassen, indem wir auf GitHub selbst nachschauen. Hier stehen einige Meldungen, die wir ignorieren können. Besonders entscheidend ist aber, dass sich die Anzahl der Branches auf zwei erhöht hat und man die Unterschiede zwischen diesen sich jetzt auch hier anschauen könnte.

Der zweite interessante Aspekt tritt auf, wenn ihr lokal mit SmartGit durch Checkout zwischen den Branches hin und her wechselt. Achtet dabei auf den obersten Commit im Journal. Hier sehen wir den Unterschied. Der neu durchgeführte Commit ist nur auf dem Branch aternativeAnalyse vorhanden (Bild 1). Auf dem Branch master ist nur der Commit aus dem letzten Tutorial angezeigt (Bild 2).

Bild 1: Bild 2: Wenn ihr dabei die Datei Datenauswertung.R in RStudio geöffnet habt, werdet ihr feststellen können, dass sich auch ihr Inhalt ändert, je nachdem welcher Branch gerade ausgewählt ist. Seid ihr auf dem Branch master, seht ihr die ursprüngliche Logik mit den Summenscores, während auf dem Branch alternativeAnalyse der Weg über die Mittelwerte angezeigt wird (kann nach dem Wechsel ein paar Sekunden brauchen, bis RStudio switched). Wenn ihr nun also weiter an Dateien arbeiten wollt, solltet ihr euch immer im klaren sein, auf welchem Branch ihr euch gerade befindet. Falls ihr euch für die technische Seite dieses Vorgangs interessiert, schaut in den Appendix A.

Nehmen wir jetzt an, dass die alternative Analyse die bessere war und wir daher die Inhalte dieses Branches auf den Master übertragen wollen.

Zwei Branches Mergen

Natürlich kann man zwei Branches auch wieder zu einem zusammenführen. Wenn ihr dem Tutorial bis hierher gefolgt seid, dann müsstet ihr zwei verschiedene Versionen eines Projekts auf verschiedenen Branches liegen haben.

Wir wollen nun den Branch alternativeAnalyse und master zusammenfügen - und zwar in der Weise, dass der Stand des neuen Branch in den alten übernommen wird. Dafür wählen wir zunächst mit Checkout den master-Branch. Dann wählen wir mit Rechtsklick den Branch alternativeAnalyse aus und drücken auf Merge. Das bedeutet, dass wir die Inhalte dieses ausgewählten Branches in master mergen wollen. Folgendes Fenster sollte sich öffnen. Jede einzelne Option zu erläutern würde zu stark ins Detail gehen. Universell ist Merge to working tree einsetzbar, weshalb wir es wählen.

SmartGit sollte nun so aussehen.

Eine ähnliche Ansicht haben wir bereits gesehen, als wir den Conflict Solver vorgestellt haben. Hier haben wir nun den Vorteil, dass die Commits sich nicht widersprechen, weshalb wir keinen Konflikt lösen müssen und daher direkt weitermachen können. Wenn wir allerdings auch auf dem master-Branch an der Datei weitergearbeitet hätten, müssten wir nun auch an dieser Stelle wieder auf den Conflict Solver aus dem letzten Tutorial zurückgreifen.

In dem hier dargestellten, etwas einfacherem Fall können wir die veränderte Datei auswählen und auf Commit klicken. Auch bei diesem Merge wird uns wieder eine Message vorgeschlagen, die wir ohne Änderung akzeptieren. Wir wählen nun Commit & Push. Jetzt haben wir zwei Branches erfolgreich gemerged.

Branches löschen

Nachdem wir nun alle Inhalte aus dem Branch alternativeAnalyse in master übertragen haben und sicher sind, dass wir keine neuen Änderungen mehr in dem Branch machen wollen, können wir ihn auch löschen. Das geht in SmartGit sehr schnell, indem wir per Rechtsklick den Branch auswählen (Achtung: Das Vorgehen funktioniert nicht, wenn wir uns gerade auf dem Branch befinden). Dann wählen wir Delete und bekommen folgendes Fenster angezeigt. Da es sich um einen Branch handelt, der auch auf GitHub liegt, gibt es in dem Fenster noch weitere Optionen, die man optional auswählen kann. Dabei geht es darum, den Branch auch aus der online Version des Repository zu entfernen. Da wir das gerne erledigen würden, wählen wir beide Optionen aus.

SmartGit fragt uns nochmal, ob wir uns wirklich sicher sind:

Wenn ihr nun auf GitHub nachschaut, seht ihr, dass auch dort wieder nur ein Branch vorhanden ist. Das Löschen von Branches sollte aber auf jeden Fall mit Vorsicht durchgeführt werden, da die Änderungen nun unwiderruflich verloren sind.

Fazit und Ausblick

Wie ihr seht, sind Branches in Git ein sehr nützliches Tool, beispielsweise wenn ihr ein Original und eine Entwicklungsdatei habt. Natürlich ist das Branches-Tool noch viel umfangreicher als hier beschrieben. Ihr könnt auch die Entwicklungsdatei nochmal spalten und dann entscheiden, welche ihr mergen wollt - im Endeffekt also die Branches immer weiter aufsplitten. Hier aber aufpassen, dass ihr den Überblick behaltet.


Appendix A - Enkodierungslogik von Git

Wie funktioniert die Datenspeicherung?

Ihr kennt bereits das grobe Konzept von Branches, widmen wir uns mal der etwas technischeren Erklärung von Branches. Wir müssen zunächst verstehen wie Git Daten speichert. Zunächst erstmal eine grobe Erklärung.

Nehmen wir hier zur Verdeutlichung unser schon existierendes Git-Repository Praktikum. In diesem liegt die Datei Datenauswertung.R.

Verändern wir jetzt etwas kleines an der Datei. Fügt in einer Zeile ein Ausrufezeichen hinzu oder einen Punkt. Wichtig ist, dass die Datei in einen neuen Commit gepackt werden muss. Öffnen wir nun das Terminal und mit cd unser Git-Repository.

Jetzt wollen wir die Datei für einen Commit vorbereiten. Dafür muss man sie, wie ihr wisst, erstmal ins Staging Environment laden.

Anschließend führen wir einen Commitdurch.

Wie unterscheidet Git jetzt aber den neuen Commit vom Alten?

Dafür erstellt Git bei jedem Commit, den ihr durchführt, sogenannte Checksums. Zu jeder Checksum gehört dann logischerweise auch eine andere Version der Datei. Git erstellt somit quasi einen Schnappschuss eurer Datei, dessen Name die jeweilige Checksum ist. Schauen wir uns mal an, wie so eine Checksum aussieht. Dafür gebt ihr im Terminal den Befehl git log ein oder ihr schaut euch über SmartGit euer Log an.

Dieser Befehl zeigt euch eure Commit-Historie an und auch die jeweiligen Checksums, die Git erstellt hat. Das sind diese langen Zeichenabfolgen:

Vergleicht mal verschiedene Checksums unterschiedlicher Commits. Ihr werdet nie zwei identische finden.

Auf SmartGit sind die Checksums etwas schwerer zu finden und sehen auch ein bisschen anders aus. Geht dafür auf den Log-Button in der obersten Leiste.

Es öffnet sich noch ein Fenster, dass jeden eurer Commits in diesem Repository anzeigt. Die Checksum zu unserem neuen Commit finden wir rechts in dem Commit Fenster.

Wie ihr hier sehen könnt, zeigt SmartGit nicht die ganze Checksum an, sondern nur den Anfang von ihr.

Auch interessant ist, dass SmartGit euch auch anzeigt von welchem Commit der neue abstammt. Welcher Commit also das “Elternteil” des Neuen ist. So könnt ihr, vor allem in der Hinsicht auf verschiedene Branches, sehr gut den Überblick über eure Commit-Historie behalten.

`

Tieferes Verständnis von Speicherprozessen

Eine Checksum oder auch Prüfsumme wird jedes Mal erstellt, wenn man eine Datei in das Staging Environment lädt. Diese kann zum Beispiel so aussehen: “7a3k9”. Mit der Checksum soll die Integrität von Daten geprüft werden. Das beinhaltet die Kontrolle der Korrektheit, Vollständigkeit und Konsistenz unserer Datei. Der Computer kann so sicherstellen, ob die Datei einen Fehler hat oder nicht.

Nützlich ist das zum Beispiel, wenn ihr eine Datei aus dem Internet ladet und sichergehen wollt, dass kein Fehler beim Herunterladen passiert ist. Ihr müsst einfach nur die Checksum der Datei aus dem Internet und euerer Datei auf dem Computer vergleichen. Sollten die Checksums identisch sein, ist kein Fehler aufgetreten.

Zurück zu Git. Ihr habt gerade eure Datei in das Staging Environment geladen und dabei für diese Datei eine Checksum erstellt. Anschließend wird diese Version der Datei in einem Git-Repository untergebracht und die Checksum zum Staging Environment hinzugefügt. Wenn ihr jetzt den Commit durchführt, nimmt Git die Checksum jedes Subordners und speichert diese in einem Tree-Objekt in eurem Git-Repository. Darauf folgend wird ein Commit-Objekt erstellt, das diese Metadaten enthält. So kann ein Schnappschuss der Daten erstellt werden, wann immer es gebraucht wird.

Datenstruktur von Git

Zurück zu unserem Ordner “Praktikum”. Dieser enthält unser Objekt Datenauswertung.R. Dazu zugehörig wird ein sogenannter “Blob” erstellt. Ein “Blob” ist ein Objekttyp, der benutzt wird, um den Dateininhalt in einem Repository unterzubringen. Jetzt brauchen wir allerdings noch ein Objekt, das diesen Dateiinhalten auch Namen wie hier Datenauswertung.R zuordnen kann. Dafür ist das “Tree-Objekt” zuständig. Zu guter Letzt befindet sich in diesem Ordner auch noch ein neues Commit-Objekt, das wir durch die Durchführung des Commits von Datenauswertung.R erstellt haben. In diesem befindet sich ein Schnappschuss der Datei zu dem Zeitpunkt an dem der Commit erstellt wurde.

Hier könnt ihr euch diese grobe Erklärung der Datenstruktur von Git nochmal verbildichen:

Metadaten

Noch ein kleiner Ausflug zum Thema Metadaten. Wenn ihr ein Foto von etwas macht, speichert eure Kamera oder euer Smartphone nicht nur das Foto, sondern auch die zugehörigen Metadaten. Dazu kann gehören:

Wann ist das Foto entstanden? Wo ist das Foto entstanden? Was für eine Kamera wurde benutzt?

Metadaten sind also im Prinzip Daten, die Informationen über bestimmte Merkmale anderer Daten enthalten.

`

Appendix B - Terminalbefehle

Branch-Erstellung und Navigation

Auch über das Terminal kann ein neuer Branch erstellt werden. Navigiert zu dem Repository in dem der neue Branch sein soll mit cd - in dem Fall also in den Ordner Praktikum. Anschließend wird mit git branch alternativeAnalayse ein Branch erzeugt, der diesen Namen trägt.

Im Terminal wird der aktuell ausgewählte Branch durch den “Zeiger” HEAD gekennzeichnet. Mit dem Befehl git log --oneline --decorate kann man im Terminal sehen, wo der HEAD-Zeiger gerade hinzeigt.

Nun wollen wir den Branch wechseln. Der zugehörige Befehl heißt git checkout alternativeAnalyse. Der HEAD-Zeiger bewegt sich damit zu unserem ausgewählten Branch. Ob es geklappt hat, können wir mit dem bereits eben verwendeten Befehl git log --oneline --decorate testen.

`