I've seen some books and articles have some really pretty looking graphs of Git branches and commits. How can I make high-quality printable images of Git history?
Update: I've posted an improved version of this answer to the Visualizing branch topology in Git [1] question, since it's far more appropriate there. Leaving this answer for historical (& rep, I'll admit) reasons, though I'm really tempted to just delete it.
My two cents: I have two aliases I normally throw in my ~/.gitconfig
file:
[alias]
lg1 = 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)' --all
lg2 = 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)'
lg = lg1
git lg
/git lg1
looks like this:
and git lg2
looks like this:
(Note: There now exists much more applicable answers to this question, such as fracz's [2], Jubobs' [3], or Harry Lee's [4]!)
[1] https://stackoverflow.com/questions/1838873/visualizing-branch-topology-in-git/34467298#34467298#202020
/#555555
, Red: #5d1a14
/#da4939
, Green: #424e24
/#a5c261
, Yellow: #6f5028
/#ffc66d
, Blue: #263e4e
/#6d9cbe
, Magenta: #3e1f50
/#a256c7
, Cyan: #234e3f
/#62c1a1
, and White: #979797
/#ffffff
. - Slipp D. Thompson
--decorate
option uses the short ref
names. - hIpPy
--date=relative
and --abbrev-commit
are redundant because you explicitly use %cr
and %h
, respectively. - graywh
!"echo 'ran lg1'"
and lg2 as !"echo 'ran lg2'"
. - Slipp D. Thompson
Preferences›Settings»Text›ANSI Colors
. - Slipp D. Thompson
git-config
. And for the 5% that don't— they really should be focused more on learning git and have a GUI for visualizations like this this rather than customizing their CLI. Honestly, I suggest anyone not already familiar with their .gitconfig
file shouldn't be putting snippets found on the interwebs in there. - Slipp D. Thompson
%C(auto)
modifier to the refnames (%d
) to get nicer colors. See stackoverflow.com/questions/5889878/color-in-git-log/… - Josef Eisl
lg = log --graph --abbrev-commit --decorate --format=format:'%C(yellow)%h%C(reset)%C(auto)%d%C(reset) %C(normal)%s%C(reset) %C(dim white)%an%C(reset) %C(dim blue)(%ar)%C (reset)' --all
- Craig P. Motlin
~/.gitconfig
file here: gist.github.com/capnslipp/859701 - Slipp D. Thompson
git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)%aD%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
- parasrish
--color
to the gitlog command - Jose V
lg1
: git config --global alias.lg1 "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(bold yellow)%d%C(reset)' --all"
- Sma Ma
glog
alias if on zsh and oh-my-zsh - Eduardo Pignatelli
!
in lg = !"git lg1"
? - mfaani
!"…"
syntax jumps over that limitation (as well as allowing you to use any combination of CLI stuff you want, like sed or grep). - Slipp D. Thompson
git init
to reload the ~/.gitconfig
so that you can run git <alias-cmd>
- Ramesh
%C(dim white)
doesn't work for me so I'm replacing it with %C(brightblack)
- DustInComp
git init
creates a new repository in the working directory. Also, all git commands reload ~/.gitconfig
automatically. If you do want to make sure Git has picked up changes to your ~/.gitconfig
, try checking the results of git config --global --list
instead. - Slipp D. Thompson
Many of the answers here are great, but for those that just want a simple one-line-to-the-point answer without having to set up aliases or anything extra, here it is:
git log --all --decorate --oneline --graph
Not everyone would be doing a git log
all the time, but when you need it just remember:
"A Dog" = git log --all --decorate --oneline --graph
If you enter
git config --global alias.adog "log --all --decorate --oneline --graph"
at the command prompt once, you can use
git adog
from that prompt even if you close and reopen it.
git config --global alias.adog "log --all --decorate --oneline --graph"
- fracz
--graph --oneline --all --decorate
. - emallove
git log --all --decorate --oneline --graph --stat
- R Brill
--all
for an emberassing amount of time but didn't know it exists... - emremrah
gloga
. (the decorate
is not longer needed, so oga is enough) - peter_v
--decorate
when we pass git log
to a pager e.g. watch git log
- M Imam Pratama
--all
so they needs to be excluded: git config --global alias.adog "log --exclude=refs/notes/tests/* --all --decorate --oneline --graph"
(NB, any --exclude
pattern needs to come before --all
). - hlovdal
decorate
is no longer needed as I noted earlier, if you are piping this command into less -R
, (because it is part of a larger script), you should still include --decorate
and also --color
But how do I git a C dog? :-) - Josiah Yoder
git "adog"
brought me here without delay. Awesome - mrbolichi
--all
option as that gives me just the commits relevant to my current branch as I would see if I run gitk
. This also nicely reduces it down to git dog
🐶 - icc97
--all
option is explained by man git-rev-list
- Rémy Hosseinkhan Boucher
For textual output you can try:
git log --graph --abbrev-commit --decorate --date=relative --all
Or:
git log --graph --oneline --decorate --all
Or: here's [1] a Graphviz [2] alias for drawing the DAG [3] graph.
I personally use
gitx
[4], gitk --all
and
gitnub
[5].
oneline
) version most of the time, but if I need more details use the long version with full commit details. Then I have two nice mappings of <leader>gl
(short) and <leader>gll
(long) in Vim. - icc97
Author
section? - alper
Gitgraph.js [1] allows to draw pretty Git branches without a repository. Just write a JavaScript code that configures your branches and commits and render it in the browser. Interactive docs [2] are available.
var gitGraph = new GitGraph({
template: "blackarrow",
mode: "compact",
orientation: "horizontal",
reverseArrow: true
});
var master = gitGraph.branch("master").commit().commit();
var develop = gitGraph.branch("develop").commit();
master.commit();
develop.commit().commit();
develop.merge(master);
Or with metro
template:
Or with commit messages, authors, and tags:
Test it with JSFiddle [3].
Generate it with Git Grapher [4] by @bsara.
[1] https://github.com/nicoespeon/gitgraph.js/gitgraph.min.js
link no longer works in the jsfiddle. There are other hostings of the script, at your own risk: stackoverflow.com/q/48106879/521799 - Lukas Eder
orientation: "verticalreverse"
for the "usual" rendering. See nicoespeon.com/gitgraph.js/stories/?path=/story/… for details. - koppor
Built on top of
TikZ & PGF
[1],
gitdags
[2] is a little LaTeX package that allows you to effortlessly produce vector-graphics commit graphs, and more.
Automatic generation of an existing repository's commit graph is not the purpose of
gitdags
[3]; the graphs it produces are only meant for educational purposes.
I often use it to produce graphs for my answers to Git questions, as an alternative to ASCII commit graphs:
Here is an example of such a graph demonstrating the effects of a simple rebase:
\documentclass{article}
\usepackage{subcaption}
\usepackage{gitdags}
\begin{document}
\begin{figure}
\begin{subfigure}[b]{\textwidth}
\centering
\begin{tikzpicture}
% Commit DAG
\gitDAG[grow right sep = 2em]{
A -- B -- {
C,
D -- E,
}
};
% Tag reference
\gittag
[v0p1] % node name
{v0.1} % node text
{above=of A} % node placement
{A} % target
% Remote branch
\gitremotebranch
[origmaster] % node name
{origin/master} % node text
{above=of C} % node placement
{C} % target
% Branch
\gitbranch
{master} % node name and text
{above=of E} % node placement
{E} % target
% HEAD reference
\gitHEAD
{above=of master} % node placement
{master} % target
\end{tikzpicture}
\subcaption{Before\ldots}
\end{subfigure}
\begin{subfigure}[b]{\textwidth}
\centering
\begin{tikzpicture}
\gitDAG[grow right sep = 2em]{
A -- B -- {
C -- D' -- E',
{[nodes=unreachable] D -- E },
}
};
% Tag reference
\gittag
[v0p1] % node name
{v0.1} % node text
{above=of A} % node placement
{A} % target
% Remote branch
\gitremotebranch
[origmaster] % node name
{origin/master} % node text
{above=of C} % node placement
{C} % target
% Branch
\gitbranch
{master} % node name and text
{above=of E'} % node placement
{E'} % target
% HEAD reference
\gitHEAD
{above=of master} % node placement
{master} % target
\end{tikzpicture}
\subcaption{\ldots{} and after \texttt{git rebase origin/master}}
\end{subfigure}
\caption{Demonstrating a typical \texttt{rebase}}
\end{figure}
\end{document}
[1] http://www.ctan.org/pkg/pgf:)
- jub0bs
latex input.tex
to generate a dvi, and then finally use dvisvgm input.dvi
to generate an SVG with transparency. Converting from the SVG to a raster format like PNG is easy enough with convert -antialias -density 300 -background none input.svg output.png
. By the way, these images look amazing with full transparency. Still working on the font issue... i.imgur.com/1Xu2Ry5.png - vmrob
standalone
class, but, if I were you, I'd go the pdflatex
route, because it produces a PDF directly. Also, no need to rasterize it; just import it wherever as a PDF. Which font are you using? - jub0bs
pdflatex
. I can see no such artefacts on my PDF output (in Mac OS X Preview). - jub0bs
convert -channel rgba -density 600 -alpha on input.pdf output.png
, results in artifacts. The DVI->SVG->PNG route doesn't produce them. Likewise, they're not present in the Tex->PDF process. - vmrob
gitdags
and xcolor-solarized
to CTAN, they will become part of your TeX distribution and you won't need to install them "manually". - jub0bs
gitdags
is on the way! - jub0bs
Gitg [1] is a clone of Gitk and GitX for GNOME (it also works on KDE etc.) which shows a pretty colored graph.
It is actively developed (as of 2012). It lets you sort the commits (graph nodes) either chronologically or topologically [2], and hide commits that don't lead to a selected branch.
It works fine with large repositories and complex dependency graphs.
Sample screenshots, showing the linux-git and linux-2.6 repositories:
[1] https://wiki.gnome.org/Apps/Gitg/A nice and clean looking table-like Git graph output for shells
With hashes as usually besides the graph tree
Or in an extra column
THX!: This answer is now among the top 10 most rated and even has its own GitHub repository [1].
EDIT: You want to start right away without reading all explanations? Jump to EDIT 8.
INFO: For a more branch-like colored version for shells, see also my second answer (https://stackoverflow.com/a/63253135/).
In all the answers to this question none showed a clean table-like looking output for shells so far. The closest was this answer from gospes [2] where I started from.
The core point in my approach is to count only the tree characters shown to the user. Then fill them to a personal length with white spaces.
Other than Git, you need these tools
Mostly on board with any Linux distribution.
The code snippet is
while IFS=+ read -r graph hash time branch message;do
# Count needed amount of white spaces and create them
whitespaces=$((9-$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)))
whitespaces=$(seq -s' ' $whitespaces|tr -d '[:digit:]')
# Show hashes besides the tree ...
#graph_all="$graph_all$graph$(printf '%7s' "$hash")$whitespaces \n"
# ... or in an own column
graph_all="$graph_all$graph$whitespaces\n"
hash_all="$hash_all$(printf '%7s' "$hash") \n"
# Format all other columns
time_all="$time_all$(printf '%12s' "$time") \n"
branch_all="$branch_all$(printf '%15s' "$branch")\n"
message_all="$message_all$message\n"
done < <(git log --all --graph --decorate=short --color --pretty=format:'+%C(bold 214)%<(7,trunc)%h%C(reset)+%C(dim white)%>(12,trunc)%cr%C(reset)+%C(214)%>(15,trunc)%d%C(reset)+%C(white)%s%C(reset)' && echo);
# Paste the columns together and show the table-like output
paste -d' ' <(echo -e "$time_all") <(echo -e "$branch_all") <(echo -e "$graph_all") <(echo -e "$hash_all") <(echo -e "$message_all")
To calculate the needed white spaces we use
sed -nl1000 'l' <<< "$graph"
to get all characters (till 1000 per line) than select only the tree characters: * | / \ _ and white spaces with
grep -Eo '\\\\|\||\/|\ |\*|_'
Finally count them and substract the result from our chosen length value, which is 9 in the example.
To produce the calculated amount of white spaces we use
seq -s' ' $whitespaces
and truncate the position numbers with
tr -d '[:digit:]'
Then add them to the end of our graph line. That's it!
Git has the nice option to
format the length of the output specifiers
[3] already with the syntax '%><(amount_of_characters,truncate_option)'
,
which adds white spaces from the left '>' or right '<' side and can truncate characters from the start 'ltrunc', middle 'mtrunc' or end 'trunc'.
It is important that printf cmd's above use the same length values for the corresponding Git column.
Have fun to style your own clean table-like looking output to your needs.
Extra:
To get the right length value you can use the following snippet
while read -r graph;do
chars=$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)
[[ $chars -gt ${max_chars:-0} ]] && max_chars=$chars
done < <(git log --all --graph --pretty=format:' ')
and use $max_chars as the right length value above.
EDIT 1:
Just noticed that the underline character is also used in the git tree and edit the code snippets above accordingly. If there are other characters missing, please leave a comment.
EDIT 2:
If you want to get rid of the brackets around branch and tag entries, just use "%D" instead of "%d" in the git command, like in EDIT 3.
EDIT 3: Maybe the "auto" color option is the one you prefer most for branch and tag entries?
Change this part of the git command (color 214)
%C(214)%>(15,trunc)%D%C(reset)
to auto
%C(auto)%>(15,trunc)%D%C(reset)
EDIT 4: Or you like your own color mix for that part, a fancy output with blinking head?
To be able to style the head, branch names and tags first we need the "auto" color option in our git command like in EDIT 3.
Then we can replace the know color values with our own by adding these 3 lines
# branch name styling
branch=${branch//1;32m/38;5;214m}
# head styling
branch=${branch//1;36m/3;5;1;38;5;196m}
# tag styling
branch=${branch//1;33m/1;38;5;222m}
just before line
branch_all="$branch_all$(printf '%15s' "$branch")\n"
in our code snippet. The replacement values produce the colors above.
For example the replacement value for head is
3;5;1;38;5;196
where 3; stands for italic, 5; for blinking and 1;38;5;196 for the color. For more infos start here. [4] Note: This behavior depends on your favorite terminal and may therefore not be usable.
BUT you can choose any color value you prefer.
OVERVIEW of the git color values and ANSI equivalents
You find a list with git color/style option here [5].
If you need the output on your console for accurate colors (the picture above is scaled down by Stack Overflow) you can produce the output with
for ((i=0;i<=255;i++));do
while IFS='+' read -r tree hash;do
echo -e "$(printf '%-10s' "(bold $i)") $hash $(sed -nl500 'l' <<< "$hash"|grep -Eom 1 '[0-9;]*[0-9]m'|tr -d 'm')"
done < <(git log --all --graph --decorate=short --color --pretty=format:'+%C(bold '$i')%h%C(reset)'|head -n 1)
done
in your Git project path which uses the first commit from your Git log output.
EDIT 5: As member "Andras Deak" mentioned, there are some ways how to use this code:
1) as a Bash alias:
alias does not accept parameters but a function can [6], therefore just define in your .bashrc
function git_tably () {
unset branch_all graph_all hash_all message_all time_all max_chars
### add here the same code as under "2) as a shell script" ###
}
and call the function git_tably (derived from table-like) directly under your git project path or from wherever you want with your git project path as first parameter.
2) as a shell script:
I use it with the option to pass a Git project directory as first parameter to it or if empty, take the working directory like the normal behavior. In it's entirety we have
# Edit your color/style preferences here or use empty values for git auto style
tag_style="1;38;5;222"
head_style="1;3;5;1;38;5;196"
branch_style="38;5;214"
# Determine the max character length of your git tree
while IFS=+ read -r graph;do
chars_count=$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)
[[ $chars_count -gt ${max_chars:-0} ]] && max_chars=$chars_count
done < <(cd "${1:-"$PWD"}" && git log --all --graph --pretty=format:' ')
# Create the columns for your preferred table-like git graph output
while IFS=+ read -r graph hash time branch message;do
# Count needed amount of white spaces and create them
whitespaces=$(($max_chars-$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)))
whitespaces=$(seq -s' ' $whitespaces|tr -d '[:digit:]')
# Show hashes besides the tree ...
#graph_all="$graph_all$graph$(printf '%7s' "$hash")$whitespaces \n"
# ... or in an own column
graph_all="$graph_all$graph$whitespaces\n"
hash_all="$hash_all$(printf '%7s' "$hash") \n"
# Format all other columns
time_all="$time_all$(printf '%12s' "$time") \n"
branch=${branch//1;32m/${branch_style:-1;32}m}
branch=${branch//1;36m/${head_style:-1;36}m}
branch=${branch//1;33m/${tag_style:-1;33}m}
branch_all="$branch_all$(printf '%15s' "$branch")\n"
message_all="$message_all$message\n"
done < <(cd "${1:-"$PWD"}" && git log --all --graph --decorate=short --color --pretty=format:'+%C(bold 214)%<(7,trunc)%h%C(reset)+%C(dim white)%>(12,trunc)%cr%C(reset)+%C(auto)%>(15,trunc)%D%C(reset)+%C(white)%s%C(reset)' && echo);
# Paste the columns together and show the table-like output
paste -d' ' <(echo -e "$time_all") <(echo -e "$branch_all") <(echo -e "$graph_all") <(echo -e "$hash_all") <(echo -e "$message_all")
3) as a Git alias:
Maybe the most comfortable way is to add a git alias in your .gitconfig
[color "decorate"]
HEAD = bold blink italic 196
branch = 214
tag = bold 222
[alias]
count-log = log --all --graph --pretty=format:' '
tably-log = log --all --graph --decorate=short --color --pretty=format:'+%C(bold 214)%<(7,trunc)%h%C(reset)+%C(dim white)%>(12,trunc)%cr%C(reset)+%C(auto)%>(15,trunc)%D%C(reset)+%C(white)%s%C(reset)'
tably = !bash -c '" \
\
\
while IFS=+ read -r graph;do \
chars_count=$(sed -nl1000 \"l\" <<< \"$graph\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l); \
[[ $chars_count -gt ${max_chars:-0} ]] && max_chars=$chars_count; \
done < <(git count-log && echo); \
while IFS=+ read -r graph hash time branch message;do \
chars=$(sed -nl1000 \"l\" <<< \"$graph\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l); \
whitespaces=$(($max_chars-$chars)); \
whitespaces=$(seq -s\" \" $whitespaces|tr -d \"[:digit:]\"); \
graph_all=\"$graph_all$graph$whitespaces\n\"; \
hash_all=\"$hash_all$(printf \"%7s\" \"$hash\") \n\"; \
time_all=\"$time_all$(printf \"%12s\" \"$time\") \n\"; \
branch_all=\"$branch_all$(printf \"%15s\" \"$branch\")\n\"; \
message_all=\"$message_all$message\n\"; \
done < <(git tably-log && echo); \
paste -d\" \" <(echo -e \"$time_all\") <(echo -e \"$branch_all\") <(echo -e \"$graph_all\") \
<(echo -e \"$hash_all\") <(echo -e \"$message_all\"); \
'"
Than just call git tably
under any project path.
Git is so powerful that you can change head, tags, ... directly as shown above and taken from here [7].
Another fancy option [8] is to select tree colors you prefer the most with
[log]
graphColors = bold 160, blink 231 bold 239, bold 166, bold black 214, bold green, bold 24, cyan
that gives you crazy looking but always table-like git log outputs
Too much blinking! Just to demonstrate what is possible. Too few specified colors leads to color repetitions.
A complete .gitconfig reference is just one click away.
[9]
EDIT 6: Due to your positive votes I improved the snippet. Now you can feed it with almost any git log command and don't have to adapt the code any more. Try it!
How does it work?
Then just call
git tably YourLogAlias
under any git project path or
git tably YourLogAlias TreeColNumber
where TreeColNumber overwrites an always defined value from above.
git tably YourLogAlias | less -r
will pipe the output into less which is useful for huge histories.
Your Git log alias must follow these format rules:
each column has to be indicated by a column delimiter which you have to choose and may cause problems if not unique
i.e. ^
in ...format:'^%h^%cr^%s'
results in a tree, a hash, a time and a commit column
before every commit placeholder in your log command you have to use
%><(<N>[,ltrunc|mtrunc|trunc])
, with one of the trunc options
(for syntax explanations see https://git-scm.com/docs/pretty-formats [10]),
however the last commit placeholder of any newline can be used without it
i.e. ...format:'^%<(7,trunc)%h^%<(12,trunc)%cr^%s'
if extra characters are needed for decoration like (committer:
, <
and >)
in
...%C(dim white)(committer: %cn% <%ce>)%C(reset)...
to get a table-like output they must be written directly before and after the commit placeholder
i.e. ...%C(dim white)%<(25,trunc)(committer: %cn%<(25,trunc) <%ce>)%C(reset)...
using column colors like %C(white)...%C(reset)
needs the --color
option for a colored output
i.e. ...--color...format:'^%C(white)%<(7,trunc)%h%C(reset)...
if you use the --stat
option or similar, add a newline %n
at the end
i.e. ...--stat...format:'...%n'...
you can place the git graph at every column as long as you use no newline or only empty ones format:'...%n'
for non-empty newlines ...%n%CommitPlaceholder...
you can place the git graph at every column n+1 only if all n-th columns of each line exist and use the same width
the name of your defined tree column number for a specific log alias have to be YourLogAlias-col
Compared to normal git log output this one is slow but nice.
Now the improved snippet to add to your .gitconfig
[color "decorate"]
HEAD = bold blink italic 196
branch = 214
tag = bold 222
[alias]
# Delimiter used in every mylog alias as column seperator
delim = ^
# Short overview about the last hashes without graph
mylog = log --all --decorate=short --color --pretty=format:'^%C(dim white)%>(12,trunc)%cr%C(reset)^%C(bold 214)%<(7,trunc)%h%C(reset)' -5
# Log with hashes besides graph tree
mylog2 = log --all --graph --decorate=short --color --pretty=format:'%C(bold 214)%<(7,trunc)%h%C(reset)^%C(dim white)%>(12,trunc)%cr%C(reset)^%C(auto)%>(15,trunc)%D%C(reset)^%C(white)%<(80,trunc)%s%C(reset)'
mylog2-col= 3
# Log with hashes in an own column and more time data
mylog3 = log --all --graph --decorate=short --color --pretty=format:'^%C(dim white)%>(12,trunc)%cr%C(reset)^%C(cyan)%<(10,trunc)%cs%C(reset)^%C(bold 214)%<(7,trunc)%h%C(reset)^%C(auto)%<(15,trunc)%D%C(reset)^%C(white)%s%C(reset)'
mylog3-col= 4
tably = !bash -c '" \
\
\
declare -A col_length; \
apost=$(echo -e \"\\u0027\"); \
delim=$(git config alias.delim); \
git_log_cmd=$(git config alias.$1); \
git_tre_col=${2:-$(git config alias.$1-col)}; \
[[ -z "$git_tre_col" ]] && git_tre_col=1; \
[[ -z "$git_log_cmd" ]] && { git $1;exit; }; \
\
\
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%$apost*}; \
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}\")\"; \
\
\
git_log_fst_part=\"${git_log_cmd%%\"$apost\"*}\"; \
git_log_lst_part=\"${git_log_cmd##*\"$apost\"}\"; \
git_log_tre_part=\"${git_log_cmd%%\"$delim\"*}\"; \
git_log_tre_part=\"${git_log_tre_part##*\"$apost\"}\"; \
git_log_cmd_count=\"$git_log_fst_part$apost $git_log_tre_part$apost$git_log_lst_part\"; \
col_length[\"1:1\"]=$(eval git \"${git_log_cmd_count// --color}\" | wc -L); \
\
\
i=0; \
while IFS=\"$delim\" read -r graph rest;do \
((i++)); \
graph_line[$i]=\"$graph\"; \
done < <(eval git \"${git_log_cmd/ --color}\" && echo); \
\
\
i=0; \
l=0; \
while IFS= read -r line;do \
c=0; \
((i++)); \
((l++)); \
[[ $l -gt $n ]] && l=1; \
while IFS= read -d\"$delim\" -r col_content;do \
((c++)); \
[[ $c -le $git_tre_col ]] && c_corr=-1 || c_corr=0; \
if [[ $c -eq 1 ]];then \
[[ \"${col_content/\\*}\" = \"$col_content\" ]] && [[ $l -eq 1 ]] && l=$n; \
count=$(wc -L <<< \"${graph_line[$i]}\"); \
whitespaces=$(seq -s\" \" $((${col_length[\"1:1\"]}-$count))|tr -d \"[:digit:]\"); \
col_content[$git_tre_col]=\"${col_content}$whitespaces\"; \
else \
col_content[$c+$c_corr]=\"$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\"; \
fi; \
done <<< \"$line$delim\"; \
for ((k=$c+1;k<=$i_max;k++));do \
[[ $k -le $git_tre_col ]] && c_corr=-1 || c_corr=0; \
col_content[$k+$c_corr]=\"$(printf \"%-${col_length[\"$l:$k\"]:-${col_length[\"${last[$k]:-1}:$k\"]:-0}}s\" \"\")\"; \
done; \
unset col_content[0]; \
echo -e \"${col_content[*]}\"; \
unset col_content[*]; \
done < <(eval git \"$git_log_cmd\" && echo); \
"' "git-tably"
where in tably
Results:
or with new TreeColNumber on the fly
AGAIN: Have fun to style your own clean table-like looking output to your needs.
EDIT 7: A more simple and fast table-like approach with almost Git-like speed but without a moving tree column (EDIT 6 has that feature).
How does it work?
Then just call
git table YourGitLogAlias
under any Git project path.
Your Git log alias only needs to follow one offical Git log rule [11]:
%<>(N,ltrunc,mtrunc,trunc)%CommitPlaceholder
where in %<>(N,ltrunc,mtrunc,trunc)
N
sets the column width to N characters, with N >= 2<>
place it on the <
- left, <>
- middle or >
- rightltrunc,mtrunc,trunc
truncate longer contents from the ltrunc
- left, mtrunc
- middle or trunc
- rightand is optional for every last commit placeholder of a format line or every commit placeholder that always expands to the same length.
To recognize your format part in the snippet below, format:''
must be used and nowhere else in your Git log alias.
Example:
log --all --graph --color --pretty=format:'%Cblue%h %Cgreen%cr %Creset%s' -10
becomes
log --all --graph --color --pretty=format:'%Cblue%<(7,trunc)%h %Cgreen%<(15,trunc)%cr %Creset%s' -10
where
%<(7,trunc)
is optional as every abbrev commit %h
has length 7%s
is the last commit placeholder of the format lineExplanation:
The key point to count the tree characters is still the same approach as in the whole answer. The resulting tree length is then appended to the beginning of each format line in a special format. The advantage of this approach is that any Git log alias can also be used as normal.
Snippet:
Add this bash snippet that only uses the external commands wc
and of course git
to your .gitconfig.
[color "decorate"]
HEAD = blink bold italic 196
branch = 214
tag = bold 222
[alias]
# change alias names to give them a more meaningfull name or add your own versions here
tlog0 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) %C(bold green)%<(15,trunc)%ar%C(reset) %C(dim white)%<(22,trunc)%an%C(auto)%<(15,trunc)%d %C(white)%s%C(reset)' --all
tlog1 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%<(31,trunc)%aD%C(reset) %C(bold green)(%<(22,trunc)%ar)%C(reset)%C(auto)%d%C(reset)%n%<(10,trunc)%x20%C(white)%s%C(reset)%n%<(10,trunc)%x20%C(dim white)%<(31,trunc)%an %ae%C(reset)'
tlog2 = log --all --color --date='format:%Y-%m-%d %H:%M:%S' --decorate=short --graph --pretty=format:'%C(bold dim white)%ad%C(reset) %C(bold dim cyan)%<(20,trunc)%an%C(reset) %C(bold cyan)%h%C(reset)%C(auto)%d%C(reset)%n%C(dim white)%<(19,trunc)%ar%C(reset) %C(dim cyan)%<(20,trunc)%ae%C(reset) %C(bold white)Commit:%C(reset) %C(white)%s%C(reset)%n'
table = !bash -c '" \
\
\
alias=$1; \
apost=$(echo -e \"\\u0027\"); \
shift; \
log_cmd=\"$(git config alias.$alias) $@\"; \
[[ \"$log_cmd\" == \" $@\" ]] && { git $alias $@; exit; }; \
\
\
log_fst_prt=\"${log_cmd%%\"format:$apost\"*}format:\"; \
log_tre_prt=\"${log_cmd#\"$log_fst_prt$apost\"}\"; \
log_tre_prt=\"${log_tre_prt%%$apost*}\"; \
log_lst_prt=\"${log_cmd#\"$log_fst_prt$apost$log_tre_prt$apost\"}\"; \
log_cmd_tre=\"${log_fst_prt}$apost%x20$apost${log_lst_prt}\"; \
\
\
for opt_dis in \"--color\" \"--stat\";do \
log_cmd_tre=\"${log_cmd_tre//\" $opt_dis\"}\"; \
done; \
tre_width=$(eval git \"${log_cmd_tre}\" | wc -L); \
\
\
i=0; \
log_tre_new=; \
while IFS= read -r line;do \
((i++)); \
if [[ $i -eq 1 ]];then \
log_tre_new+=\"%<|($tre_width,trunc)%x20${line}\"; \
else \
log_tre_new+=\"%n%<|($(($tre_width-1)),trunc)%x20${line}\"; \
fi; \
done <<< \"$(echo -e \"${log_tre_prt//\\%n/\\\\n}\")\"; \
[[ \"${log_tre_prt%\"%n\"}\" != \"$log_tre_prt\" ]] && log_tre_new+=\"%n\"; \
\
\
log_cmd=\"${log_fst_prt}${apost}${log_tre_new}${apost}${log_lst_prt}\"; \
eval git \"$log_cmd\"; \
"' "git-table"
where the
Thanks for all your support and upvotes. Make some nice table-like logs ;)
EDIT 8: One of the shortest and simplest commands to get a table-like git log output:
git log ...^...^... | column -t -s ^
a nice one-liner, where the column
command generates the table-like output by the delimiter ^
, which is used as a column indicator in your log command.
If you regularly switch your log command or add options to it or need the command to be as simple as possible, you may like this approach:
How does it work?
Then just call
git tab YourGitLogAlias
under any Git project path.
Your Git log alias needs only one simple modification:
^
in ...format:'^%h^%cr^%s'
results in a tree, a hash, a time and a commit column.The column
command sets the column width for each column to that of their widest cell. If you need shorter columns, you can limit the width in your log command with
%<>(N,ltrunc,mtrunc,trunc)%CommitPlaceholder
For explanations, please have a look at EDIT 7 or learn from the log examples in the alias section below.
Snippet:
Add this bash snippet to your .gitconfig and change the delimiter ^
to the one you use.
[color "decorate"]
HEAD = blink bold italic 196
branch = 214
tag = bold 222
[alias]
# change alias names to give them a more meaningfull name or add your own versions here
log0 = log --all --graph --abbrev-commit --color --decorate --format=format:'^%C(bold blue)%h%C(reset)^%C(bold green)%<(15,trunc)%ar%C(reset)^%C(dim white)%<(22,trunc)%an^%C(auto)%<(15,trunc)%d^%C(white)%s%C(reset)'
log1 = log --all --graph --abbrev-commit --color --decorate --format=format:'^%C(bold blue)%h%C(reset) >^%C(bold cyan)%<(30,trunc)%aD%C(reset)^%C(bold green)%<(22,trunc)(%ar)%C(reset)^%C(auto)%D%C(reset)%n^%<(7,trunc)%x20^%C(dim white)%<(30,trunc)%ae^%<(22,trunc)(%an)%C(reset) <^%C(white)%s%C(reset)'
log2 = log --all --graph --date='format:%Y-%m-%d %H:%M:%S' --color --decorate=short --pretty=format:'^%C(bold dim white)%ad%C(reset)^%C(bold dim cyan)%<(19,trunc)%an%C(reset)^%C(bold cyan)%h%C(reset)^%C(auto)%D%C(reset)%n^%C(dim white)%<(19,trunc)%ar%C(reset)^%C(dim cyan)%<(19,trunc)%ae%C(reset)^%C(bold white)Commit:%C(reset)^%C(white)%s%C(reset)%n'
# change the delimiter ^ to the one you use in your [alias] section
tab = !bash -c '" { git $@; echo; } | column -t -s ^; "' "git-tab"
This approach is fast, simple and easy to understand. However, it has its limitations. You cannot create a multi-line design in which one line has several columns and another line with only one column should utilise the entire width. But with EDIT 7 you can do that ;).
Attention: If your column program version is to old, this method does not work! Try the following test in your terminal:
echo -e "row 1\n\033[1;31mrow\033[0m 2\nrow 3" | column -t
which should lead to a table-like output like this:
Or check your column version with
dpkg -S $(which column)
dpkg -l | grep bsdmainutils
where
bsdmainutils 9.0.6ubuntu3 is to old
bsdmainutils 11.1.2ubuntu3 is okay.
* yes after the update
where input versatility means if the command
different git logs
oradding options
to manipulate themand where output flexibility means if it
different column widths
in multi-line cases andtree column positioning
.Create some nice table-like logs for a beautiful output and !THX! for your support and votes.
[1] https://github.com/dmikushin/tablyI just wrote one tool that can generate a pretty Git commits graph using HTML/Canvas [1].
And provide a jQuery plugin which makes it easy to use.
[GitHub] https://github.com/tclh123/commits-graph
Preview:
[1] https://en.wikipedia.org/wiki/Canvas_elementI wrote a web tool for converting Git logs into pretty SVG graphs:
Bit-Booster - Offline Commit Graph Drawing Tool [1]
Upload output from git log --pretty='%h|%p|%d'
directly into the tool and then click on the "download graph.svg" link.
The tool is pure-client-side, and so none of your Git data is shared with my server. You can also save the HTML + JavaScript locally and run it using "file:///" URLs. It was verified on Chrome 48 and Firefox 43 on Ubuntu 12.04 [2] (Precise Pangolin).
It generates HTML that can be posted directly into any page (including the blogspot blogging engine!). Take a look at some of the blog posts here:
http://bit-booster.blogspot.ca/
Here's a screenshot of a sample HTML file generated by the tool:
http://bit-booster.com/graph.html (the tool)
[1] http://bit-booster.com/graph.htmlSourcetree [1] is a really good one. It does print out a good looking and medium size history and branch graph: (the following is done on an experimental Git project just to see some branches). Supports Windows 7+ and Mac OS X 10.6+.
[1] https://www.sourcetreeapp.com/
git-forest
[1] is an excellent Perl script I've been using for more than a year and I hardly use the git log
command directly any more.
These are some of the things I love about this script:
--reverse
with the graph output, which is not possible with the regular git log
command.git log
internally to grab the list of commits, so all options that you pass to git log
can also be passed to this script as well.I have an alias using git-forest
as follows:
[alias]
tree = "forest --pretty=format:\"%C(red)%h %C(magenta)(%ar) %C(blue)%an %C(reset)%s\" --style=15 --reverse"
This is how the output looks like on a terminal:
[1] https://github.com/jwiegley/git-scripts/blob/master/git-forestBased on a Graphviz script I found in an answer to a related question [1], I've hacked up a Ruby script [2] that creates a summary view of a Git repository. It elides all linear history and just shows "interesting" commits, i.e. those with multiple parents, multiple children, or pointed to by a branch or tag. Here's a snippet of the graph it generates for jQuery [3]:
git-big-picture [4] and BranchMaster [5] are similar tools that try to show only the high-level structure of a graph, by only displaying how tags, branches, merges, etc. are related.
This question [6] has some more options.
[1] https://stackoverflow.com/a/5165214/47552I've added three custom commands: git tree
, git stree
and git vtree
. I'll go over them in that order.
[alias]
tree = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset) %C(auto)%d%C(reset)\n %C(black)[%cr]%C(reset) %x09%C(black)%an: %s %C(reset)'
With git stree
and git vtree
, I've use Bash to help with the formatting.
[alias]
logx = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset)+%C(dim black)(%cr)%C(reset)+%C(auto)%d%C(reset)++\n+++ %C(bold black)%an%C(reset)%C(black): %s%C(reset)'
stree = !bash -c '" \
while IFS=+ read -r hash time branch message; do \
timelength=$(echo \"$time\" | sed -r \"s:[^ ][[]([0-9]{1,2}(;[0-9]{1,2})?)?m::g\"); \
timelength=$(echo \"16+${#time}-${#timelength}\" | bc); \
printf \"%${timelength}s %s %s %s\n\" \"$time\" \"$hash\" \"$branch\" \"\"; \
done < <(git logx && echo);"'
[alias]
logx = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset)+%C(dim black)(%cr)%C(reset)+%C(auto)%d%C(reset)++\n+++ %C(bold black)%an%C(reset)%C(black): %s%C(reset)'
vtree = !bash -c '" \
while IFS=+ read -r hash time branch message; do \
timelength=$(echo \"$time\" | sed -r \"s:[^ ][[]([0-9]{1,2}(;[0-9]{1,2})?)?m::g\"); \
timelength=$(echo \"16+${#time}-${#timelength}\" | bc); \
printf \"%${timelength}s %s %s %s\n\" \"$time\" \"$hash\" \"$branch\" \"$message\"; \
done < <(git logx && echo);"'
This works with Git version 1.9a. The color value 'auto' is apparently making its debut in this release. It's a nice addition because branch names will get a different color. This makes it easier to distinguish between local and remote branches for instance.
fatal: bad color value 'auto' for variable '--pretty format'
:( - Swivel
sed: illegal option -- r
- Slipp D. Thompson
+
? - Eric
Visual Studio Code has an amazing extension - Git Graph [1]:
[1] https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graphGit Graph
😅, I always confuse it with Git Lens
. - Qwerty
For more detailed textual output, try:
git log --graph --date-order -C -M --pretty=format:"<%h> %ad [%an] %Cgreen%d%Creset %s" --all --date=short
You can add an alias in file $HOME/.gitconfig:
[alias]
graph = log --graph --date-order -C -M --pretty=format:\"<%h> %ad [%an] %Cgreen%d%Creset %s\" --all --date=short
git hist
- Show the history of current branch
git hist --all
- Show the graph of all branches (including remotes)
git hist master devel
- Show the relationship between two or more branches
git hist --branches
- Show all local branches
Add --topo-order
to sort commits topologically, instead of by date (default in this alias)
--decorate
, so with separate colors for different branch namesgit config --global alias.hist "log --graph --date-order --date=short \
--pretty=format:'%C(auto)%h%d %C(reset)%s %C(bold blue)%ce %C(reset)%C(green)%cr (%cd)'"
It depends on what they looked like. I use gitx [1] which makes pictures like this one:
You can compare git log --graph
vs.
gitk
[2] on a 24-way octopus merge (originally from http://clojure-log.n01se.net/date/2008-12-24.html):
gitx
for MacOS only? I could not find it for Linux. - Sohail Si
gitg [1]: a gtk-based repository viewer. That's new, but interesting and useful.
I use it currently.
[1] http://git.gnome.org/browse/gitgGitX
and a pretty good one at that. Recommend - Yarek T
Although I sometimes use gitg [1], I always come back to the command line:
[alias]
# Quick look at all repositories
loggsa = log --color --date-order --graph --oneline --decorate --simplify-by-decoration --all
# Quick look at active branch (or refs pointed)
loggs = log --color --date-order --graph --oneline --decorate --simplify-by-decoration
# Extend look at all repo
logga = log --color --date-order --graph --oneline --decorate --all
# Extend look at active branch
logg = log --color --date-order --graph --oneline --decorate
# Look with the date
logda = log --color --date-order --date=local --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ad%Creset %C(auto)%d%Creset %s\" --all
logd = log --color --date-order --date=local --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ad%Creset %C(auto)%d%Creset %s\"
# Look with the relative date
logdra = log --color --date-order --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ar%Creset %C(auto)%d%Creset %s\" --all
logdr = log --color --date-order --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ar%Creset %C(auto)%d%Creset %s\"
loga = log --graph --color --decorate --all
# For repositories without subject body commits (Vim repository, git-svn clones)
logt = log --graph --color --format=\"%C(auto)%h %d %<|(100,trunc) %s\"
logta = log --graph --color --format=\"%C(auto)%h %d %<|(100,trunc) %s\" --all
logtsa = log --graph --color --format=\"%C(auto)%h %d %<|(100,trunc) %s\" --all --simplify-by-decoration
As you can see, it is almost a keystroke saving aliases, based on:
See in recent version of Git (1.8.5 and above) you can benefit from %C(auto) in decorate placeholder %d.
From here all you need is a good understanding of
gitrevisions
[2] to filter whatever you need (something like master..develop, where --simplify-merges
could help with long term branches).
The power behind command line is the quickly configuration based on your needs (understand a repository isn't a unique key log configuration, so adding --numstat, or --raw, or --name-status is sometimes needed. Here git log
and aliases are fast, powerful and (with time) the prettiest graph you can achieved. Even more, with output showed by default through a pager (say less) you can always search quickly inside results. Not convinced? You can always parse the result with projects like
gitgraph
[3].
I suggest tig
https://github.com/jonas/tig, a much much better command line tool for Git.
You can use Homebrew to install tig on macOS:
$ brew install tig
$ tig
Very slightly tweaking Slipp's awesome answer [1], you can use his aliases to log just one branch:
[alias]
lgBranch1 = log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(bold white)— %an%C(reset)%C(bold yellow)%d%C(reset)' --abbrev-commit --date=relative
lgBranch2 = log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(bold white)— %an%C(reset)' --abbrev-commit
lg = !"git lg1"
By leaving off the --all
you can now do
git lgBranch1 <branch name>
or even
git lgBranch1 --all
[1] https://stackoverflow.com/a/9074343/186636!
in lg = !"git lg1"
? - mfaani
--date=format-local:'%Y-%m-%d %H:%M:%S'
and removed the newline. Thanks! - Metafaniel
Try gitk
or gitk --all
. However, it doesn't have a print/save img as a function.
--all
shows you all of the branches. - BcK
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 this in place, git l
will output something like:
In Git
2.12
[1]+ you can even customize the line colors of the graph using the
log.graphColors
[2] configuration option.
As for the logs' format, it's similar to
--oneline
[3], 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
[4].
git log --graph --oneline
just to make sure oneliner didn't get lost - tsenapathy
A more branch-like colored version for shells.
Some other answers show graph trees nicely colored by external tools, partly with colored line information. This is my approach for shells, which is a combination with my first answer here for a table-like output (https://stackoverflow.com/a/61487052).
Features:
git log
aliasesless -r
for huge historiesHow you use it:
Define your git log
alias as in several answers shown, e.g., from
Slipp D.
[1],
albfan
[2],
kaoru
[3], with the formatting instructions mentioned below and paste it into your .gitconfig file along with the code snippet.
Call it from your project path, as usually with
git colored YourLogAlias
or with
git colored YourLogAlias TreeColumnNumber
to place the tree column on the fly.
Formatting Instructions:
Your git log
alias must follow these format rules:
^
...format:'%h%cr%s'
-->...format:'^%h^%cr^%s'
...format:'^%h^%cr^%s'
-->...format:'^%h^%cr^%C(white)%s%C(reset)'
(hashes and time in branch color)%><(<N>[,ltrunc|mtrunc|trunc])
with one of the trunc options, but any last commit placeholder on a line can be used without it...format:'^%h^%cr^%C(white)%s%C(reset)'
-->...format:'^%<(7,trunc)%h^%<(12,trunc)%cr^%C(white)%<(50,trunc)%s%C(reset)'
Commit:
...^%C(white)%<(50,trunc)%s%C(reset)...
-->...^%C(white)%<(50,trunc)Commit:%s%C(reset)...
%n
put them before a column separator or at the end...^%C(white)%<(50,trunc)Commit:%s%C(reset)'
-->...%n^%C(white)%<(50,trunc)Commit:%s%C(reset)%n'
%C(white)
above you need to add the --color
option...format:'^%<(7,trunc)%h...
-->...--color...format:'^%<(7,trunc)%h...
--stat
option or similar, add a newline %n
at the end...--stat...format:'...'
-->...--stat...format:'...%n'
Miscellaneous:
for your git log
aliases with non-empty newlines ...%n%CommitPlaceholder...
,
you can place the Git graph at every column n+1 only if all n-th columns of each line exist and use the same width
YourLogAlias-col
has to be the name if you define a TreeColumnNumber in file .gitconfig for YourLogAlias
compared to the normal git log
output, this one is slow, but nice
Examples:
Code-Snippet:
Add the following lines to your .gitconfig file
[alias]
# Define your unique column separator
delim = ^
# Define your 'git log' aliases and optional tree column numbers
lgc1 = log --all --graph --color --pretty=format:'^%<(7,trunc)%h^%C(white)%<(15,trunc)- %ar -%C(reset)^%<(35,trunc)%s^%C(white)%an%C(reset)'
lgc2 = log --all --graph --color --pretty=format:'%D^%<(7,trunc)%h^%<(35,trunc)%s^%C(white)%<(20,trunc)%an%C(reset)^%C(white) (%ar)%C(reset)'
lgc2-col = 2
lgc3 = log --all --graph --color --pretty=format:'%<(7,trunc)%h%d^%<(11,trunc)%cs%C(reset)^%s%n^%C(white)%<(11,trunc)%cr%C(reset)^%C(white)%<(25,trunc)From %an%C(reset)^%C(white)%ae%C(reset)%n'
lgc3-col = 2
lgc4 = log --all --graph --color --pretty=format:'%h^%C(white)%<(25,trunc)%an%C(reset)^%C(white)%<(31,trunc)%aD%C(reset)^%s%n^%C(dim white)%<(25,trunc)%ae%C(reset)^%>(31,trunc)%D%C(reset)%n'
lgc4-col = 3
# Define your whitespace seperated tree color list
color-list = "1;38;5;222 1;38;5;69 1;38;5;250 1;38;5;70 1;31 1;38;5;93 1;33 2;38;5;11 1;38;5;48 1;35 1;32 1;38;5;111 1;38;5;160 1;38;5;130 1;36 38;5;21"
Add the Bash snippet to your .gitconfig file too
# This is the Bash snippet which does all the magic
colored = !bash -c '" \
\
\
declare -A col_length col_colored; \
apost=$(echo -e \"\\u0027\"); \
delim=$(git config alias.delim); \
git_log_cmd=$(git config alias.$1); \
graph_col=${2:-$(git config alias.$1-col)}; \
color_list=( $(git config alias.color-list) ); \
[[ -z \"$graph_col\" ]] && graph_col=1; \
[[ -z \"$git_log_cmd\" ]] && { git $1;exit; }; \
\
\
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_info:1:1}\" = \"C\" ]] && col_colored[\"$n:$i\"]=1; \
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%$apost*}; \
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 table-like 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}\")\"; \
\
\
git_log_fst_part=\"${git_log_cmd%%\"$apost\"*}\"; \
git_log_lst_part=\"${git_log_cmd##*\"$apost\"}\"; \
git_log_tre_part=\"${git_log_cmd%%\"$delim\"*}\"; \
git_log_tre_part=\"${git_log_tre_part##*\"$apost\"}\"; \
git_log_cmd_count=\"$git_log_fst_part$apost $git_log_tre_part$apost$git_log_lst_part\"; \
col_length[\"1:1\"]=$(eval git \"${git_log_cmd_count// --color}\" | wc -L); \
\
\
i=0; \
while IFS=\"$delim\" read -r graph rest;do \
((i++)); \
graph_line[$i]=\"$graph\"; \
done < <(eval git \"${git_log_cmd/ --color}\" && echo); \
\
\
i=0; \
l=0; \
msg_err=; \
color_list_ind=-1; \
color_list_num=${#color_list[*]}; \
color_repeat_ind=1; \
if [[ $color_list_num -eq 0 ]];then \
echo \"No tree colors specified via color-list under section [alias] in your .gitconfig\"; \
echo \"Therefore collecting available Git colors, which may take a while ...\"; \
while read -d\"[\" -r char;do \
color=$(sed -nl99 \"l\" <<< \"$char\"); \
case \"$color\" in \
*\"m\"*) \
color=${color%%m*}; \
;; \
*) \
continue; \
;; \
esac; \
case \" $color_list \" in \
*\" $color \"*) \
continue; \
;; \
*) \
color_list=\"$color_list$color \"; \
;; \
esac; \
done <<< \"$(git log --all --color --graph --pretty=format:)\"; \
echo -e \"Temporary used color-list = \\\"${color_list% }\\\"\\n\"; \
color_list=( ${color_list% } ); \
color_list_num=${#color_list[*]}; \
fi; \
while IFS= read -r line;do \
((i++)); \
j=-1; \
case_off=; \
graph_colored=; \
graph_line_last=\"${graph_line[$i-1]}\"; \
graph_line=\"${graph_line[$i]}\"; \
graph_line_next=\"${graph_line[$i+1]}\"; \
while IFS= read -r char;do \
((j++)); \
case \"$case_off$char\" in \
[^\\ \\_\\*\\/\\|\\\\]|\"case_off\"*) \
graph_colored=\"${graph_colored}\\033[${point_color}m$char\\033[0m\"; \
case_off=\"case_off\"; \
;; \
\" \") \
graph_colored=\"${graph_colored}$char\"; \
case \"$char_last\" in \
\" \") \
unset color_ind[$j]; \
;; \
esac; \
;; \
\"*\") \
case \"${graph_line_last:$j:1}\" in \
\"*\") \
:; \
;; \
\"|\") \
case \"${graph_line_last:$(($j-1)):1}\" in \
\"\\\\\") \
color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
;; \
*) \
:; \
;; \
esac; \
;; \
\" \") \
case \"${graph_line_last:$(($j-1)):1}\" in \
\"\\\\\") \
color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
;; \
\"/\") \
case \"${graph_line_last:$(($j+1)):1}\" in \
\"/\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
\" \") \
new_col_ind=${#color[*]}; \
while true;do \
((color_list_ind++)); \
[[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
[[ $color_list_ind -ge $color_list_num ]] && break; \
new_color=${color_list[$color_list_ind]}; \
case \"$new_color\" in \
\"\"|[\\ ]*) \
continue; \
;; \
\"${color[${color_ind[$j-1]}]}\") \
[[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
;;& \
*) \
color[$new_col_ind]=$new_color; \
color_ind[$j]=$new_col_ind; \
last_new_colored_line=$i; \
break; \
;; \
esac 2>/dev/null; \
done; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
\" \") \
case \"${graph_line_last:$(($j+1)):1}\" in \
\"/\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
*) \
new_col_ind=${#color[*]}; \
while true;do \
((color_list_ind++)); \
[[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
[[ $color_list_ind -ge $color_list_num ]] && break; \
new_color=${color_list[$color_list_ind]}; \
case \"$new_color\" in \
\"\"|[\\ ]*) \
continue; \
;; \
\"${color[${color_ind[$j-1]}]}\") \
[[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
;;& \
*) \
color[$new_col_ind]=$new_color; \
color_ind[$j]=$new_col_ind; \
last_new_colored_line=$i; \
break; \
;; \
esac 2>/dev/null; \
done; \
;; \
esac; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
\"\"|[^\\ \\_\\*\\/\\|\\\\]) \
new_col_ind=${#color[*]}; \
while true;do \
((color_list_ind++)); \
[[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
[[ $color_list_ind -ge $color_list_num ]] && break; \
new_color=${color_list[$color_list_ind]}; \
case \"$new_color\" in \
\"\"|[\\ ]*) \
continue; \
;; \
\"${color[${color_ind[$j-1]}]}\") \
[[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
;;& \
*) \
color[$new_col_ind]=$new_color; \
color_ind[$j]=$new_col_ind; \
last_new_colored_line=$i; \
break; \
;; \
esac 2>/dev/null; \
done; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
point_color=${color[${color_ind[$j]}]}; \
;; \
\"|\") \
case \"${graph_line_last:$j:1}\" in \
\" \") \
case \"${graph_line_last:$(($j-1)):1}\" in \
\"/\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
\"\\\\\") \
color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
;; \
*) \
case \"${graph_line_last:$(($j+1)):1}\" in \
\"/\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
esac; \
;; \
\"|\") \
case \"${graph_line_last:$(($j-1)):1}\" in \
\"\\\\\") \
case \"${graph_line:$(($j+1)):1}\" in \
\"\\\\\") \
:; \
;; \
\" \") \
color_ind[$j]=${color_ind_last[$j-1]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
*) \
:; \
;; \
esac; \
;; \
\"*\") \
case \"${graph_line:$(($j-1)):1}\" in \
\"/\") \
if [[ $last_new_colored_line -eq $(($i-1)) ]];then \
new_col_ind=${#color[*]}; \
while true;do \
((color_list_ind++)); \
[[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
[[ $color_list_ind -ge $color_list_num ]] && break; \
new_color=${color_list[$color_list_ind]}; \
case \"$new_color\" in \
\"\"|[\\ ]*) \
continue; \
;; \
\"${color[${color_ind[$j-1]}]}\") \
[[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
;;& \
*) \
color[$new_col_ind]=$new_color; \
color_ind[$j]=$new_col_ind; \
break; \
;; \
esac 2>/dev/null; \
done; \
else \
color_ind[$j]=${color_ind_last[$j]}; \
fi; \
;; \
*) \
:; \
;; \
esac; \
;; \
\"/\") \
color_ind[$j]=${color_ind[$j]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
;; \
\"/\") \
case \"${graph_line_last:$(($j)):1}\" in \
\"|\") \
case \"${graph_line_last:$(($j+1)):1}\" in \
\"/\") \
case \"${graph_line_next:$j:1}\" in \
\"|\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
\" \") \
color_ind[$j]=${color_ind[$j]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
*) \
color_ind[$j]=${color_ind[$j]}; \
;; \
esac; \
;; \
*) \
case \"${graph_line_last:$(($j+2)):1}\" in \
\"/\"|\"_\") \
color_ind[$j]=${color_ind[$j+2]}; \
;; \
*) \
case \"${graph_line_last:$(($j+1)):1}\" in \
\"/\"|\"_\"|\"|\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
\"*\") \
case \"${graph_line:$(($j+1)):1}\" in \
\"|\") \
if [[ $last_new_colored_line -eq $(($i-1)) ]];then \
color_ind[$j]=${color_ind_last[$j+1]}; \
else \
new_col_ind=${#color[*]}; \
while true;do \
((color_list_ind++)); \
[[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
[[ $color_list_ind -ge $color_list_num ]] && break; \
new_color=${color_list[$color_list_ind]}; \
case \"$new_color\" in \
\"\"|[\\ ]*) \
continue; \
;; \
\"${color[${color_ind[$j-1]}]}\") \
[[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
;;& \
*) \
color[$new_col_ind]=$new_color; \
color_ind[$j]=$new_col_ind; \
break; \
;; \
esac 2>/dev/null; \
done; \
fi; \
;; \
*) \
color_ind[$j]=${color_ind_last[$j+1]}; \
;; \
esac; \
;; \
*) \
case \"${graph_line_last:$j:1}\" in \
\"\\\\\") \
:; \
;; \
\" \") \
case \"${graph_line_last:$(($j+1)):1}\" in \
\"*\") \
color_ind[$j]=${color_ind[$j+1]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
esac; \
;; \
esac; \
;; \
esac; \
graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
;; \
\"\\\\\") \
case \"${graph_line_last:$(($j-1)):1}\" in \
\"|\"|\"\\\\\") \
color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
;; \
\"*\") \
new_col_ind=${#color[*]}; \
while true;do \
((color_list_ind++)); \
[[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
[[ $color_list_ind -ge $color_list_num ]] && break; \
new_color=${color_list[$color_list_ind]}; \
case \"$new_color\" in \
\"\"|[\\ ]*) \
continue; \
;; \
\"${color[${color_ind[$j-1]}]}\") \
[[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
;;& \
*) \
color[$new_col_ind]=$new_color; \
color_ind[$j]=$new_col_ind; \
break; \
;; \
esac 2>/dev/null; \
done; \
;; \
\" \") \
case \"${graph_line_last:$(($j-2)):1}\" in \
\"\\\\\"|\"_\") \
color_ind[$j]=${color_ind_last[$j-2]:-${color_ind[$j-2]}}; \
;; \
*) \
case \"${graph_line_last:$j:1}\" in \
\"|\") \
color_ind[$j]=${color_ind_last[$j]:-${color_ind[$j]}}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
esac; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char$char\\033[0m\"; \
;; \
\"_\") \
case \"${graph_line:$(($j-2)):1}\" in \
\"\\\\\"|\"_\") \
color_ind[$j]=${color_ind[$j-2]}; \
;; \
\" \"|\"/\") \
k=2; \
while [[ \"${graph_line:$(($j+$k)):1}\" = \"_\" ]];do \
k=$(($k+2)); \
done; \
case \"${graph_line:$(($j+$k)):1}\" in \
\"/\") \
case \"${graph_line_last:$(($j+$k+1)):1}\" in \
\"*\") \
color_ind[$j]=${color_ind[$j+$k+1]}; \
;; \
\" \") \
case \"${graph_line_last:$(($j+$k)):1}\" in \
\"\\\\\") \
color_ind[$j]=${color_ind[$j+$k]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
\"|\") \
case \"${graph_line:$(($j+$k+1)):1}\" in \
\"|\") \
color_ind[$j]=${color_ind[$j+$k+2]}; \
;; \
\" \") \
color_ind[$j]=${color_ind[$j+$k+1]}; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
;; \
*) \
[[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
;; \
esac; \
graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
;; \
esac; \
char_last=$char; \
done <<< \"$(grep -Eo \".\" <<< \"${graph_line%%$delim*}\")\"; \
for key in ${!color_ind[*]};do \
color_ind_last[$key]=${color_ind[$key]}; \
done; \
\
\
c=0; \
((l++)); \
[[ $l -gt $n ]] && l=1; \
while IFS= read -d\"$delim\" -r col_content;do \
((c++)); \
[[ $c -le $graph_col ]] && c_corr=-1 || c_corr=0; \
if [[ $c -eq 1 ]];then \
[[ \"${col_content/\\*}\" = \"$col_content\" ]] && [[ $l -eq 1 ]] && l=$n; \
whitespaces=$(seq -s\" \" $((${col_length[\"1:1\"]}-$j))|tr -d \"[:digit:]\"); \
col_content[$graph_col]=\"${graph_colored}$whitespaces\"; \
elif [[ ${col_colored[\"$l:$c\"]:-0} -eq 0 ]];then \
col_content[$c+$c_corr]=\"\\033[${point_color:-0}m$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\\033[0m\"; \
else \
col_content[$c+$c_corr]=\"$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\"; \
fi; \
done <<< \"$line$delim\"; \
for ((k=$c+1;k<=$i_max;k++));do \
[[ $k -le $graph_col ]] && c_corr=-1 || c_corr=0; \
col_content[$k+$c_corr]=\"$(printf \"%-${col_length[\"$l:$k\"]:-${col_length[\"${last[$k]:-1}:$k\"]:-0}}s\" \"\")\"; \
done; \
unset col_content[0]; \
echo -e \"${col_content[*]}\"; \
unset col_content[*]; \
done < <(git $1 && echo); \
"' "git-colored"
Explanations:
The biggest part is the case analysis for setting the tree colors. The other parts are explained in my linked answer for table-like shell outputs.
Please show your favorite formatted log alias in the comments, as mine are only examples.
[1] https://stackoverflow.com/a/9074343*
character) is also colorized (in 99% percents of what I saw in Google it is always white). Can you please explain how you did it? I have my own git log
alias and I just what to add commit colorization. - Refael Sheinker
GitGraph [1]
It generates a PNG or SVG representation of your Git repository's commit history.
[1] https://code.google.com/p/gitgraphgit -c core.pager='less -SRF' log --oneline --graph --decorate
This is my terminal variation, similar to many answers here. I like to adjust the flags passed to less
to prevent word wrapping.
I set this to an alias for quick access since the command is a bit cumbersome.
If your repository sits on GitLab, you can use its graph representation as that is rendered as an SVG in your browser.
Go to your repository's graph view, e.g., https://gitlab.com/gitlab-org/gitter/webapp/network/develop
Scroll the graph down to the bottom (it lazy loads commits!)
Use your browser's inspector to copy the SVG element to a new file
Open it in a renderer of your choice, e.g., Inkscape [1]
Try ditaa [1]. It can transform any ASCII diagram into an image. Although it was not designed with Git branches in mind, I was impressed by the results.
Source (txt file):
+--------+
| hotfix |
+---+----+
|
--*<---*<---*
^
|
\--*<---*
|
+---+----+
| master |
+--------+
Command:
java -jar ditaa0_9.jar ascii-graph.txt
Result:
It also supports background colors, dashed lines, different shapes and more. See the examples [2].
[1] http://ditaa.sourceforge.net/Some aliases in file ~/.oh-my-zsh/plugins/git/git.plugin.zsh:
gke='\gitk --all $(git log -g --pretty=%h)'
glg='git log --stat'
glgg='git log --graph'
glgga='git log --graph --decorate --all'
glgm='git log --graph --max-count=10'
glgp='git log --stat -p'
glo='git log --oneline --decorate'
glog='git log --oneline --decorate --graph'
gloga='git log --oneline --decorate --graph --all'
glol='git log --graph --pretty='\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\'' --abbrev-commit'
glola='git log --graph --pretty='\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\'' --abbrev-commit --all'
gloga
is the one. - peter_v
Here my alias for the community: git ls
.
With git ls
you can view the graph and each commit covers just one line. Everything coloured and with useful information. You can also check the commit history on other branches:
git config --global alias.ls '!f() { git log $1 --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cgreen\\ [%ae,%ar]" --decorate --graph; }; f'
Usage:
# shows commits graph on the current branch
git ls
# shows commits graph on the develop branch
git ls develop
There's a funky Git commit graph as one of the demos of the Raphael [1] web graphics library.
The demo is static, but it should be easy enough to take the code and swap out their static data for a live set of data -- I think it's just Git commit data in JSON format.
The demo is here: http://dmitrybaranovskiy.github.io/raphael/github/impact.html
[1] http://dmitrybaranovskiy.github.io/raphael/I find git-sim [1] visualization clear.
Although the project goal is to simulate and visualize git commands you can use it to visualize commits as well:
git sim -n 10 log --all
[1] https://github.com/initialcommit-com/git-simFor OS X users, I've taken the @gospes example and slightly modified it for gsed (gnu-sed
installed via
Homebrew
[1]) and adjusted the colors (to work with a black background, not sure how the original example could possibly render the way it does in the example since it specifies black text on a terminal with a black background).
[alias]
# tree, vtree, stree support
logx = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset)+%C(bold black)(%cr)%C(reset)+%C(auto)%d%C(reset)++\n+++ %C(bold black)%an%C(reset)%C(bold black): %s%C(reset)'
tree = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset) %C(auto)%d%C(reset)\n %C(bold black)[%cr]%C(reset) %x09%C(bold black)%an: %s %C(reset)'
stree = !bash -c '" \
while IFS=+ read -r hash time branch message; do \
timelength=$(echo \"$time\" | gsed -r \"s:[^ ][[]([0-9]{1,2}(;[0-9]{1,2})?)?m::g\"); \
timelength=$(echo \"16+${#time}-${#timelength}\" | bc); \
printf \"%${timelength}s %s %s %s\n\" \"$time\" \"$hash\" \"$branch\" \"\"; \
done < <(git logx && echo);"' | less -r
vtree = !bash -c '" \
while IFS=+ read -r hash time branch message; do \
timelength=$(echo \"$time\" | gsed -r \"s:[^ ][[]([0-9]{1,2}(;[0-9]{1,2})?)?m::g\"); \
timelength=$(echo \"16+${#time}-${#timelength}\" | bc); \
printf \"%${timelength}s %s %s %s\n\" \"$time\" \"$hash\" \"$branch\" \"$message\"; \
done < <(git logx && echo);"' | less -r
The key for OS X is to first install GNU sed (which has the -r option). It is most easily done with Homebrew, which will not overwrite the system-installed sed, but will instead install GNU sed as "gsed". I hope this helps @SlippD.Thompson who commented above [2] about OS X not working.
[1] https://en.wikipedia.org/wiki/Homebrew_(package_manager)If you are using macOS, you can try GitUp [1]:
I don't know about a direct tool, but maybe you can hack a script to export the data into dot format and render it with Graphviz [1].
[1] https://en.wikipedia.org/wiki/Graphvizio
commands to simple perl `git log [...]` commands worked for me. - Ross Rogers
brew install perl dot
and then cpan common::sense IO::all
to get the dependencies. Then, just pipe the output to an appropriate command, like git-graphviz | dot -Tpng -o repo.png
. However, the output isn't much different than git-big-picture. - jrhorn424
Looking at this conversation, I tried to use my favorite git-cola
& git-dag
.
Running View->DAG...
from git-cola
and replacing Log: master --
with --all
shows a pretty graph with all branches.
In addition to the answer of 'Slipp D. Thompson', I propose you to add this alias to have the same decoration, but in a single line by commit:
git config --global alias.tre "log --graph --decorate --pretty=oneline --abbrev-commit --all --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(bold yellow)%d%C(reset)'"
An improvement from 'Slipp D. Thompson' answer:
Most of us don't need "stash record" in our git log, which makes it redundant.
Instead of doing --all
and then trying to filter out the stashes, we only need branches, remotes and tags:
git 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)\' --branches --remotes --tags
Or alias
[alias]
lg = 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)\' --branches --remotes --tags
I have a perl script that prints pretty git graphs to the console that even make sense! It uses the normal git command line tool to get the log data so it doesn't rely on any non-standard perl plugins (in fact, the only plugins it uses are some standard ones for date handling)
You can find it here - http://knockknock.org.uk/git-graph
'git-graph -h' will print option details
tig
, github.com/jonas/tig - Toby