Skip to content

Instantly share code, notes, and snippets.

@EmmanuelOga
Created June 13, 2012 22:01
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save EmmanuelOga/2926764 to your computer and use it in GitHub Desktop.
Save EmmanuelOga/2926764 to your computer and use it in GitHub Desktop.
commit-msg hook to add a prefix to commit messages
#!/usr/bin/env ruby
#
# Git commit-msg hook. If your branch name is in the form "US1234-postfix", or
# "US1234_postfix", it automatically adds the prefix "[US1234]" to commit
# messages.
#
# Example
# =======
#
# git checkout -b US1234-some-cool-feature
# git commit "new stuff"
# git log => will show up "[US1234] 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://raw.github.com/gist/2926764/7b61cd1f2f1f399492182ed4b5dbabca3f96cced/commit-msg > your_project/.git/hooks
# chmod +x .git/hooks/commit-msg
#
# Testing
# =======
#
# git init a new repo, install the commit hook, and run:
#
# ruby .git/hooks/commit-msg testing
#
# --
# E. Oga, 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(\w{1,2}\d{4,5})[-_]/
PREFIX_FORMAT = "[%s] %s"
def prefix
(branchname.to_s[PREFIX_MATCHER, 1] || "").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 "US1234_some_cool_feature"
commit_and_check "new stuff" , "[US1234] new stuff"
commit_and_check "[US1234] new stuff" , "[US1234] new stuff"
commit_and_check "don't mess with me #noref" , "don't mess with me"
change_branch "US1234-some-cool-feature"
commit_and_check "new stuff" , "[US1234] new stuff"
commit_and_check "[US1234] new stuff" , "[US1234] 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 "[US1234] does not change the message" , "[US1234] 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 "[US1234] does not change the message" , "[US1234] 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