1076

I'm playing with Git in isolation on my own machine, and I find it difficult to maintain a mental model of all my branches and commits. I know I can do a git log to see the commit history from where I am, but is there a way to see the entire branch topography, something like these ASCII maps that seem to be used everywhere for explaining branches?

      .-A---M---N---O---P
     /     /   /   /   /
    I     B   C   D   E
     \   /   /   /   /
      `-------------'

It just feels like someone coming along and trying to pick up my repository would have difficulty working out exactly what was going on.

I guess I'm influenced by AccuRev's stream browser...

enharmonic
  • 1,800
  • 15
  • 30
Benjol
  • 63,995
  • 54
  • 186
  • 268

33 Answers33

1302

Use git log --graph or gitk. (Both also accept --all, which will show all the branches instead of just the current one.)

For branch names and a compact view, try:

git log --graph --decorate --oneline
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jrockway
  • 42,082
  • 9
  • 61
  • 86
  • 9
    Thanks! gitg also has the `--all` option and also labels the commits. I also never saw in the dropdown that you can select all branches there. – Thomas Sep 27 '12 at 15:00
  • 2
    --pretty=oneline also comes in pretty handy – Zlatko Dec 01 '13 at 11:02
  • 9
    [tig](https://github.com/jonas/tig) (a ncurse git client) also provides the ``--all`` option. Quite handy ! – Pierre-Adrien Sep 23 '14 at 16:02
  • 6
    See also [answer by Andrew](//stackoverflow.com/questions/1838873/visualizing-branch-topology-in-git#answer-7509303) regarding `--simplify-by-decoration` option. – ruvim Nov 14 '16 at 23:24
  • 2
    throw in a `-n` also. Where `n` is the number of commits you want to limit the log to – aljgom Oct 17 '18 at 05:48
  • 1
    I think `--decorate` seems to be the default now, so it's no longer necessary – Marko Knöbl Dec 25 '19 at 09:38
  • 1
    zsh: command not found: gitk – Andrii Bobrov May 13 '22 at 18:20
  • Is there a way to arrange the log horizontally as opposed to vertically? – user32882 Oct 14 '22 at 10:43
  • Actually `git log --graph --simplify-by-decoration --oneline --all` gets quite close. The `--all` is needed to show other branches and `--simplify-by-decoration` to collapse the linear parts of the history. – Niko Föhr Mar 22 '23 at 14:22
611

I have 3 aliases (and 4 alias-aliases for quick usage) that I normally throw in my ~/.gitconfig file:

[alias]
    lg = lg1
    lg1 = lg1-specific --all
    lg2 = lg2-specific --all
    lg3 = lg3-specific --all

    lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)'
    lg2-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'
    lg3-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n''          %C(white)%s%C(reset)%n''          %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)'

git lg/git lg1 looks like this:

git lg1

git lg2 looks like this:

git lg2

and git lg3 looks like this:

git lg3

It should be noted that this isn't meant as a end-all-be-all solution— it's a template for you to change, add to and fix up to your liking. If you want to use these, my recommendation is to:

  1. Add them to your .gitconfig,
  2. Customize to your liking (different color choices, different line arrangements for the 2- and 3-line versions, etc.),
  3. And then save a copy to a Gist or other code snippet tool so you can copy & paste it into .gitconfigs in the future (or alternatively version control your dotfiles, of course).

Note: Answer copied from and improved upon the answer at stackoverflow.com/questions/1057564/pretty-git-branch-graphs since it's far more appropriate here than it was there.  Left the copy on the other question for historical reasons— it's closed now, and the answer's referenced by a bunch of other answers.

Slipp D. Thompson
  • 33,165
  • 3
  • 43
  • 43
  • 22
    Suggestion: replace `%C(bold yellow)` with `%C(auto)` for having different colours for `HEAD`, *local* and *remote branches* ([ref](http://stackoverflow.com/q/12694510/2247039)). – Atcold Nov 20 '16 at 01:51
  • 1
    @Atcold I'm personally on-the-fence regarding that change— while it does give you those differing colors, they're all inverted colorings (colored background w/ black text), and the punctuation (`(` `)` `,` `->`) ends up dim-white.  **TL;DR: I find Git's `auto`-coloring useful but ugly.**  However, it cannot be understated that these shortcut commands are _meant_ to be customized by the user— everyone who adds these should consider changing colors and flags to best fit their workflow & terminal setup. – Slipp D. Thompson Dec 01 '16 at 19:43
  • @SlippD.Thompson, I'm not sure what you're talking about. To me it looks just fine (see this [image](https://s11.postimg.org/xgeaatj77/git.png)). – Atcold Dec 01 '16 at 19:52
  • @SlippD.Thompson, there is something odd with your configurations. On a fresh Ubuntu install `git log --decorate` looks just fine (see [Google](https://www.google.com/search?q=%22git+log+--decorate%22&espv=2&biw=1855&bih=990&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjUuLOA6dPQAhUI_4MKHZhZC7gQ_AUIBygC)). – Atcold Dec 01 '16 at 20:21
  • @Atcold Yep, I did have `reverse` under my `color.decorate.*` settings.  Oops. – Slipp D. Thompson Dec 01 '16 at 20:56
  • 3
    Note that you can avoid manually adding indentation in your format string by using `%w()`; this way you can also properly line-wrap longer or multi-line commit messages without messing up the graph. – charliegreen Jan 02 '17 at 02:06
  • You can also append this to your ~/.bashrc which I found more powerful for using it in different git repos. – lostcitizen Mar 15 '17 at 10:49
  • @lostcitizen I'm not sure I see the advantage over `~/.gitconfig` (not to be confused with the per-repo `«a-repo-dir»/.git/config`)— both will apply to all git repos on your machine (while logged in with that user account). And if you regularly work across multiple machines, there are a number of tools and solutions out there for syncing all your config `~/.…` dotfiles. – Slipp D. Thompson Mar 15 '17 at 22:29
  • @SlippD.Thompson when I remove `--abbrev-commit --decorate` switches from command lines, I don't see an effect on the output. Are those redundant if `--format` is specified? – mbadawi23 Sep 08 '17 at 21:18
  • I took the liberty to modify `lg3-specific` in @SlippD.Thompson's answer and added this line to my `.gitconfig` to consider line endings in the subject by using `%B` instead of `%s`, and used `%w()` instead of explicit spaces: `lg4-specific = log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n''%C(white)%w(100,10,10)%B%C(reset)''%w(,18,)%C(dim white)- %an <%ae> %C(reset)%n%n'` – mbadawi23 Sep 08 '17 at 21:27
  • 2
    @mbadawi23 They are redundant for the sake of consistency across platform and Git installations.  `--abbrev-commit` is in there because the 2nd-3rd lines are hand-indented with spaces, and I wanted to make absolutely sure that it would use the short SHA— so better safe than sorry.  `--decorate` is also in there because although Git's defaults do the same thing, that could be config'd differently or different in different Git versions— for these, I absolutely want decoration.  Ultimately, extra/redundant flags aren't bad here— this goes in a file; it's not something you type all the time. – Slipp D. Thompson Sep 08 '17 at 21:54
  • I configured these aliases in a Docker image that you can run to display such aliases. Link: https://github.com/ferrarimarco/open-development-environment-git – Marco Ferrari Jan 12 '18 at 15:56
  • combine this with github.com/theZiz/aha and you got a wonderful html git log, you just have to append `--color` to the gitlog command – Jose V May 29 '18 at 08:21
  • How do you know what each branch is? – Timothy Pulliam Apr 08 '19 at 18:13
  • 1
    @TimothyPulliam At the end of each line that represents the tip of each branch/tag, you'll see the associated branch/tag names in parentheses— e.g. in the `lg1` & `lg2` screenshots you can see `(origin/test_on_10.8)` showing the remote branch, and in the `lg2` screenshot you can see `(HEAD -> master, origin/master, origin/HEAD)` showing both local and remote positions of the `master` branch and `HEAD`.  This matches what popular branch-visualizing GUI tools for Git do (gitk, SourceTree, TortoiseGit, Tower, Fork, GitX), though with a bit more verbosity _(some GUI tools use color-coding)_. – Slipp D. Thompson Apr 14 '19 at 06:08
  • 2
    @TimothyPulliam To understand what commits are “part of each branch”, you have to visually trace the colored line.  Nearly every tool doesn't help you much with this because Git commits don't intrinsically belong to any branch— they're implied (at graph-visualization-time) to belong to any branch or tag that has them in their parent-ancestry.  If no branch/tag referencing a commit and it disappears (but isn't garbage-collected for about 2 weeks); add a branch/tag referencing a previously-unreferenced commit and it reappears. I hope this all makes sense. – Slipp D. Thompson Apr 14 '19 at 06:15
  • @SlippD.Thompson An incidental question: what does the "!" symbol do? I read something about delayed expansion of the variables, but in that case two of them are used (!variable!). I also noted that removing it, when the git + alias command is executed the word "git" is taken as part of the command and an error is thrown because "'git' is not a git command". Thank you – Pedro García Medina May 20 '20 at 03:36
  • 3
    @PedroGarcíaMedina I means “run this quoted text as a shell command, rather than calling another git command”, and is designed mainly for integrating other tools with git _(for example, you could write something like `syncup = !"git pull && make all"`)_. I'm using it here because I couldn't call another alias in an alias (I could only call a git command), but maybe that's changed in newer versions of git. I'll double-check it and simplify if it can now be done with just `lg = lg1`. – Slipp D. Thompson May 20 '20 at 03:41
  • 1
    i get the expansion of alias failed error, when i simply copy paste this in my ~/.gitconfig. Am i missing something? – BEvo Nov 22 '20 at 10:57
  • 1
    Vs code extension 'Git Graph' does all of this including many more functions like cherry-pick, merge, revert etc. – utkarsh-k Jun 15 '21 at 05:34
  • @utkarsh-k Exactly. There are many great Git GUI tools out there that will show you a graph view and so much more. I use Fork and love it so much I almost never use these command aliases… however, I keep them in my .gitconfig because they're still handy if you're already on the command line need to look at the commit graph just temporarily, or if you're working on a remote machine via an SSH terminal, or whenever the command line is handier. I don't consider these aliases a “power tool”, just a “handy tool not dissimilar to the GUI you already use”. – Slipp D. Thompson Sep 09 '22 at 14:10
  • About the use of %an %ae: you ignore mailmap entries in this way. Usually they are set for good reason, namely authors/committers changed name or email and want to point users to the correct current information. It would be better to use %aN %aE here, which is also default behaviour for git log. – Emilia Bopp Jun 21 '23 at 11:46
