Being a good citizen of the open source community means following the rules concerning software development defined by the team. One of them, sadly the one very frequently neglected , is meaningful commit message with a reference to the task you worked on. Such an info can be later leveraged by tools like FishEye, but that’s another story. So what’s the problem with that for lazy guys like me?
On my open source night shifts I’m mainly involved in Arquillian project (more about it soon). All our code is on GitHub . Each time I work on some task I’m creating a feature branch with the corresponding name (for instance ARQ-1186 ). When I’m done with the work (or consistent part of it) I commit my changes:
$ git commit -m"[ARQ-1186] Introduced new property in configuration \
file to define default (global) transaction mode"
But there’s a little annoying problem with this… I’m not really that keen to memorize the issue number and type these few extra characters by hand each and every time (yes! I’m that lazy!). Obviously you can always customize your shell by using recipies from this blog for instance, but that only solves part of the problem. You don’t need to remember this bloody issue number, but you still need to type it.
So one day I was wondering if it would be possible to prepend commit message using branch information. It turned out to be damn easy.
Git hooks
Git is very powerful tool so no surprise that it has a concept of hooks . Hooks are scripts executed at the certain point of the git workflow. They can be written in any language your shell supports. In our case we are interested in executing script on client side before we commit. Let’s have a look what kind of local hooks we have in our repository’s .git/hooks
folder :
├── applypatch-msg.sample
├── commit-msg.sample
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit.sample
├── prepare-commit-msg.sample
├── pre-rebase.sample
└── update.sample
The names are rather self explanatory - we should use prepare-commit-message
hook to achieve our goal.
A little bit of bash fu
In order to increase our productivity (or keep our lazy nature happy) we simply rename prepare-commit-msg.sample
to prepare-commit-msg
, paste the script listed below and ensure that the file is executable.
<!DOCTYPE html>
<html>
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#">
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>404 · GitHub</title>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" />
<link rel="fluid-icon" href="https://raw.github.com/fluidicon.png" title="GitHub" />
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="apple-touch-icon-114.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114.png" />
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-144.png" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144.png" />
<meta name="msapplication-TileImage" content="/windows-tile.png">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link href="https://a248.e.akamai.net/assets.github.com/assets/github-f966212984ef214218ab1d3b17b380fc4bf8a5d4.css" media="screen" rel="stylesheet" type="text/css" />
<link href="https://a248.e.akamai.net/assets.github.com/assets/github2-154ffaf2b6e54adc7b4ad61fb3c02fc3faccbd4e.css" media="screen" rel="stylesheet" type="text/css" />
<script src="https://a248.e.akamai.net/assets.github.com/assets/frameworks-28923941200b998a3e7422badab5b9be240f9be4.js" type="text/javascript"></script>
<script src="https://a248.e.akamai.net/assets.github.com/assets/github-6824ed52aef61f0c5981b94d98802c4211e5df7c.js" type="text/javascript"></script>
</head>
<body class="logged_out env-production ">
<div id="wrapper">
<div id="header" class="true clearfix">
<div class="container clearfix">
<a class="site-logo " href="https://raw.github.com/">
<img alt="GitHub" class="github-logo-4x" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x.png?1340659511" />
<img alt="GitHub" class="github-logo-4x-hover" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x-hover.png?1340659511" />
</a>
<!--
make sure to use fully qualified URLs here since this nav
is used on error pages on other domains
-->
<ul class="top-nav logged_out">
<li class="pricing"><a href="https://github.com/plans">Signup and Pricing</a></li>
<li class="explore"><a href="https://github.com/explore">Explore GitHub</a></li>
<li class="features"><a href="https://github.com/features">Features</a></li>
<li class="blog"><a href="https://github.com/blog">Blog</a></li>
<li class="login"><a href="https://github.com/login?return_to=%2Fgist%2F1396344%2Fprepare-commit-msg.sh">Sign in</a></li>
</ul>
</div>
</div>
<div class="site clearfix">
<div id="site-container" class="context-loader-container" data-pjax-container>
<style type="text/css">
#header{
border-bottom: 0;
}
.site {
padding: 0;
}
#site-container {
width: 100%;
}
* {
margin: 0px;
padding: 0px;
}
#parallax_wrapper {
position: relative;
z-index: 0;
margin-bottom: 50px;
}
#parallax_field{
overflow: hidden;
position: absolute;
left: 0;
top: 0;
height: 370px;
width: 100%;
}
#parallax_field #parallax_bg {
position: absolute;
top: -20px;
left: -20px;
width: 110%;
height: 425px;
z-index: 1;
}
#parallax_illustration {
display: block;
margin: 0 auto;
width: 940px;
height: 370px;
position: relative;
overflow: hidden;
clear: both;
}
#parallax_illustration #parallax_error_text {
position: absolute;
top: 72px;
left: 72px;
z-index: 10;
}
#parallax_illustration #parallax_octocat {
position: absolute;
top: 94px;
left: 356px;
z-index: 9;
}
#parallax_illustration #parallax_speeder {
position: absolute;
top: 150px;
left: 432px;
z-index: 8;
}
#parallax_illustration #parallax_octocatshadow {
position: absolute;
top: 297px;
left: 371px;
z-index: 7;
}
#parallax_illustration #parallax_speedershadow {
position: absolute;
top: 263px;
left: 442px;
z-index: 6;
}
#parallax_illustration #parallax_building_1 {
position: absolute;
top: 73px;
left: 467px;
z-index: 5;
}
#parallax_illustration #parallax_building_2 {
position: absolute;
top: 113px;
left: 762px;
z-index: 4;
}
#footer-push {
height: 280px;
}
#footer {
margin-top: 0px;
z-index: 12;
}
</style>
<div id="parallax_wrapper">
<div id="parallax_field">
<img alt="building" class="js-plaxify" data-invert="true" data-xrange="0" data-yrange="20" height="415" id="parallax_bg" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_bg.jpg?1340659511" width="940" />
</div>
<div id="parallax_illustration">
<img alt="404 | “This is not the web page you are looking for”" class="js-plaxify" data-xrange="20" data-yrange="10" height="249" id="parallax_error_text" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_errortext.png?1340659511" width="271" />
<img alt="Octobi Wan Catnobi" class="js-plaxify" data-xrange="10" data-yrange="10" height="230" id="parallax_octocat" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_octocat.png?1340659511" width="188" />
<img alt="land speeder" class="js-plaxify" data-xrange="10" data-yrange="10" height="156" id="parallax_speeder" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_speeder.png?1340659511" width="440" />
<img alt="Octobi Wan Catnobi's shadow" class="js-plaxify" data-xrange="10" data-yrange="10" height="49" id="parallax_octocatshadow" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_octocatshadow.png?1340659511" width="166" />
<img alt="land speeder's shadow" class="js-plaxify" data-xrange="10" data-yrange="10" height="75" id="parallax_speedershadow" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_speedershadow.png?1340659511" width="430" />
<img alt="building" class="js-plaxify" data-invert="true" data-xrange="50" data-yrange="20" height="123" id="parallax_building_1" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_building_1.png?1340659511" width="304" />
<img alt="building" class="js-plaxify" data-invert="true" data-xrange="75" data-yrange="30" height="50" id="parallax_building_2" src="https://a248.e.akamai.net/assets.github.com/images/modules/404/parallax_building_2.png?1340659511" width="116" />
</div>
</div>
</div>
<div class="context-overlay"></div>
</div>
<div id="footer-push"></div><!-- hack for sticky footer -->
</div><!-- end of wrapper - hack for sticky footer -->
<!-- footer -->
<div id="footer" >
<div class="upper_footer">
<div class="container clearfix">
<h4 id="blacktocat">GitHub Links</h4>
<ul class="footer_nav">
<h4>GitHub</h4>
<li><a href="https://github.com/about">About</a></li>
<li><a href="https://github.com/blog">Blog</a></li>
<li><a href="https://github.com/features">Features</a></li>
<li><a href="https://github.com/contact">Contact & Support</a></li>
<li><a href="http://training.github.com/">Training</a></li>
<li><a href="http://enterprise.github.com/">GitHub Enterprise</a></li>
<li><a href="http://status.github.com/">Site Status</a></li>
</ul>
<ul class="footer_nav">
<h4>Clients</h4>
<li><a href="http://mac.github.com/">GitHub for Mac</a></li>
<li><a href="http://windows.github.com/">GitHub for Windows</a></li>
<li><a href="http://eclipse.github.com/">GitHub for Eclipse</a></li>
<li><a href="http://mobile.github.com/">GitHub Mobile Apps</a></li>
</ul>
<ul class="footer_nav">
<h4>Tools</h4>
<li><a href="http://get.gaug.es/">Gauges: Web analytics</a></li>
<li><a href="http://speakerdeck.com">Speaker Deck: Presentations</a></li>
<li><a href="https://gist.github.com">Gist: Code snippets</a></li>
<h4 class="second">Extras</h4>
<li><a href="http://jobs.github.com/">Job Board</a></li>
<li><a href="http://shop.github.com/">GitHub Shop</a></li>
<li><a href="http://octodex.github.com/">The Octodex</a></li>
</ul>
<ul class="footer_nav">
<h4>Documentation</h4>
<li><a href="http://help.github.com/">GitHub Help</a></li>
<li><a href="http://developer.github.com/">Developer API</a></li>
<li><a href="http://github.github.com/github-flavored-markdown/">GitHub Flavored Markdown</a></li>
<li><a href="http://pages.github.com/">GitHub Pages</a></li>
</ul>
</div><!-- /.site -->
</div><!-- /.upper_footer -->
<div class="lower_footer">
<div class="container clearfix">
<div id="legal">
<ul>
<li><a href="https://github.com/site/terms">Terms of Service</a></li>
<li><a href="https://github.com/site/privacy">Privacy</a></li>
<li><a href="https://github.com/security">Security</a></li>
</ul>
<p>© 2012 <span title="0.01755s from fe16.rs.github.com">GitHub</span> Inc. All rights reserved.</p>
</div><!-- /#legal or /#legal_ie-->
</div><!-- /.site -->
</div><!-- /.lower_footer -->
</div><!-- /#footer -->
<div id="keyboard_shortcuts_pane" class="instapaper_ignore readability-extra" style="display:none">
<h2>Keyboard Shortcuts <small><a href="#" class="js-see-all-keyboard-shortcuts">(see all)</a></small></h2>
<div class="columns threecols">
<div class="column first">
<h3>Site wide shortcuts</h3>
<dl class="keyboard-mappings">
<dt>s</dt>
<dd>Focus command bar</dd>
</dl>
<dl class="keyboard-mappings">
<dt>?</dt>
<dd>Bring up this help dialog</dd>
</dl>
</div><!-- /.column.first -->
<div class="column middle" style='display:none'>
<h3>Commit list</h3>
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>c <em>or</em> o <em>or</em> enter</dt>
<dd>Open commit</dd>
</dl>
<dl class="keyboard-mappings">
<dt>y</dt>
<dd>Expand URL to its canonical form</dd>
</dl>
</div><!-- /.column.first -->
<div class="column last js-hidden-pane" style='display:none'>
<h3>Pull request list</h3>
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open issue</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
<dd>Submit comment</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> shift p</dt>
<dd>Preview comment</dd>
</dl>
</div><!-- /.columns.last -->
</div><!-- /.columns.equacols -->
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Issues</h3>
<div class="columns threecols">
<div class="column first">
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>x</dt>
<dd>Toggle selection</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open issue</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
<dd>Submit comment</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> shift p</dt>
<dd>Preview comment</dd>
</dl>
</div><!-- /.column.first -->
<div class="column last">
<dl class="keyboard-mappings">
<dt>c</dt>
<dd>Create issue</dd>
</dl>
<dl class="keyboard-mappings">
<dt>l</dt>
<dd>Create label</dd>
</dl>
<dl class="keyboard-mappings">
<dt>i</dt>
<dd>Back to inbox</dd>
</dl>
<dl class="keyboard-mappings">
<dt>u</dt>
<dd>Back to issues</dd>
</dl>
<dl class="keyboard-mappings">
<dt>/</dt>
<dd>Focus issues search</dd>
</dl>
</div>
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Issues Dashboard</h3>
<div class="columns threecols">
<div class="column first">
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open issue</dd>
</dl>
</div><!-- /.column.first -->
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Network Graph</h3>
<div class="columns equacols">
<div class="column first">
<dl class="keyboard-mappings">
<dt><span class="badmono">←</span> <em>or</em> h</dt>
<dd>Scroll left</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="badmono">→</span> <em>or</em> l</dt>
<dd>Scroll right</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="badmono">↑</span> <em>or</em> k</dt>
<dd>Scroll up</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="badmono">↓</span> <em>or</em> j</dt>
<dd>Scroll down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>t</dt>
<dd>Toggle visibility of head labels</dd>
</dl>
</div><!-- /.column.first -->
<div class="column last">
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">←</span> <em>or</em> shift h</dt>
<dd>Scroll all the way left</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">→</span> <em>or</em> shift l</dt>
<dd>Scroll all the way right</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">↑</span> <em>or</em> shift k</dt>
<dd>Scroll all the way up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">↓</span> <em>or</em> shift j</dt>
<dd>Scroll all the way down</dd>
</dl>
</div><!-- /.column.last -->
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<div class="columns threecols">
<div class="column first js-hidden-pane" style='display:none'>
<h3>Source Code Browsing</h3>
<dl class="keyboard-mappings">
<dt>t</dt>
<dd>Activates the file finder</dd>
</dl>
<dl class="keyboard-mappings">
<dt>l</dt>
<dd>Jump to line</dd>
</dl>
<dl class="keyboard-mappings">
<dt>w</dt>
<dd>Switch branch/tag</dd>
</dl>
<dl class="keyboard-mappings">
<dt>y</dt>
<dd>Expand URL to its canonical form</dd>
</dl>
</div>
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<div class="columns threecols">
<div class="column first">
<h3>Browsing Commits</h3>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
<dd>Submit comment</dd>
</dl>
<dl class="keyboard-mappings">
<dt>escape</dt>
<dd>Close form</dd>
</dl>
<dl class="keyboard-mappings">
<dt>p</dt>
<dd>Parent commit</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o</dt>
<dd>Other parent commit</dd>
</dl>
</div>
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Notifications</h3>
<div class="columns threecols">
<div class="column first">
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open notification</dd>
</dl>
</div><!-- /.column.first -->
<div class="column second">
<dl class="keyboard-mappings">
<dt>e <em>or</em> shift i <em>or</em> y</dt>
<dd>Mark as read</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift m</dt>
<dd>Mute thread</dd>
</dl>
</div><!-- /.column.first -->
</div>
</div>
</div>
<div id="markdown-help" class="instapaper_ignore readability-extra">
<h2>Markdown Cheat Sheet</h2>
<div class="cheatsheet-content">
<div class="mod">
<div class="col">
<h3>Format Text</h3>
<p>Headers</p>
<pre>
# This is an <h1> tag
## This is an <h2> tag
###### This is an <h6> tag</pre>
<p>Text styles</p>
<pre>
*This text will be italic*
_This will also be italic_
**This text will be bold**
__This will also be bold__
*You **can** combine them*
</pre>
</div>
<div class="col">
<h3>Lists</h3>
<p>Unordered</p>
<pre>
* Item 1
* Item 2
* Item 2a
* Item 2b</pre>
<p>Ordered</p>
<pre>
1. Item 1
2. Item 2
3. Item 3
* Item 3a
* Item 3b</pre>
</div>
<div class="col">
<h3>Miscellaneous</h3>
<p>Images</p>
<pre>
![GitHub Logo](/images/logo.png)
Format: ![Alt Text](url)
</pre>
<p>Links</p>
<pre>
http://github.com - automatic!
[GitHub](http://github.com)</pre>
<p>Blockquotes</p>
<pre>
As Kanye West said:
> We're living the future so
> the present is our past.
</pre>
</div>
</div>
<div class="rule"></div>
<h3>Code Examples in Markdown</h3>
<div class="col">
<p>Syntax highlighting with <a href="http://github.github.com/github-flavored-markdown/" title="GitHub Flavored Markdown" target="_blank">GFM</a></p>
<pre>
```javascript
function fancyAlert(arg) {
if(arg) {
$.facebox({div:'#foo'})
}
}
```</pre>
</div>
<div class="col">
<p>Or, indent your code 4 spaces</p>
<pre>
Here is a Python code example
without syntax highlighting:
def foo:
if not bar:
return true</pre>
</div>
<div class="col">
<p>Inline code for comments</p>
<pre>
I think you should use an
`<addr>` element here instead.</pre>
</div>
</div>
</div>
</div>
<div id="ajax-error-message" class="flash flash-error">
<span class="mini-icon mini-icon-exclamation"></span>
Something went wrong with that request. Please try again.
<a href="#" class="mini-icon mini-icon-remove-close ajax-error-dismiss"></a>
</div>
<div id="logo-popup">
<h2>Looking for the GitHub logo?</h2>
<ul>
<li>
<h4>GitHub Logo</h4>
<a href="http://github-media-downloads.s3.amazonaws.com/GitHub_Logos.zip"><img alt="Github_logo" src="https://a248.e.akamai.net/assets.github.com/images/modules/about_page/github_logo.png?1340659511" /></a>
<a href="http://github-media-downloads.s3.amazonaws.com/GitHub_Logos.zip" class="minibutton download">Download</a>
</li>
<li>
<h4>The Octocat</h4>
<a href="http://github-media-downloads.s3.amazonaws.com/Octocats.zip"><img alt="Octocat" src="https://a248.e.akamai.net/assets.github.com/images/modules/about_page/octocat.png?1340659511" /></a>
<a href="http://github-media-downloads.s3.amazonaws.com/Octocats.zip" class="minibutton download">Download</a>
</li>
</ul>
</div>
<span id='server_response_time' data-time='0.02591' data-host='fe16'></span>
</body>
</html>
From now on we don’t need to remember the issue number anymore! Executing
$ git commit -m”Introduced new property in configuration file \
to define default (global) transaction mode”
will result with [ARQ-1186] Introduced new property in configuration file to define default (global) transaction mode
as commit message. Life is so easier now ;)
Note: If you are using Eclipse git integration this approach won’t work. EGit is not aware of commit hooks.