Skip to content

Command: git smartlog

kain88-de edited this page May 4, 2024 · 124 revisions

Description

Available since v0.1.0.

The smartlog is a graphical representation of your commit graph. Unlike git log --graph, it's focused around commits you've made, rather than all of the commits in your repository. Here's what it looks like:

The smartlog

The smartlog is useful for people who work with many commits or branches as part of their development workflow, especially if they frequently edit those commits (such as with git commit --amend or git rebase -i).

The smartlog also shows commits which don't have branches attached this them, hence the name git-branchless. This is useful for managing many commits without having to "name" them with a branch. See Branchless commits.

Usage

Use git smartlog (aliased to git sl by default) to render the smartlog. If you didn't have any branches other than master, it would look something like this:

$ git sl
⋮
◆ 86bdeac0 47d (master) Revert "Update foo"

Observe that the following pieces of information are shown:

  • An icon in the commit graph indicating the kind of commit. See Public commits.
  • The commit hash. You can use this with git checkout/git switch, or other operations such as git move.
  • The relative timestamp of when the commit was made (in this case, 47 days ago).
  • Any branches pointing to the commit, indicated in parentheses.
  • The commit message summary.
  • The ellipsis above the icon on the left indicates that there are ancestor commits which are not shown.

Once you make some commits, they should show up in the smartlog:

$ git sl
⋮
◇ 86bdeac0 47d (master) Revert "Update foo"
┃
● 8d4738cd 1d new message

As you can see, child commits are rendered below their parents in the smartlog.

Public commits

git-branchless expects your repository to have a main branch. The commit pointed to by the main branch, plus all of its ancestor commits, are considered "public" commits. In contrast, commits which you've been working on locally and haven't been checked into the main branch are considered "draft" commits. (This terminology comes from Mercurial).

The smartlog aims to show all of your draft commits, and only as many public commits are needed for context. The following icons are used in the smartlog.

  • Public commits are marked with a diamond icon: .
    • The mnemonic is that published history shouldn't be rewritten, and instead should be considered immutable. A diamond is hard and unyielding, which also evokes immutability.
  • Draft commits are marked with a circle icon: .
  • Under some circumstances, you may see a hidden commit, marked with an x icon: .
    • Ordinarily, hidden commits are not visible in the smartlog. Its presence in the smartlog usually means that you should fix it somehow, such as by rebasing its descendant commits. See Abandoned children.

Branchless commits

To start a new line of work, most Git users start a new branch. With git-branchless, you can skip creating a branch when making commits by making use of Git's "detached HEAD" mode.

There are a few main ways to enter detached HEAD mode in the branchless workflow:

  • By running git checkout <hash>/git switch --detach <hash> with a commit hash, such as one copied from the smartlog.
  • By running git checkout --detach <branch>/git switch --detach <branch>.
  • By running a convenience command such as git next/git prev.

Branchless commits enable powerful workflows, such as Divergent development.

Custom queries

Available since v0.4.0.

git smartlog takes an optional argument specifying a revset expression of commits to display. For example, to only display commits which are ancestors of branches, you can run:

$ git smartlog 'branches()'

Note Until v0.6.0, the rendered commits always include branches and their ancestors. See #492.

Default revset

The default revset used by the smartlog is as follows:

((draft() | branches() | @) % main()) | branches() | @

Which commits are visible?

In some cases, a commit may appear in the smartlog without a clear reason. The precise logic is defined by the default revset above.

In words, a commit is visible in the smartlog if one of the following conditions applies:

  • The commit is currently checked out.
  • A branch is pointing to that commit.
  • You committed it, and it hasn't been rewritten or manually hidden.
    • Since Git commits are immutable, such an operation involves hiding the old commit and showing the new one.
    • git commit --amend is an example of a rewrite operation.
  • It has a visible descendant commit other than the main branch commit.
  • It's a public commit, but has been rewritten or manually hidden.

Some cases of note:

  • Your commits which have been committed to the main branch and are now public won't appear in the smartlog anymore.
    • You can still use git log to view commits to the main branch.
  • Commits made before running git branchless init won't appear in the smartlog.
    • The easiest way to force a commit to appear is to make a branch pointing to it, or to run git unhide <hash>.
  • Commits made by you, but authored by someone else, will still appear in the smartlog.
Clone this wiki locally