.. SPDX-FileCopyrightText: 2020 Veit Schiele .. .. SPDX-License-Identifier: BSD-3-Clause Review ====== ``log`` ------- .. seealso:: * `Git’s Database Internals III: File History Queries `_ Filter and sort ~~~~~~~~~~~~~~~ .. glossary:: :samp:`$ git log [-n {COUNT}]` lists the commit history of the current branch. ``-n`` limits the number of commits to the specified number. :samp:`$ git log [--after="{YYYY-MM-DD}"] [--before="{YYYY-MM-DD}"]` Commit history filtered by date. Relative specifications such as ``1 week ago`` or ``yesterday`` are also permitted. :samp:`$ git log --author="{VEIT}"` filters the commit history by author. It is also possible to search for several authors at the same time, for example: :samp:`$ git log --author="{VEIT\|VSC}"` :samp:`$ git log --grep="{TERM}" [-i]` filters the commit history for regular expressions in the commit message. ``-i`` ignores upper and lower case. :samp:`$ git log -S"{FOO}" [-i]` filters commits for specific lines in the source code. ``-i`` ignores upper and lower case. :samp:`$ git log -G"{BA*}"` filters commits for regular expressions in the source code. :samp:`$ git log -- {PATH}` filters the commit history for specific files. :samp:`$ git log {MAIN}..{FEATURE}` filters for different commits in different branches, in our case between the :samp:`MAIN` and :samp:`FEATURE` branches. However, this is not the same as :samp:`git log {FEATURE}..{MAIN}`. Let’s take the following example: .. code-block:: A - B main \ C - D feature :samp:`$ git log {MAIN}..{FEATURE}` shows changes in :samp:`{FEATURE}` that are not contained in :samp:`{MAIN}`, that is, commits ``C`` and ``D``. :samp:`$ git log {FEATURE}..{MAIN}` shows changes in :samp:`{MAIN}` that are not contained in :samp:`{FEATURE}`, that is, commit ``B``. :samp:`$ git log {MAIN}...{FEATURE}` shows the changes on both sides, that is, commits ``B``, ``C`` and ``D``. :samp:`$ git log --follow {PATH/TO/FILE}` This ensures that the log shows changes to a single file, even if it has been renamed or moved. You can activate ``--follow`` for individual file calls by default by activating the ``log.follow`` option in your global configuration: .. code-block:: console $ git config --global log.follow true Then you no longer have to enter ``--follow``, but only the file name. :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}` With the `-L `_ option, you can perform a refined search by checking the log of only part of a file. This function allows you to thoroughly search through the history of a single function, class or other code block. It is ideal for finding out when something was created and how it was changed so that you can correct, refactor or delete it with confidence. For more comprehensive investigations, you can also track multiple blocks. You can use multiple ``-L`` options at once. :samp:`$ git log --reverse` The log usually displays the latest commit first. You can reverse this with ``--reverse``. This is particularly useful if you are analysing with the ``-S`` and ``-G`` options already mentioned. By reversing the order of the commits, you can quickly find the first commit that added a specific string to the codebase. View ~~~~ .. glossary:: :samp:`$ git log --stat --patch|-p` ``--stat`` A summary of the number of changed lines per file is added to the usual metadata. ``--patch|-p`` adds the complete commit diff to the output. :samp:`$ git log --oneline --decorate --graph --all|{FEATURE}` display the history graph with references, one commit per line. ``--oneline`` One commit per line. ``--decorate`` The prefixes ``refs/heads/``, ``refs/tags/`` and ``refs/remotes/`` are not output. ``--graph`` The log usually smoothes historical branches and displays commits one after the other. This hides the parallel structure of the history when merging branches. ``--graph`` displays the history of the branches in ASCII format. :samp:`--all|{FEATURE}` ``--all`` shows the log for all branches; :samp:`{FEATURE}` only shows the commits of this branch. .. _reflog: ``reflog`` ---------- With `git reflog `_, your Git repository is not checked a second time. Instead, it displays the reference log, a record of all commits made. The reflog not only tracks changes to a branch, it also records changes to the current commit, branch changes, rebasing, :abbr:`etc. (et cetera)` You can use it to find all unreachable commits, even those on deleted branches. This allows you to undo many otherwise destructive actions. Let’s look at the basics of using reflog and some typical use cases. .. warning:: The reflog is only part of your local repository. If you delete a repository and clone it again, the new clone will have a fresh, empty reflog. Show the reflog for ``HEAD`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. glossary:: :samp:`$ git reflog` If no options are specified, the command displays the reflog for ``HEAD`` by default. It is short for ``git reflog show HEAD``. git reflog has other subcommands to manage the log, but show is the default command if no subcommand is passed. .. 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 * The output is quite dense. * Each line is a reflog entry, the most recent first. * The lines start with the abbreviated SHA of the corresponding commit, for example ``12bc4d4``. * The first entry is what ``HEAD`` currently refers to: ``(HEAD -> main, my-feature)``. * The names ``HEAD@\{N}`` are alternative references for the specified commits. ``N`` is the number of returning reflog entries. * remaining text describes the change. Above you can see several types of entries: * :samp:`commit: {MESSAGE}` for commits * :samp:`commit (amend): {MESSAGE}` for a commit change * :samp:`checkout: moving from {SRC} TO {DST}` for a branch change There are many other possible types of entries. The text should be descriptive enough that you can understand the process without looking it up in the documentation. In most cases, you will want to look through such reflog entries to find the corresponding commit SHA. Show the reflog for a branch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can focus on entries for a single branch by using the explicit subcommand ``show`` and the branch name: .. 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 Show timestamps of the entries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you need to distinguish between similarly titled changes, the timestamps can help. For relative timestamps you can use ``--date=relative``: .. code-block:: console $ git reflog --date=relative 12bc4d4 (HEAD -> main, my-feature) HEAD@{37 minutes ago}: merge my-feature-branch: Fast-forward 900844a HEAD@{37 minutes ago}: checkout: moving from my-feature-branch to main 12bc4d4 (HEAD -> main, my-feature-branch) HEAD@{37 minutes ago}: commit (amend): Add my feature and more 982d93a HEAD@{38 minutes ago}: commit: Add my feature 900844a HEAD@{39 minutes ago}: checkout: moving from main to my-feature-branch 900844a HEAD@{40 minutes ago}: commit (initial): Initial commit And for absolute timestamps you can also use ``--date=iso``: .. 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 Passes all options that ``git log`` supports ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``git reflog show`` has the same options as ``git log``. For example, you can use ``--grep`` to search for commit messages that mention :samp:`{my feature}` without case-sensitivity: .. 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 Note the expiry of entries ~~~~~~~~~~~~~~~~~~~~~~~~~~ Reflog entries expire after a certain time when Git runs the automatic :abbr:`gc (garbage collection)` process for your repository. This expiration time is controlled by two ``gc.*`` options: ``gc.reflogExpire`` The general expiration time, which is set to 90 days by default. ``gc.reflogExpireUnreachable`` The expiry time for entries relating to commits that can no longer be reached is set to 30 days by default. You can increase these options to a longer time frame, but this is rarely useful.