Git ist eines der essenziellsten Tools der Software-Entwicklung. Aufgrund seines enormen Funktionsumfangs gibt es jedoch auch einige Funktionen, die zwar sehr praktisch, aber nicht besonders bekannt sind. Einige nützliche Funktionen sollen hier hervorgehoben werden.
Damit Sie die Befehle beim Lesen problemlos testen können, wird explizit darauf hingewiesen, wenn Befehle schwerwiegende oder irreversible Änderungen an Ihrem Repository vornehmen. Auf der sicheren Seite sind Sie, wenn Sie alle Ihre Änderungen vorher pushen. Grundlegende Git-Kenntnisse werden im Folgenden angenommen.
1. Besseres Log
Der Befehl git log wird den meisten vertraut sein, aber er bietet auch erweiterte Optionen an, um die Informationen besser darzustellen. Mit der Option --graph erzeugt Git einen Graphen, der die Zusammenhänge der Commits und Branches visualisiert. Aufgrund der Menge an dargestellten Details ist dies noch nicht besonders übersichtlich. Hier hilft die Option --oneline, indem sie die Commits verkürzt darstellt und dazu jeweils eine Zeile verwendet. Nimmt man noch die Option --all hinzu, werden alle Commits angezeigt. So kann man sich mit git log --graph --oneline --all einen sehr guten Überblick verschaffen.
Die Aliase dieser StackOverflow-Antwort sind hierzu auch besonders empfehlenswert. Sie stellen den Verlauf der Branches mit allen wichtigen Informationen gut dar.
2. Der interaktive Modus
Vor dem Committen müssen die Änderungen ausgewählt werden, die im Commit enthalten sein soll. Häufig werden dazu die veränderten Dateien mit git add pfad/zur/datei.c hinzugefügt. Diese Methode hat allerdings ein paar Nachteile:
- Der Dateipfad jeder Datei muss angegeben werden
- Soll nur ein Teil der Änderungen in einer Datei hinzugefügt werden, dann müssen alle anderen Änderungen vorher rückgängig gemacht werden
- Kleinigkeiten wie gelöschte oder hinzugefügte Leerzeilen werden ebenfalls übernommen und führen zu einer unübersichtlicheren Änderungshistorie
Deutlich effizienter ist die Verwendung von git add -p. Mit der Option -p präsentiert Git nach und nach veränderte Blöcke und man kann interaktiv entscheiden, welche davon man zum nächsten Commit hinzufügen will. Git zeigt im interaktiven Modus nach einer leeren Eingabe (Enter) an, welche Möglichkeiten es gibt. Bei git add -p sind dies die wichtigsten:
- y – Aktuellen Block hinzufügen
- n – Aktuellen Block nicht hinzufügen
- q – Abbrechen (behält vorherige Änderungen allerdings bei)
Will man nur einen Teil der Änderungen eines Blocks hinzufügen, dann kann man den Block mit s weiter unterteilen oder, falls das nicht möglich ist, mit e Zeile für Zeile entscheiden. Außerdem kann man mit a und d für alle Blöcke der aktuellen Datei gleichzeitig entscheiden.
Neben den Vorteilen durch die gezieltere Wahl der Änderungen ermöglicht git add -p einem auch noch einmal, die Änderungen zu prüfen. Außerdem fallen hier Whitespace-Fehler besonders auf.
Möchte man noch nicht committete Änderungen gezielt verwerfen, dann bietet sich git checkout -p an. Der Befehl ähnelt git add -p in der Verwendung stark. Daher muss man allerdings auch auf eine Verwechslung aufpassen und man sollte sich bewusst sein, dass eine falsche Verwendung von git checkout -p zu irreversiblem Verlust der nicht committeten Änderungen führen kann. Dennoch ist der Befehl empfehlenswert.
3. Effizient committen
Ist man mit seinen ausgewählten Änderungen zufrieden, dann ist der nächste Schritt natürlich git commit. Git öffnet anschließend einen Texteditor, damit man die Commit-Nachricht angeben kann. Diesen Schritt kann man aber auch überspringen, indem man dem Befehl die Commit-Nachricht direkt übergibt: git commit -m ‚Dies ist eine Beispielnachricht‘.
Ergänzungen eines bereits erstellten Commits können mit git commit --amend nachgereicht werden. Mit diesem Befehl wird, anstatt einen neuen Commit zu erstellen, der Inhalt stattdessen einfach in den letzten Commit integriert. Er kann auch verwendet werden, um die Commit-Nachricht des letzten Commits zu verändern. Die Veränderung des letzten Commits ist allerdings nur empfehlenswert, wenn er noch nicht gepusht wurde.
4. Aufräumen mit git rebase
Vielen wird der Fehler bereits passiert sein, einen neuen Branch vom falschen Branch aus abzuzweigen. Natürlich kann man in dem Fall den neuen Branch löschen und an der richtigen Stelle neu erstellen, aber was, wenn man schon Änderungen committet hat? Mit git rebase [Zielcommit/-branch] kann man den aktuell ausgecheckten Branch auf den Zielcommit bzw. Zielbranch „verschieben“. Eventuell auftretende Konflikte muss man dann ebenso wie bei einem Merge lösen.
Nützlich ist dies auch, wenn man beispielsweise vor einiger Zeit einen Feature-Branch vom Master-Branch abgezweigt hat und nun sein Feature-Branch auf den neusten Stand des Master-Branchs updaten will. Zum einen kann man so mit dem neusten Stand arbeiten, zum anderen treten eventuelle Konflikte schon beim Rebasen und nicht erst hinterher beim Mergen auf, was die Arbeit der Person erleichtert, die den Branch mergen muss.
Auch hier wird es allerdings schwierig, wenn der Branch bereits gepusht wurde. Mit --force kann der Branch nach dem Rebase zwar gepusht werden, aber das ist problematisch für alle anderen Personen, die sich schon auf den Branch verlassen. Daher sollte man dies nur machen, wenn man sich bewusst ist, welche Konsequenzen dies hat.
git rebase -i [Zielcommit/-branch] kann außerdem dazu verwendet werden, die Commits des aktuellen Branches zu bearbeiten. Der Befehl öffnet den für Git eingestellten Texteditor, listet die relevanten Commits auf und stellt eine Kurzzusammenfassung der Möglichkeiten dar. Unter anderem kann man hier die Commitnachrichten und Reihenfolge der Commits ändern sowie Commits vereinen oder entfernen, wodurch es natürlich wieder zu schwerwiegenden Änderungen am Repository kommen kann. Allerdings ist es schwierig, hier unabsichtlich Commits zu entfernen.
5. Rettung durch reflog
Sollten Sie einen Fehler mit Git gemacht haben, kann Sie eventuell der Befehl git reflog retten. Das reflog bzw. reference log enthält einige Informationen zu den zuvor ausgeführten Befehlen und kann unter anderem auch dazu verwendet werden, einen früheren Stand auszuchecken und somit wiederherzustellen. Hierbei gilt es zu beachten, dass das reflog nur die Änderungen am lokalen Repository enthält und regelmäßig alte Einträge gelöscht werden.
Folgendes Beispiel zeigt, wie man mit git reflog einen gelöschten Branch wiederherstellen kann. Bitte nicht nachmachen, da im Beispiel der master-Branch gelöscht wird und dies natürlich zu schwerwiegenden Änderungen führt. git reflog können Sie aber problemlos auch in Ihrem Repository ausführen, da es lediglich Informationen anzeigt.
$ git branch -D master #Nicht ausführen! Deleted branch master (was 8f6505f). $ git reflog b776db8 (HEAD ->; feature_can) HEAD@{0}: commit: CAN: Fix init db61c14 HEAD@{1}: commit: Add CAN Module 80a3258 HEAD@{2}: checkout: moving from 80a3258 to feature_can 80a3258 HEAD@{3}: checkout: moving from master to 80a3258 8f6505f HEAD@{4}: commit: Add build instructions to readme d60b906 HEAD@{5}: commit: Add readme 80a3258 HEAD@{6}: commit (initial): Create environment $ git checkout 8f6505f #Ursprünglich master [...] $ git checkout -b master Switched to a new branch 'master' |
6. Repository durchsuchen
Mit git grep kann man in den Dateien des Repositorys (genauer: ab dem aktuellen Ordner in getrackten Dateien) nach einem bestimmten Text suchen. Beispielsweise werden nach Eingabe des Befehls git grep ‚enthält‘ alle Vorkommnisse des Textes „enthält“ angezeigt. Mit der Option -n wird die Zeilennummer des Treffers ebenso dargestellt und mit -i wird Groß- und Kleinschreibung ignoriert. Regex-Ausdrücke sind als Suchbegriffe ebenso erlaubt.
Haben Sie Fragen oder weitere Tipps? Lassen Sie es uns im Kommentarbereich wissen!