529

I usually use

git log --graph --full-history --all --pretty=format:"%h%x09%d%x20%s"

With colors (if your shell is Bash):

git log --graph --full-history --all --color \
        --pretty=format:"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s"

This will print text-based representation like this:

* 040cc7c       (HEAD, master) Manual is NOT built by default
* a29ceb7       Removed offensive binary file that was compiled on my machine and was hence incompatible with other machines.
| * 901c7dd     (cvc3) cvc3 now configured before building
| * d9e8b5e     More sane Yices SMT solver caller
| | * 5b98a10   (nullvars) All uninitialized variables get zero inits
| |/
| * 1cad874     CFLAGS for cvc3 to work successfully
| *   1579581   Merge branch 'llvm-inv' into cvc3
| |\
| | * a9a246b   nostaticalias option
| | * 73b91cc   Comment about aliases.
| | * 001b20a   Prints number of iteration and node.
| |/
|/|
| * 39d2638     Included header files to cvc3 sources
| * 266023b     Added cvc3 to blast infrastructure.
| * ac9eb10     Initial sources of cvc3-1.5
|/
* d642f88       Option -aliasstat, by default stats are suppressed

(You could just use git log --format=oneline, but it will tie commit messages to numbers, which looks less pretty IMHO).

To make a shortcut for this command, you may want to edit your ~/.gitconfig file:

[alias]
  gr = log --graph --full-history --all --color --pretty=tformat:"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%s%x20%x1b[33m(%an)%x1b[0m"

However, as Sodel the Vociferous notes in the comments, such long formatting command is hard to memorize. Usually, it's not a problem as you may put it into the ~/.gitconfig file. However, if you sometimes have to log in to a remote machine where you can't modify the config file, you could use a more simple but faster to type version:

git log --graph --oneline
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
P Shved
  • 96,026
  • 17
  • 121
  • 165
  • 12
    If you like dates: git log --graph --full-history --all --color --date=short --pretty=format:"%x1b[31m%h%x09%x1b[32m%d%x1b[0m%x20%ad %s" – sehugg Dec 11 '10 at 03:27
  • 7
    --oneline is a more memorable substitute for all that pretty formatting deep-magic. – Daniel Ralston Sep 28 '11 at 04:38
  • 1
    @SodeltheVociferous, indeed, I didn't approach the problem from the side you talk about; I expanded my answer. – P Shved Sep 28 '11 at 07:35
  • 2
    Note: `--full-history` is only relevant when using `--simplify-by-decoration` or specifying a filepath. – Slipp D. Thompson Jun 02 '16 at 19:06
  • 2
    Might I ask where you got the format string from? Or how on earth you concocted that thing? – elliotwesoff Oct 06 '16 at 16:38
  • 1
    @elli0t if you're still wondering 2 years later, see [git log documentation](https://www.git-scm.com/docs/git-log) section "PRETTY FORMATS" a little way down under the "format: " item – Andrew Spencer Jan 24 '20 at 09:42
288

To any of these recipes (based on git log or gitk), you can add --simplify-by-decoration to collapse the uninteresting linear parts of the history. This makes much more of the topology visible at once. I can now understand large histories that would be incomprehensible without this option!

I felt the need to post this because it doesn't seem to be as well-known as it should be. It doesn't appear in most of the Stack Overflow questions about visualizing history, and it took me quite a bit of searching to find--even after I knew I wanted it! I finally found it in this Debian bug report. The first mention on Stack Overflow seems to be this answer by Antoine Pelisse.

Community
  • 1
  • 1
Andrew
  • 5,611
  • 3
  • 27
  • 29
  • 7
    Perfect -- exactly what I was looking for! It should get more upvotes; almost everybody already knows about gitk/gitg/git log --graph, but those are not at all very useful if you want to visualize the branch topology and don't care about single commits. – imolit Mar 04 '14 at 09:39
  • 8
    This is exactly what I needed, fantastic. It's the only thing that helped me, out of all answers. `--simplify-by-decoration` makes so clear what's going on. – Ela782 Jul 23 '15 at 13:07
  • 14
    This should really be the answer. `git log --graph --all --simplify-by-decoration` works as well. – Irfy May 18 '16 at 19:04
  • 1
    If only we could use `--simplify-by-decoration`while adding n commits before/after each deocrated commit (like `-B` and `-A` for `grep`). – junvar Mar 16 '20 at 20:36
  • 1
    I use this solution so frequently I have it aliased as 'git tree'. – user16973 Jun 03 '20 at 13:57
82

Gitk's output is sometimes painful for me to read:

Enter image description here

It motivated me to write GitVersionTree:

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
checksum
  • 6,415
  • 4
  • 36
  • 34
  • 4
    @exhuma I have a PR in with the author to support Mono (tested on Ubuntu 13.10 against Mono 2.10) – Max Ehrlich Mar 13 '14 at 14:45
  • 1
    I've found that GitVersionTree keeps branches in the same place with time, which makes it easier to see how things change. – sfranky Jan 22 '16 at 16:38
  • 2
    Just stumbled on this. It looks really cool; I can't wait t check it out. One suggestion (maybe you already have it), but it could be nice to collapse multiple commits that aren't forking points. That would make it easier to view the branch topology. – Edward Falk Feb 05 '21 at 18:14
61

Take a look at GitKraken - a cross-platform GUI that shows topology in a lucid way.

Topology

Here's a quick video tutorial on some advanced features.

Note: registration is required.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pylang
  • 40,867
  • 14
  • 129
  • 121
  • 13
    How does this thread have GitKraken, but it doesn't have the older and free SourceTree? (I know, I know, Atlassian doesn't always get everything right. But SourceTree is a pretty great tool for visualizing.) – XML May 29 '18 at 22:10
  • @XML It isn't available for Linux. – imashnake_ May 15 '22 at 22:32
  • The same company has also made an extension for Visual Studio Code, called [GitLens](https://www.gitkraken.com/gitlens). It's free, and it doesn't even require registration. – Fabio says Reinstate Monica Jan 18 '23 at 18:40
53

99.999% of my time is looking at history by git lg and the 0.001% is by git log.

I just want to share two log aliases that might be useful (configure from .gitconfig):

[Alias]
     lg = log --graph --pretty=format:'%Cred%h%Creset %ad %s %C(yellow)%d%Creset %C(bold blue)<%an>%Creset' --date=short
     hist = log --graph --full-history --all --pretty=format:'%Cred%h%Creset %ad %s %C(yellow)%d%Creset %C(bold blue)<%an>%Creset' --date=short
  • git lg will see the current branch history.
  • git hist will see the whole branch history.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yeo
  • 11,416
  • 6
  • 63
  • 90
45

I like, with git log, to do:

 git log --graph --oneline --branches

(also with --all, for viewing remote branches as well)

Works with recent Git releases: introduced since 1.6.3 (Thu, 7 May 2009)

  • "--pretty=<style>" option to the log family of commands can now be spelled as "--format=<style>".
    In addition, --format=%formatstring is a short-hand for --pretty=tformat:%formatstring.

  • "--oneline" is a synonym for "--pretty=oneline --abbrev-commit".

PS D:\git\tests\finalRepo> git log --graph --oneline --branches --all
* 4919b68 a second bug10 fix
* 3469e13 a first bug10 fix
* dbcc7aa a first legacy evolution
| * 55aac85 another main evol
| | * 47e6ee1 a second bug10 fix
| | * 8183707 a first bug10 fix
| |/
| * e727105 a second evol for 2.0
| * 473d44e a main evol
|/
* b68c1f5 first evol, for making 1.0

You can also limit the span of the log display (number of commits):

PS D:\git\tests\finalRepo> git log --graph --oneline --branches --all -5
* 4919b68 a second bug10 fix
* 3469e13 a first bug10 fix
* dbcc7aa a first legacy evolution
| * 55aac85 another main evol
| | * 47e6ee1 a second bug10 fix

(show only the last 5 commits)


What I do not like about the current selected solution is:

 git log --graph

It displayed way too much info (when I want only to look at a quick summary):

PS D:\git\tests\finalRepo> git log --graph
* commit 4919b681db93df82ead7ba6190eca6a49a9d82e7
| Author: VonC <vonc@laposte.net>
| Date:   Sat Nov 14 13:42:20 2009 +0100
|
|     a second bug10 fix
|
* commit 3469e13f8d0fadeac5fcb6f388aca69497fd08a9
| Author: VonC <vonc@laposte.net>
| Date:   Sat Nov 14 13:41:50 2009 +0100
|
|     a first bug10 fix
|

gitk is great, but forces me to leave the shell session for another window, whereas displaying the last n commits quickly is often enough.

adl
  • 15,627
  • 6
  • 51
  • 65
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I choose this method also, but I made an alias so that typing "git graph" is the same as executing "git log --graph --decorate --oneline". – Will Pike Aug 16 '14 at 03:04
  • @ConnerPike good idea. I have the alias 'lg' myself: see http://stackoverflow.com/a/3667139/6309 – VonC Aug 16 '14 at 04:22
41

Gitg is a great tool for Linux, similar to Gitx for OS X. Just run 'gitg' on the command line from somewhere inside your repository's tree structure (same with gitx).

jwhb
  • 516
  • 4
  • 19
Jack Senechal
  • 1,600
  • 2
  • 17
  • 20
  • 3
    In so many words: gitg has a drop-down menu where one can chose which branch to visualize. This drop-down also has an "All" option. – Phluks Oct 22 '12 at 13:21
  • 1
    Or you can start it with `gitg --all`, if you want to avoid mucking around in the drop down menu. – imolit Mar 04 '14 at 12:17
29

A nice web based tool is ungit. It runs on any platform that Node.js and Git supports. There is a video of how it works for those that find that sort of things easier than reading...

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sardathrion - against SE abuse
  • 17,269
  • 27
  • 101
  • 156
  • I am using it. Works well on small project - when there are not too many branches. Unfortunately it is unusable with 20-50 open branches – Anton Prokofiev Jul 27 '21 at 10:48
27

I found git-big-picture quite useful.

It creates pretty 2D graphs using dot/Graphviz instead of the rather linear, "one-dimensional" views gitk and friends produce. With the -i option it shows the branch points and merge commits, but leaves out everything in-between.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • It should scale with the number of commits just fine (if you use -i), it might become unreadable if you have complexing branches and merges (but then, which tool doesn't) – Frank Osterfeld Feb 24 '15 at 19:47
  • 1
    With our project of a medium scale, this generates a huge picture with tons of lines. Can I limit the depth it goes to? I.e. commits from last N days or so. – Ondra Žižka Jun 15 '18 at 17:54
27

Have a look at BranchMaster.

I wrote it to visualize a complex branch structure, by collapsing all commits between them to a single line. The numbers indicates the number of commits.

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
stroyer
  • 271
  • 3
  • 4
  • 2
    This is what i'm looking for. Are there alternative commands/tools to do this? – Aalex Gabi Jul 07 '16 at 07:29
  • 3
    @AalexGabi Put this into your gitconfig, it does same thing, but in command line gbranch = log --graph --simplify-by-decoration --pretty=format:'%C(yellow)%h%C(white)%d %C(bold black)%ar %C(reset)%n' --all – kracejic May 03 '17 at 02:24
  • How are you getting the data to visualize the branches? – Snowfish Jan 24 '18 at 03:57
  • My only beef with your app is that it works, but I can't reposition the nodes or scroll around. – FilBot3 Dec 19 '20 at 22:41
25

I found this blog post which shows a concise way:

git log --oneline --abbrev-commit --all --graph --decorate --color

I usually create an alias for the above command:

alias gl='git log --oneline --abbrev-commit --all --graph --decorate --color'

And simply just use gl.

You can also add the alias to the Git configuration. Open file ~/.gitconfig and add the following line to the [alias] section:

[alias]
        lg = log --oneline --abbrev-commit --all --graph --decorate --color

And use it like this:

git lg

Sample output:

enter image description here

Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
Sadegh
  • 2,669
  • 1
  • 23
  • 26
19

I'm using the Visual Studio Code editor, and I found myself very pleased with the Git Graph extension of it, made by mhutchie. (And I'm not alone, there are 1 million users of the extension!).

Enter image description here

If you happened to like the editor, then just go to the extension tab (the cubicles on the left middle) and type in "Git Graph" and install

Enter image description here

To use it, go to the Git control tab and press View Git Graph button

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
klm123
  • 12,105
  • 14
  • 57
  • 95
  • Sadly the main dev of this project at https://github.com/mhutchie/vscode-git-graph seems to have gone awol. The project has been dormant since mid 2021. There is some attempt to move it forward (see https://marketplace.visualstudio.com/items?itemName=hansu.git-graph-2) but mhutchie put a line in the license that makes that action questionable. This is an open issue with GitHub (Q1/23). An Alternate may be a maturing project which some are considering - https://marketplace.visualstudio.com/items?itemName=phil294.git-log--graph - Personally I hope mhutchie opens up the license. – Jay M May 25 '23 at 01:39
  • suggestion: May be worth mentioning that all of vscode-git-graph git-graph-2 and (I assume) git-log--graph do far more than visualize. They all fully integrate into VSCode's IDE and can be used to perform pretty much all the every day tasks you need right from the GUI. Leaving the CLI for the more unusual and complex tasks. Checkin/Checkout/Clone/Merge/Branch/Compare/Revert/Stash git-graph also supports sub-modules I don't know about git-log--graph. – Jay M May 25 '23 at 01:48
18

There is also Tig. It doesn't fold branches like "BranchMaster", but...

It is fast, runs in the terminal.

Because it is so quick (+ keyboard control) you get a great UX. It is almost like my "ls" for directories containing Git repositories.

It has the usual shortcuts, / to search, etc.

The revision graph

(PS: It is the terminal in the background of this screenshot. It looks better nowadays, but my computer refuses to take a screenshot, sorry)

(PPS: I use GitKraken as well, and it has really clear visualisations, but it's much heavier than Tig)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wires
  • 4,718
  • 2
  • 35
  • 31
  • I'm a terminal lover and Tig(text-mode interface for Git) is good tool to interact with Git repositories, it is very useful including graph view and Git history. I recommend it to the terminal lovers as an extra tool to the Git command line. – hermeslm Oct 09 '19 at 15:13
18

For Mac users, check out (no pun intended) the free, open source tool GitUp.

I like the way the graphs are displayed. It's clearer than some of the other tools I've seen.

The project is at GitHub.

GitUp screenshot

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Edward Tan
  • 934
  • 9
  • 17
  • 1
    This is the only graph where you see the branches on the x axis and time on the y axis. It's very intuitive. GitUp is absolutely awesome! macOS isn't, any more, so I'm switching to Windows and will very sorely miss Gitup. – w00t Mar 31 '20 at 15:36
  • Great work. wow - Don't know what "Fixup with Parent" does. a tool tip for these would be great. – Stryker Jun 19 '21 at 11:37
17

Giggle draws really nice graphs.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Renat
  • 417
  • 4
  • 12
  • So does [Grittle](https://github.com/NewAlexandria/grittle), if you use [OmniGraffle](http://www.omnigroup.com/applications/omnigraffle/) – New Alexandria Dec 21 '12 at 05:53
  • Tried it and I see a line per commit and not a line per branch/tag. It's too detailed when you have dozens of branches/tags. – Aalex Gabi Jun 01 '18 at 14:49
15

TortoiseGit has a tool called "Revision Graph". If you're on Windows it's as easy as right clicking on your repository → Tortoise GitRevision Graph.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cSn
  • 2,796
  • 3
  • 23
  • 29
12

I use the following aliases.

[alias]
    lol = log --graph --decorate --pretty=oneline --abbrev-commit
    lola = log --graph --decorate --pretty=oneline --abbrev-commit --all

It has more info in the color scheme than aliases that I saw above. It also seems to be quite common, so you might have a chance of it existing in other's environment or being able to mention it in conversation without having to explain it.

With screenshots and a full description in Git lola.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lokist
  • 242
  • 4
  • 10
12

For those using the VSCode text editor, consider the Git History Extension by D. Jayamanne:

enter image description here

pylang
  • 40,867
  • 14
  • 129
  • 121
  • 1
    this extension is kinda slow in my opinion. It also does not auto update and looks unpolished. But it does a good job visualizing the commit tree... – aljazerzen Jun 28 '18 at 16:13
  • 4
    Another extension for Visual Studio Code is [Git Graph](https://github.com/mhutchie/vscode-git-graph) by mhutchie. I use this along with GitLens. – Josef.B Jun 22 '19 at 11:21
11

I have this git log alias in ~/.gitconfig to view the graph history:

[alias]
l = log --all --graph --pretty=format:'%C(auto)%h%C(auto)%d %s %C(dim white)(%aN, %ar)'

With the alias in place, git l will show something like this:

enter image description here

In Git 2.12+ you can even customize the line colors of the graph using the log.graphColors configuration option.

As for the logs' format, it's similar to --oneline, with the addition of the author name (respecting .mailmap) and the relative author date. Note that the %C(auto) syntax, which tells Git to use the default colors for commit hash, etc. is supported in Git >= 1.8.3.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
9

Gitx is also a fantastic visualization tool if you happen to be on OS X.

kEND
  • 7,379
  • 3
  • 19
  • 13
  • 4
    gitk (for everyone) is very similar. not exactly the same, but pretty similar. – xero Mar 14 '13 at 21:09
  • 1
    There are a couple of forks of Gitx - [this one](http://rowanj.github.io/gitx/) (rowanj) seems to be the best at the moment. – rjmunro Jul 27 '14 at 22:19
9

Another git log command. This one with fixed-width columns:

git log --graph --pretty=format:"%x09%h | %<(10,trunc)%cd |%<(25,trunc)%d | %s" --date=short

Sample output:

enter image description here

Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
David
  • 2,942
  • 33
  • 16
7

Check out SmartGit. It very much reminds me of the TortoiseHg branch visualization and it's free for non-commercial use.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
7

My personal favorite alias, via .gitconfig, is:

graph = log --graph --color --all --pretty=format:"%C(yellow)%H%C(green)%d%C(reset)%n%x20%cd%n%x20%cn%x20(%ce)%n%x20%s%n"

You can test directly from the command line like this:

git log --graph --color --all --pretty=format:"%C(yellow)%H%C(green)%d%C(reset)%n%x20%cd%n%x20%cn%x20(%ce)%n%x20%s%n"

Sample output:

enter image description here

Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
xero
  • 4,077
  • 22
  • 39
7

I found it incredible that among the many answers it is not mentioned Gitviz, available for Window/Linux/Mac
In addition to providing a 2-D view of the branches and commit, it listens your git commands and it modify by itself the graph.

enter image description here

Nick
  • 1,439
  • 2
  • 15
  • 28
  • 1
    I think is only for windows, can you please share links for Mac/Linux ? – nbari Mar 14 '22 at 09:28
  • It is .net, so in theory you could run it using mono on Linux (maybe mono works on Mac too?) But this is probably why not many mention it: From Gitviz GitHub: Release Quality **Alpha**. This entire project so far consists of one Readify guy sitting down the back of a training course and tapping away for a few hours, no more. – Matthew Nov 08 '22 at 21:35
5

I want to share my compact preset for git log command:
(green is my default console color)
Preset preview

It's designed to be as compact and table-like as possible (without adding any excess spaces) while still being informative and easy to read. This is basically a compact version of medium format Git uses by default.

Features:

  • Fixed item positions;
  • Default colors of commit hash and ref names;
  • Commit author date is in local time zone;
  • Commit message is wrapped at 128 characters and indented;
  • Extended commit message is also shown (if any) with any trailing newlines removed.

You can add it into your config file using these commands:
(note that they will change the date format for all git log formats!)

$ git config --global log.date 'format-local:%d %b %Y %H:%M'
$ git config --global pretty.compact '%C(auto)%h %C(cyan)%<(17,trunc)%an%C(auto) %D%n        %C(cyan)%ad%C(auto) %w(128,0,26)%s%w(0,0,26)%+b%-(trailers:key=FAKE)'

... and then use it like so (with --graph, --all or any other options):

$ git log --graph --pretty=compact

If you'd also like to make it default you can do so with this command:

$ git config --global format.pretty compact

Or if you like aliases:

$ git config --global alias.logc "log --date=format-local:'%d %b %Y %H:%M' --pretty='%C(auto)%h %C(cyan)%<(17,trunc)%an%C(auto) %D%n        %C(cyan)%ad%C(auto) %w(128,0,26)%s%w(0,0,26)%+b%-(trailers:key=FAKE)'"

If you'd like to make any changes, see the PRETTY FORMATS section of git log reference.

EvgenKo423
  • 2,256
  • 2
  • 16
  • 23
  • This answer has taught me a lot about fancy formatting capabilities. For example `%+b`. I was going to ask you about what `%-(trailers:key=FAKE)` does but it is clarified near the end of the pretty formats section in the documentation, you can search for `after % of a placeholder`. Not really sure what a FAKE trailer is though. Maybe you could help me out by explaining that. – Steven Lu Nov 11 '22 at 01:45
  • Hi, @StevenLu. This part is a bit of a hack. As you've seems to already figured out, the `%-` prefix is used to remove any trailing newlines here. But the problem is, it only does so "if the placeholder expands to an empty string". I was searching for a placeholder that would _always_ expand to an empty string and the trailers with a non-existent key seems to be the only one. – EvgenKo423 Nov 11 '22 at 11:22
5

Git built-in tools (no add-ons) with date-time formatting

Because the docs are a little obtuse on using the built-in formatting, here's two more example aliases that will work right out of the box.

git tree – Timestamped log of all commits

# Tools for analyzing the merge history of a repo using tree-like graphics
[alias]
    tree = log --no-show-signature --graph --date=format-local:%H:%M:%S --all \
        --pretty="'%C(#ffe97b ul)%h%C(reset) %C(#568ea6)%cs %C(#305f72)%cd%C(reset)%C(auto)%d%C(reset) %s %C(yellow)(%C(reset)%C(#1abc9c)%an%C(reset)%C(yellow),%C(reset) %C(#007055)%cr%C(reset)%C(yellow))%C(reset)'"

git tree

git tree.branches – Timestamped log of all branch/tag commits

# Some refinements to normal 'git tree' output for alternative perspectives.
[alias "tree"]
    branches = tree --simplify-by-decoration

git tree.branches

Color code

Spec Color Style
Commit ID Yellow Underline
Commit date Dark Blue
Commit time Light Blue
Commit message White
Commit Author Green
Commit relative date Dark Green
Remote branches Red
Local branches Purple
Tags Pink Underline
ardnew
  • 2,028
  • 20
  • 29
  • _"None of the existing answers show how to change the date-time format using the built-in `git log` tooling"_ – Well, [my answer](/a/67289484/11725753) does, [two](/q/1838873/11725753#11594406:~:text='-,--date=short&text=--date=short,-git) [other](/q/1838873/11725753#31459695:~:text="-,--date=short) answers use a preset and [another one](/q/1838873/11725753#34467298:~:text=%25aD,-%25C%28reset&text=%25cD,-%29) uses the `%aD`/`%cD` placeholders. Nevertheless, you have a nice example of using different colors for date and time here. ;-) – EvgenKo423 Nov 11 '22 at 15:22
  • 1
    @EvgenKo423 Rescanning the thread, yeah, I have no idea why I said that! My apologies. Removed it from the answer. – ardnew Jul 01 '23 at 14:51
4

The most rated answers are showing git log commands as favorite solutions.

If you need a tablelike, say column-like output, you can use your awesome git log commands with slight modifications and some limitations with the .gitconfig alias.tably snippet below.

Modifications:

  • you have to use %><(<N>[,ltrunc|mtrunc|trunc]) before every commit placeholder
  • add a unique delimiter as column separator
  • add --color option for colored output

Limitations:

  • you can place the CPU graph at every column as long as you do not use non-empty newlines %n...

  • the last commit placeholder of any newline can be used without %><(<N>[,trunc])

  • if extra characters are needed for decoration like (committer: , < and >) in

    ...%C(dim white)(committer: %cn% <%ce>)%C(reset)...

    to get a tablelike output they must be written directly before and after the commit placeholder

    ...%C(dim white)%<(25,trunc)(committer: %cn%<(25,trunc) <%ce>)%C(reset)...

  • if the --format=format: option is not the last one close it with %C(reset) as mostly done

  • compared to normal git log output this one is slow, but nice

Example taken from this site:

thompson1     = log --all --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)'

will be with ^ as delimiter and without added characters

thompson1-new = log --all --graph --color --abbrev-commit --decorate --format=format:'^%C(bold blue)%<(7,trunc)%h%C(reset)^%C(bold green)%<(21,trunc)%ar%C(reset)^%C(white)%<(40,trunc)%s%C(reset)^%C(dim white)%<(25,trunc)%an%C(reset)^%C(auto)%d%C(reset)'

which compares like

Enter image description here

Enter image description here

Or with moving the graph to column 5:

Enter image description here

To achieve this, add the following to your .gitconfig file and call your log alias with git tably YourLogAlias:

[color "decorate"]
    HEAD = bold blink italic 196
    branch = 214
    tag = bold 222

[alias]

    # delimiter used as column seperator
    delim = ^
    # example thompson1
    thompson1     = log --all --graph         --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)'
    # modified thompson1 example
    thompson1-new = log --all --graph --color --abbrev-commit --decorate --format=format:'^%C(bold blue)%<(7,trunc)%h%C(reset)^%C(bold green)%<(21,trunc)%ar%C(reset)^%C(white)%<(40,trunc)%s%C(reset)^%C(dim white)%<(25,trunc)%an%C(reset)^%C(auto)%d%C(reset)'
    # set a column for the graph
    thompson1-new-col = 1

tably     = !bash -c '"                                                                                                              \
              declare -A col_length;                                                                                                 \
              delim=$(git config alias.delim);                                                                                       \
              git_log_cmd=$(git config alias.$1);                                                                                    \
              git_tre_col=${2:-$(git config alias.$1-col)};                                                                          \
                                                                                                                                     \
              i=0;                                                                                                                   \
              n=0;                                                                                                                   \
              while IFS= read -r line; do                                                                                            \
                ((n++));                                                                                                             \
                while read -d\"$delim\" -r col_info;do                                                                               \
                  ((i++));                                                                                                           \
                  [[ -z \"$col_info\" ]] && col_length[\"$n:$i\"]=${col_length[\"${last[$i]:-1}:$i\"]} && ((i--)) && continue;       \
                  [[ $i -gt ${i_max:-0} ]] && i_max=$i;                                                                              \
                  col_length[\"$n:$i\"]=$(grep -Eo \"\\([0-9]*,[lm]*trunc\\)\" <<< \"$col_info\" | grep -Eo \"[0-9]*\" | head -n 1); \
                  [[ -n \"${col_length[\"$n:$i\"]}\" ]] && last[$i]=$n;                                                              \
                  chars_extra=$(grep -Eo \"\\trunc\\).*\" <<< \"$col_info\");                                                        \
                  chars_extra=${chars_extra#trunc)};                                                                                 \
                  chars_begin=${chars_extra%%\\%*};                                                                                  \
                  chars_extra=${chars_extra#*\\%};                                                                                   \
                  case \" ad aD ae aE ai aI al aL an aN ar as at b B cd cD ce cE ci cI cl cL cn cN cr                                \
                          cs ct d D e f G? gd gD ge gE GF GG GK gn gN GP gs GS GT h H N p P s S t T \" in                            \
                   *\" ${chars_extra:0:2} \"*)                                                                                       \
                     chars_extra=${chars_extra:2};                                                                                   \
                     chars_after=${chars_extra%%\\%*};                                                                               \
                     ;;                                                                                                              \
                   *\" ${chars_extra:0:1} \"*)                                                                                       \
                     chars_extra=${chars_extra:1};                                                                                   \
                     chars_after=${chars_extra%%\\%*};                                                                               \
                     ;;                                                                                                              \
                   *)                                                                                                                \
                     echo \"No Placeholder found. Probably no tablelike output.\";                                                   \
                     continue;                                                                                                       \
                     ;;                                                                                                              \
                  esac ;                                                                                                             \
                  if [[ -n \"$chars_begin$chars_after\" ]];then                                                                      \
                    len_extra=$(echo \"$chars_begin$chars_after\" | wc -m);                                                          \
                    col_length["$n:$i"]=$((${col_length["$n:$i"]}+$len_extra-1));                                                    \
                  fi;                                                                                                                \
                                                                                                                                     \
                done <<< \"${line#*=format:}$delim\";                                                                                \
                i=1;                                                                                                                 \
              done <<< \"$(echo -e \"${git_log_cmd//\\%n/\\\\n}\")\";                                                                \
                                                                                                                                     \
              while IFS= read -r graph;do                                                                                            \
                chars_count=$(sed -nl1000 \"l\" <<< \"$graph\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l);           \
                [[ ${chars_count:-0} -gt ${col_length["1:1"]:-0} ]] && col_length["1:1"]=$chars_count;                               \
              done < <([[ -n \"$(grep -F graph <<< \"$git_log_cmd\")\" ]] && git log --all --graph --pretty=format:\" \" && echo);   \
                                                                                                                                     \
              l=0;                                                                                                                   \
              while IFS= read -r line;do                                                                                             \
                c=0;                                                                                                                 \
                ((l++));                                                                                                             \
                [[ $l -gt $n ]] && l=1;                                                                                              \
                while IFS= read -d\"$delim\" -r col_content;do                                                                       \
                  ((c++));                                                                                                           \
                  if [[ $c -eq 1 ]];then                                                                                             \
                    [[ -n \"$(grep -F \"*\" <<< \"$col_content\")\" ]] || l=2;                                                       \
                    chars=$(sed -nl1000 \"l\" <<< \"$col_content\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l);       \
                    whitespaces=$((${col_length["1:1"]}-$chars));                                                                    \
                    whitespaces=$(seq -s\" \" $whitespaces|tr -d \"[:digit:]\");                                                     \
                    col_content[1]=\"${col_content[1]}$col_content$whitespaces\n\";                                                  \
                  else                                                                                                               \
                    col_content[$c]=\"${col_content[$c]}$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\n\";      \
                  fi;                                                                                                                \
                done <<< \"$line$delim\";                                                                                            \
                for ((k=$c+1;k<=$i_max;k++));do                                                                                      \
                  empty_content=\"$(printf \"%-${col_length[\"$l:$k\"]:-${col_length[\"${last[$k]:-1}:$k\"]:-0}}s\" \"\")\";         \
                  col_content[$k]=\"${col_content[$k]}$empty_content\n\";                                                            \
                done;                                                                                                                \
              done < <(git $1 && echo);                                                                                              \
                                                                                                                                     \
              while read col_num;do                                                                                                  \
                if [[ -z \"$cont_all\" ]];then                                                                                       \
                  cont_all=${col_content[$col_num]};                                                                                 \
                else                                                                                                                 \
                  cont_all=$(paste -d\" \" <(echo -e \"$cont_all\") <(echo -e \"${col_content[$col_num]}\"));                        \
                fi;                                                                                                                  \
              done <<< $(seq 2 1 ${git_tre_col:-1};seq 1;seq $((${git_tre_col:-1}+1)) 1 $i_max);                                     \
              echo -e \"$cont_all\";                                                                                                 \
              "' "git-tably"

This is more or less only a part of my answer https://stackoverflow.com/a/61487052/8006273 where you can find deeper explanations, but nicely fits to this question here too.

If there are problems with your git log commands leave a comment.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
onemorequestion
  • 1,056
  • 1
  • 10
  • 15
3

On Windows there is a very useful tool you can use: Git Extensions. It's a GUI tool and makes Git operations very easy.

Also it's open sourced.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
loneshark99
  • 706
  • 5
  • 16
2

I've tried --simplify-by-decoration but all my merges are not shown. So I instead just prune off lines with no "\" and "/" symbols at the headers, while always keeping lines with "(" indicating branches immediately after that. When showing branch history I'm in general uninterested in commit comments, so I remove them too. I end up with the following shell alias.

gbh () { 
    git log --graph --oneline --decorate "$@" | grep '^[^0-9a-f]*[\\/][^0-9a-f]*\( [0-9a-f]\|$\)\|^[^0-9a-f]*[0-9a-f]*\ (' | sed -e 's/).*/)/'
}
Isaac To
  • 131
  • 1
  • 5
1

Git's official site enlisted some third-party platform specific GUI tools. Open Git GUI Tools for Linux Platform.

I have used gitg and GitKraken for the Linux platform. Both are good for understanding the commit tree.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rookie4evr
  • 53
  • 6
1

For those of you that work in VIM anyway, gv.vim may be interesting. That's what I use directly from within VIM that also enables to conveniently browse through the commit history and check the specific changes.

This is the screenshot directly from gv.vim's Github page:

enter image description here

The specific style depends on the utilized color theme.

Wolfson
  • 1,187
  • 17
  • 22