Read Git Branch History Clearly with git show-branch

git show-branch draws branch ancestry as compact ASCII columns, so you can see at a glance which commits two branches share and which they do not. It also lists branch tips on their own, finds commits unique to one branch, spots possible merge bases and reads recent reflog entries. The examples use Git 2.43.0 from Ubuntu package git-man 1:2.43.0-1ubuntu7.3. Allow about fifteen minutes. You need a Git repository with at least two refs; all commands here are ordinary, read-only inspection and do not need elevated privileges.

Checkpoint: Confirm the version before relying on output details:

$ git --version
git version 2.43.0

1. Compare two branch tips

Run the command with the branch names you want to understand:

$ git show-branch main topic
! [main] main change
 * [topic] topic change
--
 * [topic] topic change
+  [main] main change
+* [topic^] base

The first line for each ref names its tip. The current branch gets *; other branch tips get !. In the ancestry section, each column belongs to one argument. A + means that the commit is reachable from that branch, while a blank means it is not. The short name in square brackets, such as topic^, is another revision expression you can pass to Git.

Do not read the leading marks as a quality judgement. They describe reachability, not which branch is newer or safer to merge. Merge commits use a - marker, and the default display can stop at a common ancestor. If the result is difficult to scan, make the ordering explicit:

$ git show-branch --topo-order main topic

--topo-order keeps descendants before their parents. --date-order also respects ancestry, but otherwise follows commit dates. Neither option changes commits or branch pointers.

2. Limit the view to branch tips

When you only need a quick list of the supplied refs, use --list:

$ git show-branch --list main topic
  [main] main change
* [topic] topic change

This is a useful first check before examining a noisy graph. The option is an alias for --more=-1, so it deliberately omits the ancestry tree. It is mutually exclusive with --more, --independent and --merge-base. Pick one purpose per invocation rather than combining these switches.

To include refs that are not named individually, use a glob or ask for all local and remote-tracking branches:

$ git show-branch 'topic/*'
$ git show-branch --all
$ git show-branch --remotes

Quote a glob so the shell passes it to Git unchanged. --remotes shows remote-tracking branches. --all includes both local branches and remote-tracking branches. The command has a limit on how many branches and commits it can show; this installed 2.43.0 manual states 29. Reduce a large view with an explicit glob or a smaller set of refs.

3. Find commits that are not shared

Use --topics when the first ref is the main line and the remaining refs are topics:

$ git show-branch --topics main topic

This hides commits already reachable from the first branch. It is a visual form of the useful question, "what does this topic add beyond main?" It does not calculate a patch, test the code or prove that a merge will be conflict-free.

For a machine-friendly answer containing only the independent tips, use --independent:

$ git show-branch --independent main topic
<commit-id-for-main>
<commit-id-for-topic>

The output contains object names, not branch labels. A ref is independent when no other supplied ref can reach it. If one branch contains another, only the containing tip remains. Replace the placeholder output above with the actual IDs from your repository; do not compare the length of IDs or assume their order is meaningful.

4. Find a possible merge base

Ask for merge bases when the question is where the supplied histories meet:

$ git show-branch --merge-base main topic
<common-ancestor-commit-id>

This mode prints possible merge-base object IDs instead of the commit graph. Several IDs can be returned when the history has criss-cross merges, so scripts must be prepared for more than one line. The result is specifically for the commits you supplied. It is not interchangeable with every invocation of git merge-base, especially when three or more commits are involved.

Safety boundary: These commands inspect history only. Do not follow a merge-base result by running git merge, git reset or git rebase unless you have reviewed the target branch and have a recovery plan. Those operations can change the working tree or branch history.

5. Inspect recent movement with the reflog

The reflog mode answers a different question: which recent values has a ref had? List entries without drawing ancestry:

$ git show-branch --reflog=5 --list main
  [main@{0}] commit: main change
  [main@{1}] checkout: moving from topic to main

Reflog entries are local records and their contents depend on the repository's recent activity. --reflog=5 requests the five most recent entries. You can give a base as well, for example --reflog="10,1 hour ago", to count backwards from a time-relative entry. Without an explicit ref, Git uses the current branch, or HEAD when the repository is detached.

Reflogs are not a remote audit trail. They can expire under repository housekeeping, and another clone has a different reflog. Treat the displayed dates and messages as local evidence, then verify an object with git show before using it for recovery.

6. Make output easier to script and review

Use --no-name to suppress naming strings on commits, or --sha1-name to label commits with unique object-name prefixes instead of expressions such as main~2. Capture a reviewable graph in a temporary file when you need to inspect it more than once:

$ git show-branch --topo-order main topic > /tmp/branch-history.txt
$ sed -n '1,12p' /tmp/branch-history.txt

The temporary file is outside the repository and the command changes no Git state. If you need to discard it later, remove only that known file after checking its contents. Do not use a broad wildcard in a cleanup command.

If you run git show-branch without refs, its selection comes from multi-valued showbranch.default configuration. For example, this configuration asks for primary branches and topological ordering:

[showbranch]
        default = --topo-order
        default = heads/*

Inspect before changing it:

$ git config --get-all showbranch.default

If an unqualified command shows unexpected branches, explicit refs are clearer. To undo a configuration value that you deliberately added, remove only that key with git config --unset-all showbranch.default and check the exit status. This is the one state-changing command in the guide, so do not run it unless you know the values came from your configuration scope.

Done means