.. SPDX-FileCopyrightText: 2020 cusy GmbH
..
.. SPDX-License-Identifier: BSD-3-Clause
Rückblick
=========
``log``
-------
.. seealso::
* `Git’s Database Internals III: File History Queries
`_
Filtern und sortieren
~~~~~~~~~~~~~~~~~~~~~
:samp:`$ git log [-n {COUNT}]`
listet die Commit-Historie des aktuellen Zweiges auf.
``-n``
beschränkt die Anzahl der Commits auf die angegebene Zahl.
:samp:`$ git log [--after="{YYYY-MM-DD}"] [--before="{YYYY-MM-DD}"]`
Commit-Historie gefiltert nach Datum.
Auch relative Angaben wie ``1 week ago`` oder ``yesterday`` sind
zulässig.
:samp:`$ git log --author="{VEIT}"`
filtert die Commit-Historie nach Autor*innen.
Es kann auch nach mehreren Autor*innen gleichzeitig gesucht werden,
:abbr:`z.B. (zum Beispiel)`:
:samp:`$ git log --author="{VEIT\|VSC}"`
:samp:`$ git log --grep="{TERM}" [-i]`
filtert die Commit-Historie nach regulären Ausdrücken in der
Commit-Nachricht.
``-i``
ignoriert Groß- und Kleinschreibung.
:samp:`$ git log -S"{FOO}" [-i]`
filtert Commits nach bestimmten Zeilen im Quellcode.
``-i``
ignoriert Groß- und Kleinschreibung.
:samp:`$ git log -G"{BA*}"`
filtert Commits nach regulären Ausdrücken im Quellcode.
:samp:`$ git log -- {PATH/TO/FILE}`
filtert die Commit-Historie nach bestimmten Dateien.
:samp:`$ git log {MAIN}..{FEATURE}`
filtert nach unterschiedlichen Commits in verschiedenen Zweigen
(Branches), in unserem Fall zwischen den Branches :samp:`MAIN` und
:samp:`FEATURE`.
Dies ist jedoch nicht dasselbe wie :samp:`git log {FEATURE}..{MAIN}`.
Nehmen wir folgendes Beispiel.
.. code-block::
A - B main
\
C - D feature
:samp:`$ git log {MAIN}..{FEATURE}`
zeigt Änderungen in :samp:`{FEATURE}` an, die nicht in :samp:`{MAIN}`
enthalten sind, also die Commits ``C`` und ``D``.
:samp:`$ git log {FEATURE}..{MAIN}`
zeigt Änderungen in :samp:`{MAIN}` an, die nicht in :samp:`{FEATURE}`
enthalten sind, also den Commit ``B``.
:samp:`$ git log {MAIN}...{FEATURE}`
zeigt die Änderungen auf beiden Seiten an, also die Commits ``B``,
``C`` und ``D``.
:samp:`$ git log --follow {PATH/TO/FILE}`
Dies sorgt dafür, dass das Log Änderungen an einer einzelnen Datei
anzeigt, auch wenn diese umbenannt oder verschoben wurde.
Ihr könnt ``--follow`` für einzelne Dateiaufrufe standardmäßig
aktivieren, indem ihr die Option ``log.follow`` in eurer globalen
Konfiguration aktiviert:
.. code-block:: console
$ git config --global log.follow true
Dann müsst ihr nicht mehr ``--follow`` angeben, sondern nur noch den
Dateinamen.
``$ git log -L``
Mit der Option `-L
`_
könnt ihr eine verfeinerte Suche durchführen, indem ihr das Log nur eines
Teils einer Datei überprüft:
* :samp:`$ git log -L {LINE_START_INT|LINE_START_REGEX},{LINE_END_INT|LINE_END_REGEX}:{PATH/TO/FILE}`
* :samp:`$ git log -L :{FUNCNAME_REGEX}:{PATH/TO/FILE}`
Mit dieser Funktion könnt ihr die Historie einer einzelnen Funktion, einer
Klasse oder eines anderen Code-Blocks gründlich durchforsten. Sie ist ideal,
um herauszufinden, wann etwas erstellt und wie es geändert wurde, so dass ihr
es getrost korrigieren, refaktorisieren oder löschen könnt.
Für umfassendere Untersuchungen könnt ihr auch mehrere Blöcke verfolgen.
Hierfür könnt ihr mehrere ``-L``-Optionen auf einmal verwenden.
:samp:`$ git log --reverse`
Üblicherweise zeigt das Protokoll den neuesten Commit zuerst an. Ihr
könnt dies mit ``--reverse`` umkehren. Dies ist besonders nützlich, wenn
ihr mit den bereits erwähnten Optionen ``-S`` und ``-G`` untersucht.
Indem ihr die Reihenfolge der Commits umkehrt, könnt ihr schnell den
ersten Commit finden, der eine bestimmte Zeichenfolge zur Codebasis
hinzugefügt hat.
Ansicht
~~~~~~~
:samp:`$ git log --stat --patch|-p`
``--stat``
Den üblichen Metadaten wird noch eine eine Zusammenfassung der Anzahl
der geänderten Zeilen pro Datei hinzugefügt.
``--patch|-p``
ergänzt die Ausgabe um den vollständigen Commit-Diff.
:samp:`$ git log --oneline --decorate --graph --all|{FEATURE}`
anzeigen des Verlaufsdiagramms mit Referenzen, ein Commit pro Zeile.
``--oneline``
Ein Commit pro Zeile.
``--decorate``
Die Präfixe ``refs/heads/``, ``refs/tags/`` und ``refs/remotes/``
werden nicht ausgegeben.
``--graph``
Üblicherweise *glättet* das Log historische Zweige und zeigt Commits
nacheinander an. Damit wird die parallele Struktur der Historie beim
Zusammenführen von Zweigen verborgen. ``--graph`` stellt den Verlauf
der Zweige in ASCII-Art dar.
:samp:`--all|{FEATURE}`
``--all`` zeigt das Log für alle Zweige; :samp:`{FEATURE}` zeigt nur
die Commits dieses Zweiges an.
.. _reflog:
``reflog``
----------
Mit `git reflog `_ wird euer Git-Repository
nicht ein zweites Mal überprüft. Stattdessen zeigt es das Reference-Log an, eine
Aufzeichnung aller vorgenommenen Commits. Das Reflog verfolgt nicht nur
Änderungen an einem Zweig, es zeichnet auch Änderungen am *aktuellen* Commit,
den Wechsel des Zweiges, Rebasing, :abbr:`etc. (et cetera)` auf. Ihr könnt es
benutzen, um alle unerreichbaren Commits zu finden, sogar solche auf gelöschten
Zweigen. Damit könnt ihr viele, ansonsten destruktive Aktionen wieder rückgängig
machen.
Schauen wir uns die Grundlagen der Verwendung von Reflog und einige typische
Anwendungsfälle an.
.. warning::
Das Reflog ist nur Teil eures lokalen Repository. Wenn ihr ein Projektarchiv
löscht und neu klont, wird der neue Klon ein frisches, leeres Reflog haben.
Das Reflog für ``HEAD`` anzeigen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:samp:`$ git reflog`
Wenn keine Optionen angegeben sind, zeigt der Befehl standardmäßig das
Reflog für ``HEAD`` an. Es ist die Abkürzung für ``git reflog show
HEAD``. git reflog hat weitere Unterbefehle zur Verwaltung des Logs, aber
``show`` ist der Standardbefehl, wenn kein Unterbefehl übergeben wird.
.. code-block:: console
:linenos:
$ git reflog
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{0}: merge my-feature-branch: Fast-forward
900844a HEAD@{1}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2}: commit (amend): Add my feature and more
982d93a HEAD@{3}: commit: Add my feature
900844a HEAD@{4}: checkout: moving from main to my-feature-branch
900844a HEAD@{5}: commit (initial): Initial commit
* Die Ausgabe ist ziemlich dicht.
* Jede Zeile ist ein Reflog-Eintrag, der neueste zuerst.
* Die Zeilen beginnen mit dem abgekürzten SHA des entsprechenden Commits,
:abbr:`z.B. (zum Beispiel)` ``12bc4d4``.
* Der erste Eintrag ist das, worauf ``HEAD`` derzeit verweist: ``(HEAD ->
main, my-feature)``.
* Die Namen ``HEAD@\{N}`` sind alternative Referenzen für die angegebenen
Commits. ``N`` ist die Anzahl der zurückgehenden reflog-Einträge.
* Der restliche Text beschreibt die Änderung. Oben könnt ihr mehrere Arten
von Einträgen sehen:
* :samp:`commit: {MESSAGE}` für Commits
* :samp:`commit (amend): {MESSAGE}` für eine Commit-Änderung
* :samp:`checkout: moving from {SRC} TO {DST}` für einen Zweigwechsel
Es gibt viele weitere mögliche Arten von Einträgen. Der Text sollte so
beschreibend sein, dass ihr den Vorgang auch ohne Nachschlagen in der
Dokumentation nachvollziehen könnt. In den meisten Fällen werdet ihr solche
Reflog-Einträge durchsehen wollen, um den entsprechenden Commit SHA zu
finden.
Das Reflog für einen Zweig anzeigen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ihr könnt euch auf Einträge für einen einzelnen Zweig fokussieren, indem ihr den
expliziten Unterbefehl ``show`` und dem Zweignamen verwendet:
.. code-block:: console
$ git reflog show my-feature-branch
12bc4d4 (HEAD -> main, my-feature-branch) my-feature-branch@{0}: commit (amend): Add my feature and more
982d93a my-feature-branch@{1}: commit: Add my feature
900844a my-feature-branch@{2}: branch: Created from HEAD
Zeitstempel der Einträge anzeigen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Wenn ihr zwischen ähnlich betitelten Änderungen unterscheiden müsst, können die
Zeitstempel helfen. Für relative Zeitstempel könnt ihr ``--date=relative``
verwenden:
.. code-block:: console
$ git reflog --date=relative
12bc4d4 (HEAD -> main, my-feature) HEAD@{vor 37 Minuten}: merge my-feature-branch: Fast-forward
900844a HEAD@{vor 37 Minuten}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{vor 37 Minuten}: commit (amend): Add my feature and more
982d93a HEAD@{vor 38 Minuten}: commit: Add my feature
900844a HEAD@{vor 39 Minuten}: checkout: moving from main to my-feature-branch
900844a HEAD@{vor 40 Minuten}: commit (initial): Initial commit
Und für absolute Zeitstempel könnt ihr auch ``--date=iso`` verwenden:
.. code-block:: console
$ git reflog --date=iso
12bc4d4 (HEAD -> main, my-feature) HEAD@{2024-01-11 15:26:53 +0100}: merge my-feature-branch: Fast-forward
900844a HEAD@{2024-01-11 15:26:47 +0100}: checkout: moving from my-feature-branch to main
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2024-01-11 15:26:11 +0100}: commit (amend): Add my feature and more
982d93a HEAD@{2024-01-11 15:25:38 +0100}: commit: Add my feature
900844a HEAD@{2024-01-11 15:24:37 +0100}: checkout: moving from main to my-feature-branch
900844a HEAD@{2024-01-11 15:23:56 +0100}: commit (initial): Initial commit
Übergebt alle Optionen, die ``git log`` unterstützt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``git reflog show`` hat die gleichen Optionen wie ``git log``. So könnt ihr
beispielsweise mit ``--grep`` nach Commit-Meldungen suchen, in denen :samp:`{my
feature}` erwähnt wird, ohne die Groß- und Kleinschreibung zu berücksichtigen:
.. code-block:: console
$ git reflog -i --grep 'my feature'
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{0}: merge my-feature: Fast-forward
12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{2}: commit (amend): Add my feature and more
982d93a HEAD@{3}: commit: Add my feature
Beachtet den Verfall von Einträgen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reflog-Einträge verfallen nach einer gewissen Zeit, wenn Git den automatischen
:abbr:`gc (engl.: Garbage Collection)`-Prozess für euer Repository ausführt.
Diese Verfallszeit wird durch zwei ``gc.*``-Optionen gesteuert:
``gc.reflogExpire``
Die allgemeine Verfallszeit, die standardmäßig auf 90 Tage eingestellt ist.
``gc.reflogExpireUnreachable``
Die Verfallszeit für Einträge, die sich auf nicht mehr erreichbare Commits
beziehen, ist standardmäßig auf 30 Tage eingestellt.
Ihr könnt diese Optionen auf einen längeren Zeitrahmen erhöhen, was allerdings
nur selten sinnvoll sein dürfte.
``fsck``
--------
`git fsck `_ ist der letzte Ausweg wenn ein
Commit nicht mehr im Reflog ist (:abbr:`z. B. (zum Beispiel)` wenn ihr ihn mit
``git stash drop`` *„verloren”*. habt). Mit ``git fsck`` könnt ihr euch alle
Commit-IDs auflisten lassen, auf die nicht verwiesen wird.