<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>David Winterbottom (@codeinthehole)</title><link>http://codeinthehole.com/writing/</link><description>Latest writing</description><atom:link href="http://codeinthehole.com/writing/feed/" rel="self"></atom:link><language>en-us</language><lastBuildDate>Thu, 16 Mar 2017 20:25:30 -0000</lastBuildDate><item><title>Octopus Energy</title><link>http://codeinthehole.com/writing/octopus-energy/</link><description>&lt;p&gt;Last Wednesday was my last day at Yoyo Wallet. Thursday marked my first day at
Octopus Energy.&lt;/p&gt;
&lt;p&gt;I'm deeply excited about Octopus. Through innovative use of technology,
especially automation and cloud computing, Octopus Energy is going to radically
change how people consume and pay for energy in the UK. We're going to be both
cheaper and massively better at customer service than the much-maligned
incumbents.&lt;/p&gt;
&lt;p&gt;Right now, &lt;a class="reference external" href="http://tech.octopus.energy/2015/11/23/tech-jobs.html"&gt;we're looking to build a superb tech team&lt;/a&gt;. Get in touch if you're
looking for a challenge and would like to play a formative part in a company
that's genuinely making the world a better place, in helping transition the UK
to a lower carbon future.&lt;/p&gt;
</description><guid>http://codeinthehole.com/writing/octopus-energy/</guid></item><item><title>A useful template for commit messages</title><link>http://codeinthehole.com/writing/a-useful-template-for-commit-messages/</link><description>&lt;p&gt;Here's a useful heuristic for writing better commit messages. Set your commit
message template to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;# If applied, this commit will...

# Explain why this change is being made

# Provide links to any relevant tickets, articles or other resources
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and you'll be guided into writing concise commit subjects in the imperative
mood - a good practice.  See rule 5 of Chris Beam's &lt;a class="reference external" href="http://chris.beams.io/posts/git-commit/"&gt;&amp;quot;How to write a commit message&amp;quot;&lt;/a&gt;
for the inspiration of this tip and more reasoning on the use of the imperative
mood.&lt;/p&gt;
&lt;p&gt;To do this in Git, save the above content in a file (eg
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.git_commit_msg.txt&lt;/span&gt;&lt;/tt&gt;) and run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config --global commit.template ~/.git_commit_msg.txt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here's what this looks like in practice:&lt;/p&gt;
&lt;img alt="/static/images/git-commit-snap.png" src="/static/images/git-commit-snap.png" style="width: 800px;" /&gt;
&lt;p&gt;Try it - it's ...&lt;/p&gt;</description><guid>http://codeinthehole.com/writing/a-useful-template-for-commit-messages/</guid></item><item><title>Copying Postgres output into a spreadsheet</title><link>http://codeinthehole.com/writing/copying-postgres-output-into-a-spreadsheet/</link><description>&lt;p&gt;I often need to grab information from a Postgres database and paste it into a
spreadsheet for sharing with others. Google Sheets needs the pasted
data to be tab-separated in order to be correctly split into columns. This isn't
the default behaviour for psql but here's how to configure psql's output to get
it.&lt;/p&gt;
&lt;p&gt;At a psql prompt, switch to unaligned output&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;\a&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and set the field separator to a tab character:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="gp"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;\f&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;\t&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;then the output from subsequent &lt;tt class="docutils literal"&gt;SELECT ...&lt;/tt&gt; statements can be cleanly pasted
into your Google Doc.&lt;/p&gt;
</description><guid>http://codeinthehole.com/writing/copying-postgres-output-into-a-spreadsheet/</guid></item><item><title>An SSH tip for modern AWS patrons</title><link>http://codeinthehole.com/writing/an-ssh-tip-for-modern-aws-patrons/</link><description>&lt;p&gt;Cloud computing and immutable infrastructure deployments have changed the way I
use SSH. I miss the days when I could run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh app1-prod
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to jump onto a machine and investigate an issue. This would work as,
back in the days of yore, your web servers didn't change IP address
several times a week so I could create a helpful alias in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.ssh/config&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;Host app1-prod
    User example_user
    HostName 74.207.251.29
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This circumvented the labour-intensive act of typing in the remote username and
IP address when SSHing around town.&lt;/p&gt;
&lt;p&gt;I can no longer do this as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Immutable infrastructure deployments mean EC2 instances are replaced for
every update so the IP addresses keep changing.  Life is too short to ...&lt;/li&gt;&lt;/ul&gt;</description><guid>http://codeinthehole.com/writing/an-ssh-tip-for-modern-aws-patrons/</guid></item><item><title>commandlinefu.com is in new hands</title><link>http://codeinthehole.com/writing/commandlinefucom-is-in-new-hands/</link><description>&lt;p&gt;For the record, I no longer maintain &lt;a class="reference external" href="http://www.commandlinefu.com/"&gt;commandlinefu.com&lt;/a&gt;. I've handed over the
baton to notable Bay Area celebrity, Jon Hendren (&lt;a class="reference external" href="https://twitter.com/fart"&gt;&amp;#64;fart&lt;/a&gt;). This is a good thing
for the site and its users as I have been unable to do much maintenance in
recent times. I look forward to seeing how the site evolves.&lt;/p&gt;
</description><guid>http://codeinthehole.com/writing/commandlinefucom-is-in-new-hands/</guid></item><item><title>Backing up Postgres database rows before deleting them</title><link>http://codeinthehole.com/writing/backing-up-database-rows-in-postgres-before-deleting-them/</link><description>&lt;blockquote&gt;
Hmmm, this delete statement is taking longer than I thought it would...&lt;/blockquote&gt;
&lt;p&gt;If you ever have to manually run a SQL delete statement in &lt;tt class="docutils literal"&gt;psql&lt;/tt&gt;, you can
back-up the rows you're about to delete:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;copy&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/tmp/backup.csv&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and, if you've got your filter clause wrong (we've all done it), restore them with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;copy&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/tmp/backup.csv&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Moderately useful.&lt;/p&gt;
</description><guid>http://codeinthehole.com/writing/backing-up-database-rows-in-postgres-before-deleting-them/</guid></item><item><title>Avoiding clashing Django migrations</title><link>http://codeinthehole.com/writing/avoiding-clashing-django-migrations/</link><description>&lt;p&gt;Managing South migrations on a multi-developer Django project can be painful.
Developers working on separate branches will often create migrations for the
same app with the same migration number &lt;a class="footnote-reference" href="#id3" id="id1"&gt;[1]&lt;/a&gt;. When merged into master,
these clashing migrations can cause deployment hiccups as South will complain if
migrations are applied out of order.&lt;/p&gt;
&lt;p&gt;There are various techniques available for dealing with this &lt;a class="footnote-reference" href="#id4" id="id2"&gt;[2]&lt;/a&gt;, but what we do
at &lt;a class="reference external" href="http://justyoyo.com/"&gt;Yoyo&lt;/a&gt; is test for such clashes as part of our Travis continuous integration.&lt;/p&gt;
&lt;p&gt;This is done by calling a &lt;tt class="docutils literal"&gt;makefile&lt;/tt&gt; target from &lt;tt class="docutils literal"&gt;.travis.yml&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# .travis.yml&lt;/span&gt;

&lt;span class="l-Scalar-Plain"&gt;language&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;python&lt;/span&gt;

&lt;span class="l-Scalar-Plain"&gt;python&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;2.7&lt;/span&gt;

&lt;span class="l-Scalar-Plain"&gt;install&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;make virtualenv&lt;/span&gt;

&lt;span class="l-Scalar-Plain"&gt;script&lt;/span&gt;
    &lt;span class="l-Scalar-Plain"&gt;- make test&lt;/span&gt;
    &lt;span class="l-Scalar-Plain"&gt;- make migration_test&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where the &lt;tt class="docutils literal"&gt;migration_test&lt;/tt&gt; target is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# makefile&lt;/span&gt;

&lt;span class="nv"&gt;MIGRATION_CLASHES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;shell find . -type f -name &lt;span class="s2"&gt;&amp;quot;*.py&amp;quot;&lt;/span&gt; | grep ...&lt;/pre&gt;&lt;/div&gt;</description><guid>http://codeinthehole.com/writing/avoiding-clashing-django-migrations/</guid></item><item><title>Bootstrapped virtualenvs</title><link>http://codeinthehole.com/writing/bootstrapped-virtualenvs/</link><description>&lt;p&gt;The excellent &lt;a class="reference external" href="https://bitbucket.org/dhellmann/virtualenvwrapper.."&gt;virtualenvwrapper&lt;/a&gt; supports a &lt;tt class="docutils literal"&gt;postmkvirtualenv&lt;/tt&gt; script to
bootstrap your virtual environments. Here's a useful implementation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="c"&gt;# Grab project name from virtualenv name&lt;/span&gt;
&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename &lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Set terminal title on postactivate&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;title $NAME&amp;quot;&lt;/span&gt; &amp;gt; &lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;/bin/postactivate

&lt;span class="c"&gt;# Change directory to root of project on postactivate. We assume the&lt;/span&gt;
&lt;span class="c"&gt;# mkvirtualenv is being run from the root of the project. This line&lt;/span&gt;
&lt;span class="c"&gt;# will need to edited later if not.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd $PWD&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;/bin/postactivate

&lt;span class="c"&gt;# Run postactivate now to get the title set&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;/bin/postactivate
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This ensures that a new virtualenv has a &lt;tt class="docutils literal"&gt;postactivate&lt;/tt&gt; script which:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Sets the terminal title to that of the virtualenv&lt;/li&gt;
&lt;li&gt;Changes directory to the root of the project&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By convention, such ...&lt;/p&gt;</description><guid>http://codeinthehole.com/writing/bootstrapped-virtualenvs/</guid></item><item><title>Integrating Django application metrics into Zabbix</title><link>http://codeinthehole.com/writing/integrating-django-application-metrics-into-zabbix/</link><description>&lt;p&gt;At &lt;a class="reference external" href="http://www.tangentsnowball.com"&gt;Tangent&lt;/a&gt;, we use &lt;a class="reference external" href="http://www.zabbix.com/"&gt;Zabbix&lt;/a&gt; for monitoring and alerting. This is a note-to-self on
how to configure application monitoring.&lt;/p&gt;
&lt;div class="section" id="management-command"&gt;
&lt;h1&gt;Management command&lt;/h1&gt;
&lt;p&gt;You need a script that prints out a value to STDOUT. A simple management command
suffices:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.management.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CommandError&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="n"&gt;method_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;fetch_&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;CommandError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;No method found with name &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method_name&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;fetchers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;fetch&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;fetcher&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fetchers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;docstring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__doc__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__doc__&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;no description&amp;gt;&amp;quot;&lt;/span&gt;
            &lt;span class="n"&gt;descriptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append ...&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description><guid>http://codeinthehole.com/writing/integrating-django-application-metrics-into-zabbix/</guid></item><item><title>Linking to Github</title><link>http://codeinthehole.com/writing/linking-to-github/</link><description>&lt;p&gt;It was rightly &lt;a class="reference external" href="http://andrew.yurisich.com/work/2014/07/16/dont-link-that-line-number/"&gt;pointed out yesterday&lt;/a&gt; that it's dangerous to link to lines or
blocks of code on Github without explicitly specifying the commit hash in the
URL. On this theme, consider this git command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git browse -u -- commit/&lt;span class="k"&gt;$(&lt;/span&gt;git rev-parse HEAD&lt;span class="k"&gt;)&lt;/span&gt;
https://github.com/tangentlabs/django-oscar/commit/17851d4b66922f8d7e203e2b469040690c84a0db
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This emits the Github URL to the &lt;tt class="docutils literal"&gt;HEAD&lt;/tt&gt; commit on the current branch,
specifying the commit hash in the URL. Note that the &lt;tt class="docutils literal"&gt;browse&lt;/tt&gt; subcommand is
provided by the excellent &lt;a class="reference external" href="https://hub.github.com/"&gt;hub&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;Pasting links to commits is common, both for mailing list posts and within
discussion on Github itself. Getting the correct URL quickly is useful.&lt;/p&gt;
&lt;p&gt;We can streamline further using an alias:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# ~/.gitconfig&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; !hub browse -u -- commit ...&lt;/pre&gt;&lt;/div&gt;</description><guid>http://codeinthehole.com/writing/linking-to-github/</guid></item><item><title>Continuously rebuild your project</title><link>http://codeinthehole.com/writing/continuously-re-build-your-project/</link><description>&lt;p&gt;New developers joining a project will often find that the project won't build
cleanly on their machine, and hours of time will be sunk into setting up the
project so work can start. This is sad and expensive for all concerned.&lt;/p&gt;
&lt;p&gt;This is a particular menace in agencies (or anywhere with lots of small projects)
where a large team of developers need to jump between projects.  Tools like
&lt;a class="reference external" href="http://www.vagrantup.com"&gt;Vagrant&lt;/a&gt; and &lt;a class="reference external" href="http://www.docker.com/"&gt;Docker&lt;/a&gt; can help but aren't the panacea they first seem to be &lt;a class="footnote-reference" href="#id2" id="id1"&gt;[*]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Counter this by using continuous integration to build your project from scratch.
Then any changes that break the build process (such as database schema changes
not applying correctly) will be spotted early. New team members will ...&lt;/p&gt;</description><guid>http://codeinthehole.com/writing/continuously-re-build-your-project/</guid></item><item><title>Using the silver searcher with Vim</title><link>http://codeinthehole.com/writing/using-the-silver-searcher-with-vim/</link><description>&lt;p&gt;If you're not doing this already, then you should use the &lt;a class="reference external" href="http://geoff.greer.fm/2011/12/27/the-silver-searcher-better-than-ack/"&gt;Silver Searcher&lt;/a&gt;
within Vim for rapid, convenient file searching. In a nutshell, &lt;tt class="docutils literal"&gt;ag&lt;/tt&gt; offers
similar functionality to &lt;tt class="docutils literal"&gt;ack&lt;/tt&gt; but with much better performance.&lt;/p&gt;
&lt;p&gt;It's easily installed - on OSX, run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew install the_silver_searcher
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Urge Vim to use it for &lt;tt class="docutils literal"&gt;:grep&lt;/tt&gt; commands by adding the following to
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.vimrc&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;if executable(&amp;#39;ag&amp;#39;)
    &amp;quot; Note we extract the column as well as the file and line number
    set grepprg=ag\ --nogroup\ --nocolor\ --column
    set grepformat=%f:%l:%c%m
endif
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;:grep&lt;/tt&gt; searches are now lightning-fast and respectful of your
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.gitignore&lt;/span&gt;&lt;/tt&gt; patterns. It's genuinely impressive.&lt;/p&gt;
&lt;p&gt;Improve your efficiency further by remapping the keys for jumping through search
matches (stored in the &amp;quot;quickfix ...&lt;/p&gt;</description><guid>http://codeinthehole.com/writing/using-the-silver-searcher-with-vim/</guid></item><item><title>The road to Oscar 1.0</title><link>http://codeinthehole.com/writing/the-road-to-oscar-10/</link><description>&lt;img alt="/static/images/oscar.png" class="noborder align-right" src="/static/images/oscar.png" /&gt;
&lt;p&gt;Oscar 0.7 was &lt;a class="reference external" href="http://django-oscar.readthedocs.org/en/latest/releases/v0.7.html"&gt;released this week&lt;/a&gt;, a comparatively minor house-keeping release
that allowed us to reduce our pull-request and issue backlogs.  We have a plan
for Oscar through 2014 and this article outlines the roadmap.&lt;/p&gt;
&lt;div class="section" id="v1-0"&gt;
&lt;h1&gt;v1.0&lt;/h1&gt;
&lt;p&gt;We're aiming to be v1.0 before the end of the year &lt;a class="footnote-reference" href="#id3" id="id1"&gt;[*]&lt;/a&gt;.  Oscar has been beta for
nearly two years and its APIs are stabilising. We're ready to commit to the
backward compatibility responsibilities associated with coming out of beta.&lt;/p&gt;
&lt;p&gt;Plus, this will help &lt;a class="reference external" href="http://www.tangentsnowball.com/"&gt;Tangent Snowball&lt;/a&gt; (who sponsor Oscar's development) promote
Oscar to blue-chip or &amp;quot;enterprise&amp;quot; clients, who feel nervous enough using
open-source e-commerce software, let alone &lt;em&gt;beta&lt;/em&gt; open-source software.&lt;/p&gt;
&lt;p&gt;There isn't a lot to do before this ...&lt;/p&gt;&lt;/div&gt;</description><guid>http://codeinthehole.com/writing/the-road-to-oscar-10/</guid></item><item><title>Command-line tips for effective release announcements</title><link>http://codeinthehole.com/writing/command-line-tips-for-effective-release-announcements/</link><description>&lt;p&gt;We finally &lt;a class="reference external" href="http://django-oscar.readthedocs.org/en/latest/releases/v0.6.html"&gt;released Oscar 0.6&lt;/a&gt; last week.  The process brought home the
importance of writing your release notes as you go rather than at the end.
It's a real pain to extract the key changes from 1200 commits spread over the
last 8 months.  Lesson learnt.&lt;/p&gt;
&lt;p&gt;This article is largely a note-to-self in case I have to repeat the process.
However, if you do find yourself in a similar position, here are a few
command-line tricks for analysing your git history.&lt;/p&gt;
&lt;div class="section" id="analysing-codebase-changes-since-a-tag"&gt;
&lt;h1&gt;Analysing codebase changes since a tag&lt;/h1&gt;
&lt;p&gt;Basics: browse commits since the last tagged release&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log 0.5..0.6
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--name-status&lt;/span&gt;&lt;/tt&gt; option for &lt;tt class="docutils literal"&gt;git diff&lt;/tt&gt; is useful for analysing codebase changes
between two commits.  For instance ...&lt;/p&gt;&lt;/div&gt;</description><guid>http://codeinthehole.com/writing/command-line-tips-for-effective-release-announcements/</guid></item><item><title>How to install PostGIS and GeoDjango on Ubuntu</title><link>http://codeinthehole.com/writing/how-to-install-postgis-and-geodjango-on-ubuntu/</link><description>&lt;p&gt;Despite its &lt;a class="reference external" href="https://docs.djangoproject.com/en/dev/ref/contrib/gis/install/"&gt;extensive documentation&lt;/a&gt;, getting GeoDjango installed and configured
can be a pain.  Here are my notes for future reference:&lt;/p&gt;
&lt;div class="section" id="installation-on-ubuntu-12-04"&gt;
&lt;h1&gt;Installation on Ubuntu 12.04&lt;/h1&gt;
&lt;p&gt;First, ensure your system locale is UTF8 as PostgreSQL uses it to determine its
default encoding during installation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LANGUAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;en_US.UTF-8&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;en_US.UTF-8&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LC_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;en_US.UTF-8&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now install dependencies:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo apt-get update
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo apt-get install postgresql-server-dev-9.1 postgresql-9.1-postgis
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;PostgreSQL should now be installed and running with UTF8 encodings.  Verify this
with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo -u postgres psql -l
                                     List of databases
       Name       |  Owner   | Encoding |   Collate   |    Ctype    |
------------------+----------+----------+-------------+-------------+-...
 postgres         | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0        | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
                  |          |          |             |             |
 template1        | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
                  |          |          |             |             |
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now create a spatial database ...&lt;/p&gt;&lt;/div&gt;</description><guid>http://codeinthehole.com/writing/how-to-install-postgis-and-geodjango-on-ubuntu/</guid></item></channel></rss>