Skip to content

Instantly share code, notes, and snippets.

@swissonid
Last active August 13, 2021 11:22
Show Gist options
  • Save swissonid/af9750c24f9952aca251a6de70cf8f83 to your computer and use it in GitHub Desktop.
Save swissonid/af9750c24f9952aca251a6de70cf8f83 to your computer and use it in GitHub Desktop.
Git-hook to add task prefix based on the branch name (feature | hotfix |bugfix)/MIT-1234-
#!/usr/bin/env ruby
#
# Git commit-msg hook. If your branch name is in the form "ABCDE-1234567-postfix", or
# "ABCDE-1234567_postfix", it automatically adds the prefix "ABCDE-1234567 |" to commit
# messages.
#
# Example
# =======
#
# git checkout -b ABCDE-1234567-some-cool-feature
# git commit -m "new stuff"
# git log => will show up "ABCDE-1234567 | new stuff"
#
# If you include "#noref" in the commit message, nothing will be added to the
# commit message, and the "#noref" itself will be stripped.
#
# Example
# =======
#
# git commit "don't prefix this message #noref"
# git log => will show up "don't prefix this message"
#
# Install
# =======
#
# cd your_project
# curl https://gist.githubusercontent.com/swissonid/af9750c24f9952aca251a6de70cf8f83/raw/bbddae84c1cc5fc07bdb2ec6393d1f3a03367d82/commit-msg > .git/hooks/commit-msg
# chmod +x .git/hooks/commit-msg
#
# Or if you like to install global
# --------------------------------
#
# mkdir ~/.git-templates
# curl https://gist.githubusercontent.com/swissonid/af9750c24f9952aca251a6de70cf8f83/raw/bbddae84c1cc5fc07bdb2ec6393d1f3a03367d82/commit-msg ~/.git-templates/hooks/commit-msg
# chmod +x .git/hooks/commit-msg
# git config --global init.templatedir '~/.git-templates'
#
# now you have it on each new project with git init
#
# Testing
# =======
#
# git init a new repo, install the commit hook, and run:
#
# ruby .git/hooks/commit-msg testing
#
# --
# Patrice Müller, adapted from https://gist.github.com/184711 By Henrik Nyh
# <http://henrik.nyh.se> 2009-09-10 under the MIT License.
# Convert a message to include branch name information.
class Transmogrifier < Struct.new(:message, :branchname)
NOREF_MATCHER = /#noref/
PREFIX_MATCHER = /\A(feature|bugfix|hotfix)\/(\w{1,10}-\d{1,7})[-_]/ # Matches ABCDE-1234567
PREFIX_FORMAT = "%s | %s"
def prefix
(branchname.to_s[PREFIX_MATCHER, 2] || "").strip
end
def to_s
return message unless prefix =~ /\S/
if message =~ NOREF_MATCHER
output = message.gsub(NOREF_MATCHER, "")
elsif message.include?(prefix)
output = message
else
output = PREFIX_FORMAT % [prefix, message]
end
output.squeeze(" ").strip
end
end
# Overwrites the file which holds the commit message with a fancier one.
def run!
branchname = `git branch --no-color 2> /dev/null`[/^\* (.+)/, 1].to_s
message_path = ARGV.first
message = File.read(message_path).strip.chomp
File.open(message_path, 'w') {|f| f.write Transmogrifier.new(message, branchname) }
end
if ARGV.first != "testing"
run!
else
################################################################################
# TESTS
################################################################################
puts "This will commit stuff to your repo! Do you want to proceed? [yes/n]: "
abort unless $stdin.gets.chomp.downcase == "yes"
require 'shellwords'
def change_branch(name)
`git checkout -B #{name}`
end
def commit(msg)
`echo 'testing' >> a; git add a; git commit -m #{msg.shellescape}`
end
def top_message
`git log --format="%s" -n1`.chomp
end
def assert_equal(a, b)
abort "\nFailure!\n#{a.inspect} != #{b.inspect}\n#{caller.join("\n")}" unless a == b
end
def commit_and_check(msg, expected_message)
commit(msg); assert_equal(top_message, expected_message)
end
change_branch "feature/ABCDE-1234567_some_cool_feature"
commit_and_check "new stuff" , "ABCDE-1234567 | new stuff"
commit_and_check "ABCDE-1234567 | new stuff" , "ABCDE-1234567 | new stuff"
commit_and_check "don't mess with me #noref" , "don't mess with me"
change_branch "bugfix/ABCDE-1234567_some_cool_feature"
commit_and_check "new bugfix stuff" , "ABCDE-1234567 | new bugfix stuff"
commit_and_check "ABCDE-1234567 | new bugfix stuff" , "ABCDE-1234567 | new bugfix stuff"
commit_and_check "don't mess with me #noref" , "don't mess with me"
change_branch "hotfix/ABCDE-1234567_some_cool_feature"
commit_and_check "new hotfix stuff" , "ABCDE-1234567 | new hotfix stuff"
commit_and_check "ABCDE-1234567 | new hotfix stuff" , "ABCDE-1234567 | new hotfix stuff"
commit_and_check "don't mess with me #noref" , "don't mess with me"
change_branch "ABCDE-1234567-some-cool-feature"
commit_and_check "new stuff" , "ABCDE-1234567 | new stuff"
commit_and_check "ABCDE-1234567 | new stuff" , "ABCDE-1234567 | new stuff"
commit_and_check "don't mess with me #noref" , "don't mess with me"
change_branch "some-feature-without-a-task"
commit_and_check "does not change the message" , "does not change the message"
commit_and_check "ABCDE-1234567 | does not change the message" , "ABCDE-1234567 | does not change the message"
commit_and_check "it doesn't remove the #noref" , "it doesn't remove the #noref"
change_branch "master"
commit_and_check "does not change the message" , "does not change the message"
commit_and_check "ABCDE-1234567 | does not change the message" , "ABCDE-1234567 | does not change the message"
commit_and_check "it doesn't remove the #noref" , "it doesn't remove the #noref"
puts "\nAll tests passed."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment