This hooks will remind you to reference task in your commit, and remember your task ref for branch. Your commit messages will have style "[reference] message"
- Create two files in your repo - e.g.
[PROJECT_ROOT]/hooks/prepare-commit-msg.rb
and[PROJECT_ROOT]/hooks/post-checkout.rb
- Copy to first file (here will assume that this is a
[PROJECT_ROOT]/hooks/prepare-commit-msg.rb
):
#!/usr/bin/env ruby
require 'fileutils'
MESSAGE_WITH_ISSUE_PATTERN = /^\[(#\d+)\]/ # Regexp that matches messages with specified issue
# Remember that actual issue link will be taken from
# message.match(MESSAGE_WITH_ISSUE_PATTERN)[1]
# so currrent example is for github issues references
ISSUE_PATTERN = /^#\d+$/ # Regexp that matches issue reference
# e.g. if you want to reference github issues it will be /^#\d+$/
# or may be you want to reference trello -- /^https:\/\/trello.com/.+/
# Have no idea why STDIN.reopen is not working, so this
def read_stdin
open '/dev/tty' do |f|
input = f.gets.chomp
yield input
end
end
def save_issue(number)
File.write '.git/ISSUE', number
branch = File.read('.git/HEAD').match /^ref: refs\/heads\/(.+)/
FileUtils.mkdir_p '.git/refs/issues'
File.write ".git/refs/issues/#{branch[1]}", number if branch
end
def cache_issue(number, force: false)
if !force && File.exists?('.git/ISSUE')
return if number.to_s == File.read('.git/ISSUE')
puts "Do you want to update issue in branch? y(es)/anything else"
read_stdin do |input|
save_issue number if input.downcase.strip.match? /^y(es)?$/
end
else
save_issue number
end
end
msg = File.read(ARGV[0])
issue_match = msg.match MESSAGE_WITH_ISSUE_PATTERN
unless issue_match.nil?
cache_issue issue_match[1]
exit 0
end
issue = File.read('.git/ISSUE') if File.exists? '.git/ISSUE'
File.write(ARGV[0], "[#{issue}] #{msg}") && exit(0) if !issue.nil? && !issue.empty?
puts "Do you want to specify issue? Enter a reference if yes or anything else if no."
read_stdin do |input|
if input.match? ISSUE_PATTERN
File.write ARGV[0], "[#{input}] #{msg}"
cache_issue input, force: true
end
end
exit 0
- Specify your own regexp in
MESSAGE_WITH_ISSUE_PATTERN
andISSUE_PATTERN
which will satisfy your needs - Copy to second file (assume that this is
[PROJECT_ROOT]/hooks/post-checkout.rb
):
#!/usr/bin/env ruby
heads = '.git/refs/heads/'
issues = '.git/refs/issues/'
branch = File.read('.git/HEAD').match /^ref: refs\/heads\/(.+)/
if !branch.nil? && File.exists?(issues + branch[1])
issue = File.read issues + branch[1]
puts "Current issue is #{issue}"
File.write '.git/ISSUE', issue
else
puts "Current issue is not specified yet"
File.write '.git/ISSUE', ''
end
exit 0
- Create links:
ln -s ../../hooks/prepare-commit-msg.rb .git/hooks/prepare-commit-msg
ln -s ../../hooks/post-checkout.rb .git/hooks/post-checkout
- Add permissions:
chmod u+x .git/hooks/prepare-commit-msg
chmod u+x .git/hooks/post-checkout
- When you will run
git commit -m "My awesome commit!"
you will be asked for issue. For next time, your commit in same branch will marked automatically. - If you want to redefine issue in branch, you just need to ref new issue. E.g. with default values (reference to GitHub)
git commit -m "[#5] One more awesome commit"
. You will be asked if you want to update issue ref permanently or just for this commit.