Die vielfältigen Fähigkeiten von Git, Teil 2

Der zweite Teil der Artikelserie widmet sich den vielfältigen Git-Optionen für DevOps und Automatisierer.

Werkzeuge  –  18 Kommentare

(Bild: blambca / Shutterstock.com)

In dieser Artikelserie geht es um "vielfältige" Fähigkeiten von Git. Gemeint sind damit Möglichkeiten, in Git "mehrere" verwalten zu können, wo im normalen Alltag "eins" genügt. Der erste Teil führte verschiedene Beispiele für eine solche Multiplizität auf, die zu kennen für die allgemeine Entwicklungspraxis nützlich ist. Der zweite Teil bietet weitere Beispiele. Einige sind speziell für Mitwirkende an Open-Source-Projekten interessant (und alle, die es werden wollen), andere für DevOps und andere Automatisierende.

Mehrere Identitäten

Im Zusammenhang mit Open Source tritt manchmal ein Problem auf. Und zwar betrifft es Aktive, die für Lohn und Brot in kommerziellen Projekten arbeiten und sich zusätzlich in ihrer Freizeit für Open-Source-Projekte engagieren. Auf den ersten Augenschein hin sieht es so aus, als müssten sie sich entscheiden: Welche E-Mail-Anschrift sollen sie für die eigenen Git-Aktivitäten benutzen: die berufliche oder die private?

Viele entscheiden sich für die private. Es kann ganz amüsant sein, sich für ein internes kommerzielles Repository von example.com eine Gesamtliste der im Projekt benutzten E-Mail-Anschriften zu besorgen, die nicht zu example.com gehören:

git log --pretty='%ae' | sort -u | grep -v example.com

Obwohl solche Kommandozeilen oft viel Output erzeugen, besteht das Problem eigentlich nur scheinbar. Denn Git erlaubt durchaus mehrere Identitäten derselben Person: Man kann die eigene Identität für jedes Repository einzeln konfigurieren.

Konkret wechselt man in ein Repository und konfiguriert dort spezifisch die in die Commits einzutragende eigene E-Mail-Anschrift, sowie, wenn man für den Namen eine andere Variante benutzen möchte als sonst, auch diesen. Dafür genügt es, git config wie bei der Ersteinrichtung von git aufzurufen, aber jetzt die Option --global wegzulassen – dadurch wird die Konfiguration Repository-spezifisch:

git config user.email 'a.u.thor@example.org'
git config user.name 'A. U. Thor'

Mehrere Bäume

Die folgende Mehrfachmöglichkeit von Git wird nicht so oft gebraucht, aber wenn, ist sie da: Und zwar kann Git im selben Repository komplett getrennte Branch-Bäume verwalten.

Normalerweise gibt es in einem Repository nur einen Commit ohne Vorgänger: den ersten. Aber es kann durchaus auch mehrere solcher Commits geben. Graphentheoretisch ausgedrückt: Der Commit-Graph kann unzusammenhängend sein.

Repo mit Branches ohne gemeinsame Vorfahren (Abb. 1)

Man kann in einem existierenden Repository einen neuen leeren Branch ohne jede Commits und Vorfahren erzeugen, zum Beispiel mit:

git checkout --orphan isolated-branch

Die Situation ist ähnlich der nach git init: Ein Commit, den man nun erzeugt, ist ein "erster" Commit, also ein Commit ohne Vorgänger. Man fängt sozusagen ganz von vorne an.

Dies kann nützlich sein unmittelbar vor der Veröffentlichung bisher interner Arbeit. Etwas hat klein angefangen, als privates Feierabendprojekt einer einzelnen Person, hat einige Irrungen und Wirrungen durchlebt, aber sich ganz manierlich entwickelt und soll nun als Open-Source-Repository debütieren.

In der Situation ist es eine offene Frage, ob man die Irrungen und Wirrungen mit veröffentlichen will. Die genauen Zeitstempel, wann man seinerzeit aktiv war, sind verhältnismäßig intime personenbezogene Daten, die man der Welt vielleicht nicht zur Verfügung stellen will. An die Stelle der Gesamthistorie kann man eine Art "Paukenschlag-Commit" treten lassen, der das gesamte bisher Erreichte sozusagen "aus dem Nichts" entstehen lässt.

Ein beispielhaftes Vorgehen ist:

git branch -m master old-master
git checkout --orphan master
git reset old-master -- .
git commit -m 'Results thus far, without convoluted history.'

Der Code benennt zunächst den bisherigen master in old-master um. Es gibt also kurzfristig keinen Branch master mehr im Repository. In der nächsten Zeile wird master neu hergestellt, als leerer Branch, ohne Commit, Vorgänger oder Historie.

Anschließend kommt eine Variante von git reset zum Einsatz. Die Variante kopiert den gesamten Datenbestand des letzten Commits von old-master direkt in den Index. (Man beachte den die Kommandozeile abschließenden Punkt.)

Es ist etwas ungewohnt, dass die Daten direkt im Index landen und nicht im Arbeitsverzeichnis. Wer das nicht weiß, den kann der Output von git status verwirren.

Mit dem abschließenden git commit wird ein neuer Commit ohne Vorgänger angelegt (und nebenbei wird das Arbeitsverzeichnis gefüllt). Man kann sich anschließend mit gitk oder git log --pretty=raw davon überzeugen, dass der neue Commit tatsächlich keine Vorgänger hat. Der Commit ist der gewünschte "Paukenschlag-Commit", der veröffentlicht werden kann.