Tably
A nice and clean looking table-like Git graph output for shells
Install / Use
/learn @dmikushin/TablyREADME
A nice and clean looking table-like Git graph output for shells
Published on StackOverflow by @onemorequestion and made into a GitHub repository under his permission.
[![With hashes as usually besides the graph tree][1]][1]
With hashes as usually besides the graph tree
[![Or in an extra column][2]][2]
Or in an extra column
EDIT: You want to start right away without reading all explanations? Jump to EDIT 6.
INFO: For a more branch-like colored version for shells, see also my second answer ([https://stackoverflow.com/a/63253135/][3]).
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][4] 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
- grep
- paste
- printf
- sed
- seq
- tr
- wc
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][5] 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. <br>
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. <br>
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. <br>
EDIT 3: Maybe the "auto" color option is the one you prefer most for branch and tag entries?
[![Git bracketless auto color head and tag tablelike shell output][6]][6]
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)
<br>
EDIT 4: Or you like your own color mix for that part, a fancy output with blinking head?
[![Git tree fancy styled tablelike output][7]][7]
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.][8] 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
[![enter image description here][9]][9]
You find a list with [git color/style option here][10].
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. <br>
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][11], 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\" | gre
Security Score
Audited on Jan 18, 2026
