Skip to main content

Interactive Commit Sorter for Changelogs

Sidebar

I wrote a Bash script to sort git commits into buckets, to be used as the first step of making a change log. It supports rewording commit messages, can be stopped and resumed, and supports automatic filtering based on keywords.

I wrote a Bash script to sort git commits into buckets, to be used as the first step of making a change log. It supports rewording commit messages, can be stopped and resumed, and supports automatic filtering based on keywords.

License: MIT

Example #

$ commitsorter ~/Documents HEAD~10..HEAD

Outputting to /home/ruben/Documents/commitsorter

[bugfix / feature / csm / ssm / other / delete / reword]

Fix something (''rubenwardy'')
: b  (auto)

Add foo (''rubenwardy'')
: f

Add bnrre mispelt (''rubenwardy'')
: r

New message: Add bar (''rubenwardy'')

Add bar (''rubenwardy'')
: f

Summary:
- Bugfixes: 1
- Features: 2
- CSM     : 0
- SSM     : 0
- Others  : 0
- Deleted : 0

The Script #

#!/bin/bash

if [[ $# -ne 2 ]]; then
	echo "Usage: commitsorter output REF1..REF2"
	exit 1
fi

### Define new results here ... ###
makebuckets() {
	echo -e "## Bug fixes and Improvements ##\n" > "$1/b.txt"
	echo -e "## Features ##\n" > "$1/f.txt"
	echo -e "## Client Modding ##\n" > "$1/c.txt"
	echo -e "## Server Modding ##\n" > "$1/m.txt"
	echo -e "## Other / Misc ##\n" > "$1/o.txt"
	echo -e "## Deleted ##\n" > "$1/d.txt"
}

### ... and also add them to help ###
help() {
	echo -e "[\e[4mb\e[0mugfix / \e[4mf\e[0meature / \e[4mc\e[0msm / ss\e[4mm\e[0m / \e[4mo\e[0mther / \e[4md\e[0melete / \e[4mr\e[0meword]"
}

output="$1/commitsorter"
echo "Outputting to $output"

### Uncomment to backup and start again instead of resuming ###
# if [ -d "$output" ]; then
# 	DATE=$(date +%Y_%m_%d_%H_%M_%S)
# 	backup="${output}_$DATE"
# 	echo "Backing up $output to $backup"
# 	mv "$output" "$backup"
# fi

# Create directories and buckets
mkdir -p "$1"
mkdir -p "$output"
mkdir -p "$output/cache"
if [ ! -f $output/b.txt ]; then
	makebuckets $output
fi

# Get log
entries=`git log --pretty=format:"%h %s (''%an'')" "$2"`

# Print help
echo ""
help

# Loop
IFS=$'\n'
for line in $entries
do
	hash=$(echo $line | cut -c1-7)
	message=$(echo $line | cut -c 9- )

	echo ""
	echo "$message"

	if [[ -f $output/cache/$hash ]] ; then
		input=$(cat $output/cache/$hash)
		echo -e ": $input  (already sorted)"
	elif echo $message | grep -iq "fix\(ed\)\? "; then
		echo ": b  (auto)"
		echo $message >> $output/b.txt
		echo b > $output/cache/$hash
	elif echo $message | grep -iq "translated using weblate"; then
		echo ": d  (auto)"
		echo $message >> $output/d.txt
		echo d > $output/cache/$hash
	else
		while true; do
			read -p ": " -rsn1 input
			echo $input

			LC_ALL=C # Turn off locale.
			if [[ $input == r ]] ; then
				echo ""
				read -p "New message: " line2
				if [[ ! -z $message2 ]] ; then
					line=$message2
				fi
				echo ""
				echo $message
			elif [[ $input == [a-z] ]] ; then
				if [ -f $output/$input.txt ]; then
					echo $message >> $output/$input.txt
					echo $input > $output/cache/$hash
					break
				else
					help
				fi
			else
				help
			fi
		done
	fi
done


echo ""
echo "Summary:"
for filename in $output/*.txt; do
	title=$(head -n1 $filename | sed 's/^## \([^#]*\) ##$/\1/')
	count=$(cat $filename | tail -n+2 | sed '/^\s*$/d' | wc -l)
	echo "- $title: $count"
done
rubenwardy's profile picture, the letter R

Hi, I'm Andrew Ward. I'm a software developer, an open source maintainer, and a graduate from the University of Bristol. I’m a core developer for Luanti, an open source voxel game engine.

Comments

Leave comment

Shown publicly next to your comment. Leave blank to show as "Anonymous".
Optional, to notify you if rubenwardy replies. Not shown publicly.
Max 1800 characters. You may use plain text, HTML, or Markdown.