Skip to content

Instantly share code, notes, and snippets.

@dsmrt
Last active February 3, 2026 20:22
Show Gist options
  • Select an option

  • Save dsmrt/19acafe54663e50286fdce87c92b0fd4 to your computer and use it in GitHub Desktop.

Select an option

Save dsmrt/19acafe54663e50286fdce87c92b0fd4 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Note on examples:
# - Uses null byte (%x00) as delimiter via git log --format=%B%x00
# - %B outputs the raw commit message body
# - read -d $'\0' reads until null byte, naturally handling multi-line commits
# - Works reliably with any commit message content (including special characters)
# Examples:
# Get change type for commits between v1.0.0 and HEAD
# git log v1.0.0..HEAD --format=%B%x00 | ./determine-semver-from-conventional-commit.sh
# Get change type for commits between two tags
# git log v1.0.0..v2.0.0 --format=%B%x00 | ./determine-semver-from-conventional-commit.sh
# Get change type for last 10 commits
# git log -10 --format=%B%x00 | ./determine-semver-from-conventional-commit.sh
# Function to determine change type for a single commit
get_change_type() {
local COMMIT_MSG="$1"
local FIRST_LINE=$(echo "$COMMIT_MSG" | head -n 1)
local CHANGE_TYPE="patch"
# Check for breaking changes (highest priority)
if [[ "$FIRST_LINE" =~ ^[a-z]+(\([^\)]+\))?\!\:(.*) ]]; then
CHANGE_TYPE="major"
elif echo "$COMMIT_MSG" | grep -qE "^(BREAKING CHANGE:|BREAKING-CHANGE:)"; then
CHANGE_TYPE="major"
elif [[ "$FIRST_LINE" =~ ^feat(\([^\)]+\))?\: ]]; then
CHANGE_TYPE="minor"
fi
echo "$CHANGE_TYPE"
}
# If argument provided, process single commit
if [ -n "$1" ]; then
get_change_type "$1"
exit 0
fi
# Otherwise, read multiple commits from stdin using null byte delimiter
HIGHEST="patch"
while IFS= read -r -d $'\0' commit; do
# Skip empty commits
[ -z "$commit" ] && continue
TYPE=$(get_change_type "$commit")
# Update highest if needed (major > minor > patch)
if [ "$TYPE" = "major" ]; then
HIGHEST="major"
break # Can't go higher than major
elif [ "$TYPE" = "minor" ] && [ "$HIGHEST" = "patch" ]; then
HIGHEST="minor"
fi
done
echo "$HIGHEST"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment