Skip to content

Instantly share code, notes, and snippets.

@StephenHwang
Created December 15, 2023 04:20
Show Gist options
  • Save StephenHwang/bf8e29a02586b4ab738849e35f6a9701 to your computer and use it in GitHub Desktop.
Save StephenHwang/bf8e29a02586b4ab738849e35f6a9701 to your computer and use it in GitHub Desktop.
Plot histogram of git commit times.
#!/usr/bin/env python
#
# Run: Plot histogram of git commit history times.
# ./plot_git_commit_times.py \
# -r git_repo_path \
# -a git_author \
# -o output_path
import os
import subprocess
import argparse
import pandas as pd
from plotnine import ggplot, aes, theme, themes, element_blank, element_line, \
element_text, geom_histogram, ggtitle, xlab, ylab, \
scale_x_continuous
from plotnine.options import figure_size
def my_theme(base_size=19, base_family='sans', rotate=True):
''' Plotnine plotting theme. '''
thm = themes.theme_bw(base_size=base_size, base_family = base_family) + \
theme(
legend_background = element_blank(),
legend_key = element_blank(),
panel_background = element_blank(),
panel_border = element_blank(),
strip_background = element_blank(),
plot_background = element_blank(),
panel_grid = element_blank(),
axis_line = element_line(colour = 'black', size = 1),
axis_text_y = element_text(colour = 'black')
)
if rotate:
thm += theme(axis_text_x=element_text(rotation=45, hjust=1))
if figure_size is not None:
thm += theme(figure_size=figure_size)
return thm
def run_git_log(repo_path, author=None):
''' Run git log, with optional parameter for commit author. '''
if author:
command = ['git', '-C', repo_path, 'log', '--author', author]
else:
command = ['git', '-C', repo_path, 'log']
git_log = subprocess.run(command, capture_output = True, text = True).stdout
df = pd.DataFrame( [git_log.split(' ')[6] for git_log in list(map(lambda _ : _.strip(), git_log.split('\n'))) if git_log.startswith('Date')], columns=['Time'] )
df['Hour'] = df['Time'].apply(lambda _: pd.to_datetime(_).hour + pd.to_datetime(_).minute / 60)
return df
def plot_commit_times(repo_path, author=None):
''' Plot histogram ofgit commit times. '''
repo_name = os.path.normpath(repo_path).split('/')[-1]
military_time = list(range(0, 25, 4))
normal_time = ['12:00 AM', '4:00 AM', '8:00 AM', '12:00 PM', '4:00 PM', '8:00 PM', '12:00 AM']
if author:
df = run_git_log(repo_path, author)
title = repo_name + ' commit times by ' + author
else:
df = run_git_log(repo_path)
title = repo_name + ' commit times'
return (ggplot(df, aes(x='Hour')) +
geom_histogram(bins=48) +
ggtitle(title) +
xlab('Time') +
ylab('Frequency') +
scale_x_continuous(breaks=military_time, labels=normal_time, limits=[0,24]) +
my_theme(base_size=20, rotate=True))
def parse_arguments():
'''Parse and return the command-line arguments. '''
parser = argparse.ArgumentParser(description='Plot git histogram of git commits by time.')
parser.add_argument('-r', '--repo_path', dest='repo_path', help='Git repo path.', required=False, default=os.getcwd())
parser.add_argument('-a', '--author', dest='author', help='Optional: git commit author.', required=False)
parser.add_argument('-o', '--out_path', dest='out_path', help='Optional: path to save plot.', required=False)
args = parser.parse_args()
return args
def main(args):
commit_histogram = plot_commit_times(args.repo_path, args.author)
if args.out_path:
commit_histogram.save(args.out_path)
else:
print(commit_histogram)
if __name__ == '__main__':
args = parse_arguments()
main(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment