<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>coding is the best</description><title>JJ Geewax</title><generator>Tumblr (3.0; @geewax)</generator><link>http://geewax.org/</link><item><title>Getting started with tmux</title><description>&lt;p&gt;As a long-time user of GNU screen, I knew it would be difficult to switch, but I&amp;#8217;ve made the move and am so far pretty happy. tmux does all the same things that screen does, but was a lot easier to customize. I wanted to share &lt;a href="https://gist.github.com/jgeewax/5218315" target="_blank"&gt;my tmux configuration file&lt;/a&gt; and other things that made the switch all that much more amazing.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Keyboard bindings&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I changed the default keyboard bindings to be more like screen:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;span&gt;Ctrl-b? Forget that. Ctrl-a all the way.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Ctrl-(left/right) arrow to move between windows? Hell yes.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Ctrl-a twice to go &amp;#8220;back&amp;#8221;? Perfect.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Ctrl-a, r to reload the config file made it very easy to debug.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;&lt;strong&gt;Status bar at the bottom&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I made my status bar have the session name and my machine name on the far left, the various tabs centered in the middle, and the system time and date on the far right. It was very easy to configure, and I&amp;#8217;m guessing I&amp;#8217;ll end up tweaking it from time to time.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Project-specific configurations (and attach tool)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s the coolest part in my opinion. I forked &lt;a href="https://github.com/ryandotsmith/tat" target="_blank"&gt;a repository called &amp;#8220;tat&amp;#8221;&lt;/a&gt; that does some nifty things to make project-specific configurations really easy to set up consistently, and attach to them later on. Oh, and there&amp;#8217;s tab completion for existing sessions as well as for your project directory names. &lt;a href="https://github.com/jgeewax/tat/blob/b26503174464ea622aab33bcc46e600c3bb0d11e/tat.sh" target="_blank"&gt;Check out my fork&lt;/a&gt; to see the details.&lt;/p&gt;
&lt;p&gt;With tat you can create a .tmux file in your project directory, which be run with the first argument being the session name. You can use this to configure your project workspace easily and consistently. Here&amp;#8217;s one of my &lt;a href="https://gist.github.com/jgeewax/5218567" target="_blank"&gt;example .tmux project files&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Tab completion&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Don&amp;#8217;t forget to enable tab completion. On Ubuntu I did the following:&lt;/p&gt;
&lt;pre&gt;$ sudo curl &lt;a href="https://raw.github.com/mithro/rcfiles/master/bash/completion/tmux"&gt;https://raw.github.com/mithro/rcfiles/master/bash/completion/tmux&lt;/a&gt; &amp;gt; /usr/share/bash-completion/completions/tmux&lt;/pre&gt;</description><link>http://geewax.org/post/45958712464</link><guid>http://geewax.org/post/45958712464</guid><pubDate>Thu, 21 Mar 2013 21:42:00 -0400</pubDate><category>tmux</category><category>coding</category><category>bash</category><category>shell</category><category>screen</category></item><item><title>Python Dictionary Comprehensions</title><description>&lt;p&gt;I&amp;#8217;m a little embarrassed to say that I haven&amp;#8217;t yet used these in my own code &amp;#8212; they seem so obvious now that I look back on it.&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; d = {'a': 1, 'b': 2', 'c': 3}
&amp;gt;&amp;gt;&amp;gt; keys = ['a', 'c']
&amp;gt;&amp;gt;&amp;gt; { k: d[k] for k in keys }
{'a': 1, 'c': 3}
&lt;/pre&gt;</description><link>http://geewax.org/post/45914087017</link><guid>http://geewax.org/post/45914087017</guid><pubDate>Thu, 21 Mar 2013 10:43:00 -0400</pubDate><category>python</category><category>coding</category></item><item><title>Task Queue support in App Engine's ext.Testbed</title><description>&lt;p&gt;A while back I wrote &lt;a href="http://github.com/jgeewax/gaetestbed" target="_blank"&gt;some (now deprecated) code&lt;/a&gt; that allowed you to easily test your Python App Engine applications and their interaction with the App Engine APIs. When we got acquired by Google, I started working with some of the awesome App Engine engineers on making that code part of the official App Engine codebase.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;We &lt;a href="https://developers.google.com/appengine/docs/python/tools/localunittesting"&gt;launched that&lt;/a&gt;, but one of the APIs that was noticeably lacking helper-methods was the Task Queue. I added one of the old methods (&lt;code&gt;get_filtered_tasks()&lt;/code&gt;) but&lt;/span&gt;&lt;span&gt; a bit later I noticed a pretty serious bug where timezones weren&amp;#8217;t handled properly.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So that code hid quietly in the App Engine code base, undocumented and technically broken. &lt;strong&gt;Sorry :(&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I wrote some extra code to fix it, but that didn&amp;#8217;t get merged into the main repository for quite a while.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;But now it&amp;#8217;s here.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;If you&amp;#8217;re curious about the change, feel free to &lt;a href="https://code.google.com/p/googleappengine/source/diff?spec=svn318&amp;amp;r=308&amp;amp;format=side&amp;amp;path=/trunk/python/google/appengine/api/taskqueue/taskqueue_stub.py&amp;amp;old_path=/trunk/python/google/appengine/api/taskqueue/taskqueue_stub.py&amp;amp;old=257"&gt;check out the diff&lt;/a&gt; (scroll to the bottom). The method is still called &lt;code&gt;get_filtered_tasks()&lt;/code&gt; and takes several arguments as &amp;#8220;filters&amp;#8221; for various properties of tasks &amp;#8212; and it should properly handle timezones when you set the &lt;code&gt;eta&lt;/code&gt; or &lt;code&gt;countdown&lt;/code&gt; properties when creating tasks.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Sorry for the delay. And enjoy.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;PS:&lt;/strong&gt; Since this isn&amp;#8217;t documented on the official App Engine page, the API may change. I don&amp;#8217;t intend to change it, but I can&amp;#8217;t promise it won&amp;#8217;t. Apologies in advance if you use this helper method and have it break out from under you.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;Also, check out &lt;a href="https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/api/taskqueue/taskqueue_stub.py?spec=svn318&amp;amp;r=308#2507"&gt;the official code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Some example code:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;import unittest
from google.appengine.api import taskqueue
from google.appengine.ext import testbed


class TaskQueueTestCase(unittest.TestCase):

  def setUp(self):
    self.testbed = testbed.Testbed()
    self.testbed.activate()
    self.testbed.init_taskqueue_stub()
    self.task_queue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)

  def tearDown(self):
    self.testbed.deactivate()

  def testTaskAdded(self):
    taskqueue.add(url='/path/to/task')

    tasks = self.taskqueue_stub.get_filtered_tasks(url='/path/to/task')
    self.assertEqual(1, len(tasks))
    self.assertEqual('/path/to/task', tasks[0].url)

unittest.main()
&lt;/pre&gt;</description><link>http://geewax.org/post/45198021298</link><guid>http://geewax.org/post/45198021298</guid><pubDate>Tue, 12 Mar 2013 13:25:00 -0400</pubDate><category>appengine</category><category>taskqueue</category><category>unittesting</category><category>Testbed</category><category>googl</category></item><item><title>Daily Meeting</title><description>&lt;p&gt;&lt;span&gt;TLDR: I re-built one of my old side projects. Check it out at &lt;/span&gt;&lt;a href="http://www.dailymeetingapp.com/" title="Daily Meeting"&gt;dailymeetingapp.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/6eac90ec22afe82f9b543e6179d98375/tumblr_inline_mioum9u8IW1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;A long time ago, when I was working with a bunch of awesome guys at Invite Media, we started expanding our engineering team quite a bit. We had two engineering offices (New York City and Philadelphia) that were each doing more and more stuff, which was awesome, but we had a problem:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;our daily &amp;#8220;stand-up&amp;#8221; meeting in two cities was kind of a pain.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To clarify what I mean by this, when I say &amp;#8220;stand-up meeting&amp;#8221; I mean that we had one meeting, every day atnoon, where we went around the room and told the rest of the team &lt;em&gt;what we did since yesterday&lt;/em&gt;, and &lt;em&gt;what we&amp;#8217;re doing for the rest of the day&lt;/em&gt;. It was some kind of agile-ish thing that our team had deteriorated into. (There are lots of ways people do &amp;#8220;Scrum&amp;#8221; or &amp;#8220;Agile&amp;#8221; or &amp;#8220;Hip New Methodology&amp;#8221;, but let&amp;#8217;s not get into that. )&lt;/p&gt;
&lt;p&gt;This sounds like an easy meeting, right? 30 seconds per person. &lt;strong&gt;&lt;strong&gt;Boom. Done.&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What about when you have this with two groups of people in &lt;em&gt;different cities&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Early on we tried Skype. That was horrible. Laptop microphones really aren&amp;#8217;t made for group conference calls. The camera wasn&amp;#8217;t really all that great either.&lt;/p&gt;
&lt;p&gt;Next we had a coordless phone. We would put that on speaker-phone and pass it around through the group. The audio was a bit better, but it was still pretty bad.&lt;/p&gt;
&lt;p&gt;Then we upgraded to those fancy tripod-looking conference room phones, which were a lot better. Still not quite like being in-person, but they got the job done just fine. &lt;strong&gt;&lt;strong&gt;One problem solved.&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next issue we had to tackle was that most people would show up to this meeting, and not remember what they did yesterday! &lt;em&gt;&amp;#8220;I, um&amp;#8230;. worked on&amp;#8230; um&amp;#8230; what did I do&amp;#8230; hmm&amp;#8230; one second&amp;#8230;. oh yea! I built this awesome thing that does &amp;#8230;. &amp;#8220;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For a 30-second-per-person meeting, that is a lot of wasted time! What we needed was a reminder for everyone to actually think beforehand about what they did, so they could show up prepared for this meeting.&lt;/p&gt;
&lt;p&gt;We can&amp;#8217;t force everyone to set an alarm, but even if we did, how would we know if they actually thought out what they were working on? What if we had a little app that sent a reminder e-mail at 11:30 to everyone, and they could reply with what they did for everyone to see?&lt;/p&gt;
&lt;p&gt;Sounds like a pain in the ass, right? &lt;strong&gt;It was. But it did have some benefits.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;em&gt;&lt;em&gt;&lt;span&gt;&lt;img alt="image" src="http://media.tumblr.com/298952686e34a746a43e92a1b94d0935/tumblr_inline_miounzdutz1qz4rgp.png"/&gt;&lt;/span&gt;&lt;/em&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;It didn&amp;#8217;t get in the way as much as you&amp;#8217;d think. Reply to the e-mail and that&amp;#8217;s it. You&amp;#8217;re &lt;strong&gt;done&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It was easy for everyone to see which people &lt;span&gt;didn&amp;#8217;t&lt;/span&gt; post an update. Little red dot next to their name.&lt;em&gt;Busted.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;People who missed our stand-up meeting (travel, doctor&amp;#8217;s appointment, whatever) could come in later and see who did what. &lt;em&gt;Sweet.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;People who checked beforehand could show up prepared with a question or two based on what they read.&lt;/li&gt;
&lt;li&gt;Everyone got a digest e-mail at noon with everyone&amp;#8217;s notes. Super easy to notice the guy who says every day that he&amp;#8217;s going to finish Feature X. &lt;em&gt;What&amp;#8217;s going on there&amp;#8230;?&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Eventually, the app morphed into something that was more about a digital (and shared) work-log than an &amp;#8220;online stand-up meeting&amp;#8221;, which was pretty cool for me.&lt;/p&gt;
&lt;p&gt;Recently, I rebuilt quite a bit of the app and started testing it out with some people &amp;#8212; who seem to really like it. It&amp;#8217;s still not completely done (as you can see from some lorem-ipsum on the landing page&amp;#8230;.), but I would love to get some constructive feedback (and feature requests).&lt;/p&gt;
&lt;p&gt;Check it out at &lt;a href="http://www.dailymeetingapp.com/"&gt;&lt;a href="http://www.dailymeetingapp.com/"&gt;http://www.dailymeetingapp.com/&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43824620936</link><guid>http://geewax.org/post/43824620936</guid><pubDate>Sat, 23 Feb 2013 14:41:00 -0500</pubDate><category>coding</category><category>dailymeeting</category><category>agile</category><category>standup</category><category>scrum</category></item><item><title>Login required should be the default</title><description>&lt;p&gt;&lt;span&gt;If you&amp;#8217;re building a web-app in Python that requires people to sign in, you are probably pretty familiar with the concept of a &lt;/span&gt;&lt;code&gt;@login_required&lt;/code&gt;&lt;span&gt; decorator. For those that might not be, it&amp;#8217;s pretty straight forward: the decorator wraps a handler method with a check for whether the current request is coming from someone who has been through your sign in process.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;!-- more --&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;When I first saw this however many years ago, I was pretty new to Python decorators and thought it was pretty awesome. I still think the whole concept is pretty awesome. This seems to fit the mold of a &amp;#8220;decorator&amp;#8221; pretty perfectly&amp;#8230; almost as if decorators were built with this in mind&amp;#8230;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But what if you forget your &lt;code&gt;@login_required&lt;/code&gt; decorator?&lt;/strong&gt;&lt;span&gt; It&amp;#8217;s so easy to do. When you&amp;#8217;re testing that &amp;#8220;Edit your account&amp;#8221; page, you&amp;#8217;re authenticated, you assume everything should go to plan. You could (and should) add a functional test to check that an unauthenticated request is redirected, but this is just a &lt;/span&gt;&lt;em&gt;quick little side project&lt;/em&gt;&lt;span&gt;&amp;#8230;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So why don&amp;#8217;t we just make login_required the default?&lt;/strong&gt;&lt;span&gt; I think that it should be, so here&amp;#8217;s some code to save somebody else some time.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It works by wrapping all local methods with your &lt;/span&gt;&lt;code&gt;login_required&lt;/code&gt;&lt;span&gt; method during object creation (aka,&lt;/span&gt;&lt;code&gt;__new__&lt;/code&gt;&lt;span&gt;). If you want a method to be public, you decorate it with the &lt;/span&gt;&lt;code&gt;login_not_required&lt;/code&gt;&lt;span&gt; method &amp;#8212; which sets a flag on the method saying &amp;#8230; that login is not required.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Here&amp;#8217;s the BaseHandler (and Meta class) which does the wrapping:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;import types

import webapp2

from auth import login_required


class BaseHandlerMeta(type):
  """Meta class for all request handlers.

  This automatically wraps all handler methods with the login_required
  decorator. If something should be exposed publicly, it should be wrapped
  with the login_not_required decorator.
  """

  def __new__(cls, name, bases, local):
    if name != 'BaseHandler':
      for func_name, func in local.iteritems():
        if isinstance(func, types.FunctionType):
          local[func_name] = login_required(func)

    return type.__new__(cls, name, bases, local)

class BaseHandler(webapp2.RequestHandler):
  """Base class for all RequestHandlers."""

  __metaclass__ = BaseHandlerMeta

  def user_is_logged_in(self):
    # Do some magic here to check if someone is logged in
    return False&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;Here are the login_required and login_not_required decorators:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;def login_not_required(handler_method):
  """Allows a user to *not* be logged in.

  The login_required attribute is inspected by BaseHandlerMeta and is used
  as the flag for whether to wrap a method with login_required or not.
  """
  handler_method.login_required = False
  return handler_method

def login_required(handler_method):
  """Requires that a user be logged in."""

  required = getattr(handler_method, 'login_required', True)
  already_wrapped = getattr(handler_method, 'wrapped', False)

  # If the method doesn't require a login, or has already been wrapped,
  # just return the original.
  if not required or already_wrapped:
    return handler_method

  def check_login(self, *args, **kwargs):
    if not self.user_is_logged_in():
      uri = self.uri_for('login', redirect=self.request.path)
      self.redirect(uri, abort=True)
    else:
      return handler_method(self, *args, **kwargs)

  # Let others know that this method is already wrapped to avoid wrapping
  # it more than once...
  check_login.wrapped = True

  return check_login&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;This would make your request handlers look something like this:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;import base
from auth import login_not_required


class MyHandler(base.BaseHandler):
  @login_not_required
  def my_public_method(self):
    self.response.write('Hello world!')

  @login_not_required
  def my_public_method_with_a_problem(self):
    # Calling this should force a redirect to the login page!
    self.my_other_handler_that_is_protected()

  def my_other_handler_that_is_protected(self):
    self.response.write('Hello privately!')

  def protected_by_default(self):
    self.response.write('Once you log in, you can view this!')&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Notice&lt;/strong&gt;&lt;span&gt; that if you are in a public method (&lt;/span&gt;&lt;code&gt;@login_not_required&lt;/code&gt;&lt;span&gt;) and you call a method that does *not* have that decorator, you&amp;#8217;ll get redirected to a login page. If you want something to be public, it and all of the functions it calls (inside the handler) should be explicitly defined as public.&lt;/span&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43824434285</link><guid>http://geewax.org/post/43824434285</guid><pubDate>Sat, 23 Feb 2013 14:38:00 -0500</pubDate><category>coding</category><category>python</category><category>security</category><category>authentication</category><category>webapp</category></item><item><title>Friendly URL routing in App Engine using webapp2</title><description>&lt;p&gt;&lt;span&gt;I used to do crazy things like hard-code URLs in my templates:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&amp;lt;a href="/accounts/create/"&amp;gt;Create your account&amp;lt;/a&amp;gt;

or

&amp;lt;a href="/accounts/view/?id={{ the_id }}"&amp;gt;View account {{ the_id }}&amp;lt;/a&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;Ever since &lt;/span&gt;&lt;a href="http://webapp-improved.appspot.com/"&gt;webapp2&lt;/a&gt;&lt;span&gt; came around, I&amp;#8217;ve been really into the &lt;/span&gt;&lt;a href="http://webapp-improved.appspot.com/api/webapp2_extras/routes.html"&gt;URL routing helpers&lt;/a&gt;&lt;span&gt;, which make it much easier to keep long lists of URLs organized. I started using a new project layout that makes routing really simple &amp;#8212; maybe even fun.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;!-- more --&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Before I get to the interesting part I need to digress slightly. A while back, I posted &lt;/span&gt;&lt;a href="http://stackoverflow.com/questions/3025921/is-there-a-performance-gain-from-defining-routes-in-app-yaml-versus-one-large-ma" target="_blank"&gt;a question on Stack Overflow&lt;/a&gt;&lt;span&gt; asking whether it was better to break your app apart into separate routes in &lt;/span&gt;&lt;code&gt;app.yaml&lt;/code&gt;&lt;span&gt; or inside a&lt;/span&gt;&lt;code&gt;WSGIApplication&lt;/code&gt;&lt;span&gt;. Put simply: should you create one &lt;/span&gt;&lt;code&gt;WSGIApplication&lt;/code&gt;&lt;span&gt; object and route everything there? Or many separate ones, each with their own routing in &lt;/span&gt;&lt;code&gt;app.yaml&lt;/code&gt;&lt;span&gt;?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The short answer was:&lt;/strong&gt;&lt;span&gt; It doesn&amp;#8217;t really matter.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The longer answer was:&lt;/strong&gt;&lt;span&gt; if you&amp;#8217;re particularly sensitive about start-up time or memory, you might break things apart.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I decided to use one big app. &lt;/strong&gt;&lt;span&gt;Having a single app makes unit testing with &lt;/span&gt;&lt;a href="https://developers.google.com/appengine/docs/python/tools/localunittesting"&gt;ext.testbed&lt;/a&gt;&lt;span&gt; a bit easier.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In addition to making testing easier, I&amp;#8217;ve been using the Python 2.7 runtime which lends itself nicely to a single &lt;/span&gt;&lt;code&gt;WSGIApplication&lt;/code&gt;&lt;span&gt;: I put my code in &lt;/span&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;span&gt; and then route &lt;/span&gt;&lt;code&gt;/.*&lt;/code&gt;&lt;span&gt; to &lt;/span&gt;&lt;code&gt;main.app&lt;/code&gt;&lt;span&gt; and don&amp;#8217;t think about it anymore. But how are you supposed to keep track of all the URLs, Handlers, methods, and routes in your app as it grows larger and larger?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;webapp2 to the rescue.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span&gt;Take a look at &lt;/span&gt;&lt;a href="https://gist.github.com/jgeewax/2998463#file-routes-py" target="_blank"&gt;&lt;code&gt;routes.py&lt;/code&gt;&lt;/a&gt;&lt;span&gt;&lt;a href="https://gist.github.com/jgeewax/2998463#file-routes-py" target="_blank"&gt; in this gist&lt;/a&gt;:&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;from webapp2_extras.routes import RedirectRoute

from handlers.account import AccountHandler


__all__ = ['application_routes']

application_routes = []

_route_info = [
  ('account.list',   'GET', '/accounts/',                 AccountHandler, 'list'),
  ('account.create', None,  '/accounts/create/',          AccountHandler, 'create'),
  ('account.view',   'GET', '/accounts/&amp;lt;id:\d+&amp;gt;/',        AccountHandler, 'view'),
  ('account.delete', None,  '/accounts/&amp;lt;id:\d+&amp;gt;/delete/', AccountHandler, 'delete'),
  ('account.update', None,  '/accounts/&amp;lt;id:\d+&amp;gt;/update/', AccountHandler, 'update'),
]

for name, methods, pattern, handler_cls, handler_method in _route_info:
  # Allow a single string, but this has to be changed to a list.
  # None here means any method
  if isinstance(methods, basestring):
    methods = [methods]

  # Create the route
  route = RedirectRoute(name=name, template=pattern, methods=methods,
                        handler=handler_cls, handler_method=handler_method)

  # Add the route to the public list
  application_routes.append(route)&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;span&gt;There are a few things to notice here:&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;You could type out all the boiler-plate every time. I don&amp;#8217;t think routes have enough distinguishing factors to merit that. I removed the boiler plate and put together a list of tuples.&lt;/li&gt;
&lt;li&gt;Each tuple defines a route: (name, methods, URL pattern, HandlerClass, handler_method).&lt;/li&gt;
&lt;li&gt;Routes are named as thing.action (thing is &lt;strong&gt;singular&lt;/strong&gt; &amp;#8212; not &lt;em&gt;things&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;The method can be &lt;code&gt;'GET'&lt;/code&gt;, &lt;code&gt;'POST'&lt;/code&gt;, &lt;code&gt;None&lt;/code&gt;, or any other method (or list of methods). &lt;code&gt;None&lt;/code&gt; simply means &amp;#8220;I don&amp;#8217;t care&amp;#8221;.&lt;/li&gt;
&lt;li&gt;URL patterns allow fancy matching (&lt;code&gt;&amp;lt;id:\d+&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Rather that having many handlers (&lt;code&gt;CreateUserHandler&lt;/code&gt;, &lt;code&gt;DeleteUserHandler&lt;/code&gt;), I use one handler per &amp;#8220;thing&amp;#8221; and have the methods correspond to the actions (&lt;code&gt;UserHandler.create&lt;/code&gt;, &lt;code&gt;UserHandler.delete&lt;/code&gt;). If necessary, I can use &lt;code&gt;self.request.method&lt;/code&gt; to distinguish between intent (ie, &amp;#8220;show me the account creation form&amp;#8221; versus &amp;#8220;create my account and rediect me somewhere&amp;#8221;).&lt;/li&gt;
&lt;li&gt;The handler method name (AccountHandler.&lt;strong&gt;list&lt;/strong&gt;) and the &amp;#8220;action&amp;#8221; part of the route name (&amp;#8216;account.&lt;strong&gt;list&lt;/strong&gt;&amp;#8217;) are identical. This makes linking easy &amp;#8212; you know the route&amp;#8217;s name because it lines up with your code. &lt;/li&gt;
&lt;li&gt;I break from &lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP8&lt;/a&gt; about lining data up vertically. This is data you&amp;#8217;d put in a table. I don&amp;#8217;t like jagged tables.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;span&gt;Now to tie this all together, I just put some configuration for webapp2 into &lt;/span&gt;&lt;code&gt;config.py&lt;/code&gt;&lt;span&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;__all__ = ['webapp2_config']

webapp2_config = {
  'webapp2_extras.sessions': {
    'secret_key': 'Put some magical secret here.', 
  },
  'webapp2_extras.jinja2': {
    'environment_args': {
      'autoescape': True,
    },
  },
}&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;and hook it all up in &lt;/span&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;span&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;import webapp2

from config import webapp2_config
from routes import application_routes


app = webapp2.WSGIApplication(routes=application_routes, config=webapp2_config)&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;After that, your handlers might look like this:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;import webapp2
from webapp2_extras import auth
from webapp2_extras import jinja2
from webapp2_extras import sessions


class BaseHandler(webapp2.RequestHandler):
  @webapp2.cached_property
  def jinja2(self):
    return jinja2.get_jinja2(app=self.app)

  @webapp2.cached_property
  def auth_config(self):
    return {'login_url': self.uri_for('login'),
            'logout_url': self.uri_for('logout')}

  @webapp2.cached_property
  def auth(self):
    return auth.get_auth()

  @webapp2.cached_property
  def session_store(self):
    return sessions.get_store(request=self.request)

  def dispatch(self):
    """Override dispatch to persist session data."""
    try:
      super(BaseHandler, self).dispatch()
    finally:
      self.session_store.save_sessions(self.response)

  def render_template(self, template, context=None):
    context = context or {}

    extra_context = {
      'request': self.request,
      'uri_for': self.uri_for,
    }
    
    # Only override extra context stuff if it's not set by the template:
    for key, value in extra_context.items():
      if key not in context:
        context[key] = value

    rendered = self.jinja2.render_template(template, **context)
    self.response.write(rendered)&lt;/pre&gt;
&lt;pre&gt;from handlers import base


class AccountHandler(base.BaseHandler):
  def create(self):
    if self.request.method == 'POST':
      # Create the account
      pass
    
      # Redirect them to the dashboard page
      return self.redirect(self.uri_for('account.view'))
    
    else:
      return self.render_template('account_create.html')&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;And your templates can now create links that look like this:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&amp;lt;a href="{{ uri_for('account.create', my_param='something') }}"&amp;gt;Create your account&amp;lt;/a&amp;gt;

or

&amp;lt;a href="{{ uri_for('account.view', id=the_id) }}"&amp;gt;View account {{ the_id }}&amp;lt;/a&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Extra bonus&lt;/strong&gt;&lt;span&gt;: If you delete a URL and the template tries to look it up, you&amp;#8217;ll get an exception &amp;#8212; and so will your unit tests. I guess this could be a scary thing if you don&amp;#8217;t have tests, but hopefully it is helpful.&lt;/span&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43824274514</link><guid>http://geewax.org/post/43824274514</guid><pubDate>Sat, 23 Feb 2013 14:36:00 -0500</pubDate><category>coding</category><category>python</category><category>appengine</category><category>webapp2</category><category>routing</category></item><item><title>GAE Testbed moving into the Python SDK!</title><description>&lt;p&gt;Since we were &lt;a href="http://techcrunch.com/2010/06/03/google-confirms-invite-media/"&gt;acquired by Google&lt;/a&gt;, I figured that it would be a fitting 20% project to work with some App Engine engineers to move &lt;a href="https://github.com/jgeewax/gaetestbed"&gt;GAE Testbed&lt;/a&gt; into the &lt;a href="http://code.google.com/appengine/docs/python/overview.html"&gt;App Engine Python SDK&lt;/a&gt;. The benefits are pretty obvious:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;No third-party package to install (ie, no more &lt;span&gt;easy_install gaetestbed&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&amp;#8220;Official&amp;#8221; documentation for how to write your tests&lt;/li&gt;
&lt;li&gt;More people working on making it easy for users to test their code&lt;/li&gt;
&lt;li&gt;Many maintainers, meaning fewer regressions (ie, no more &amp;#8220;whoops, the API changed a bit&amp;#8230; GAE Testbed doesn&amp;#8217;t work right now&amp;#8230;&amp;#8221;)&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;And I&amp;#8217;m incredibly happy to say that that the 1.4.3 release includes the first steps toward no longer needing GAE Testbed at all: &lt;a href="http://code.google.com/appengine/docs/python/tools/localunittesting.html"&gt;google.appengine.ext.testbed&lt;/a&gt;! The testbed module sets up your environment so that you&amp;#8217;re able to verify that API calls you expected to be made are actually made.&lt;/p&gt;
&lt;p&gt;For example, you can put something in memcache and then get it back to out to verify your application logic. Of course, this isn&amp;#8217;t using an actual memcache instance, but looks and acts mostly the same.&lt;/p&gt;
&lt;p&gt;I had very little involvement with the code in this release (just a reviewer), but there&amp;#8217;s plenty more to come in the future. Many thanks to Robert Schuppenies and Guido van Rossum for helping get this huge improvement out the door.&lt;/p&gt;
&lt;p&gt;P.S. Although there isn&amp;#8217;t yet a way to do things like self.assertEmailSent(to=&amp;#8221;&lt;a href="mailto:email@example.com"&gt;email@example.com&lt;/a&gt;&amp;#8221;), I hope that feature parity between google.appengine.ext.testbed and GAE Testbed is only a short while away.&lt;/p&gt;</description><link>http://geewax.org/post/43823824448</link><guid>http://geewax.org/post/43823824448</guid><pubDate>Sat, 23 Feb 2013 14:31:04 -0500</pubDate><category>python</category><category>testbed</category><category>unittesting</category><category>appengine</category><category>coding</category></item><item><title>Encoding subtitles into your movie...</title><description>&lt;p&gt;&lt;span&gt;So, you have an AVI file and a SRT file, and you want to put them together so that you don&amp;#8217;t have to carry around the two files&amp;#8230; (and you&amp;#8217;re on Ubuntu&amp;#8230;)&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;$ sudo apt-get install mencoder
$ mencoder -oac copy -ovc lavc -sub TheSubtitlesFile.srt \&lt;br/&gt;  -subfont-text-scale 3 -o TheMovieWithSubtitles.avi \&lt;br/&gt;  TheOriginalMovie.avi&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;(Of course you could add change &amp;#8220;-ovc lavc&amp;#8221; to &amp;#8220;-ovc divx&amp;#8221;, all up to you&amp;#8230;)&lt;/span&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43823891251</link><guid>http://geewax.org/post/43823891251</guid><pubDate>Sat, 23 Feb 2013 14:31:00 -0500</pubDate><category>ubuntu</category><category>mencoder</category><category>subtitles</category><category>divx</category></item><item><title>My git workflow -- in code</title><description>&lt;p&gt;&lt;span&gt;There have been a lot of blog posts (one of mine included&amp;#8230;) that talk about using feature branches to have an &amp;#8220;agile&amp;#8221; workflow while you code. This is all great to talk about but it seemed to me that a lot of people weren&amp;#8217;t doing it. Not because they were against the idea but because it was too tricky to remember or too complicated to do or too annoying to do for that one little feature.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Then there are tools like &lt;/span&gt;&lt;a href="http://github.com/nvie/gitflow"&gt;git flow&lt;/a&gt;&lt;span&gt; that do the trick but they seemed like kind of a lot of typing to me, so I threw something together that was three aliases to help make my workflow involve less typing, less remembering, and less confusion.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;span&gt;: If you ask me, &amp;#8220;what git workflow tool should I use?&amp;#8221; my answer will be git flow. git flow is FAR better documented, supported, and tested than the tool that I threw together today&amp;#8230;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Now&amp;#8230; it is with great pleasure that I introduce &lt;/span&gt;&lt;a href="http://github.com/jgeewax/git-feature"&gt;git-feature&lt;/a&gt;&lt;span&gt;. It&amp;#8217;s simple to install (all three commands are git aliases &amp;#8212; you know, those things in .git/config?), simple to remember (if you forget arguments, it will prompt you for them), &lt;/span&gt;&lt;em&gt;mostly&lt;/em&gt;&lt;span&gt; safe (it prompts you before doing anything that changes your repository), and has very little magic (those git aliases are just shell commands, think of this as a few friendly shortcuts&amp;#8230;).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So, getting right down to the dirt&amp;#8230; here&amp;#8217;s how I currently use it:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;$ git branch
* master
$ git feature my-new-feature
this will create a feature branch my-new-feature to be merged into master (Y/n): Y
$ git branch
* features/my-new-feature
  master
$ # Do some work here, commit it...
$ git finish
this will integrate my-new-feature into master (Y/n): Y
$ git branch
* master&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;If you&amp;#8217;re actually wondering, &amp;#8220;Hmm&amp;#8230; maybe I could use this!&amp;#8221;, you&amp;#8217;ll probably have lots of questions like&amp;#8230; &lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;&lt;li&gt;what if I forget arguments? or&amp;#8230; &lt;/li&gt;
&lt;li&gt;what if I want my feature to based off a different parent? or&amp;#8230; &lt;/li&gt;
&lt;li&gt;what if I want to integrate my feature into two different parents? &lt;/li&gt;
&lt;/ul&gt;
Most of there are answered on the project&amp;#8217;s GitHub page: &lt;a href="http://github.com/jgeewax/git-feature"&gt;&lt;a href="http://github.com/jgeewax/git-feature"&gt;http://github.com/jgeewax/git-feature&lt;/a&gt;&lt;/a&gt; but if you have one that isn&amp;#8217;t answered, I&amp;#8217;d guess somebody else had that question, so let me know and I&amp;#8217;ll try to come up with an answer for everyone.&lt;/div&gt;
&lt;/div&gt;</description><link>http://geewax.org/post/43823228152</link><guid>http://geewax.org/post/43823228152</guid><pubDate>Sat, 23 Feb 2013 14:23:00 -0500</pubDate><category>coding</category><category>git</category><category>workflow</category></item><item><title>Deploying code on App Engine? Be careful with your indexes...</title><description>&lt;p&gt;Have you ever deployed a new version of your application on App Engine and end up with this rude error saying something like, &amp;#8220;You need an index to run that query&amp;#8221;? So you scratch your head for a minute, check index.yaml, and sure enough that index is there just like you thought&amp;#8230; After all, most (if not all) of your index.yaml is auto generated by the SDK&amp;#8230;&lt;/p&gt;
&lt;p&gt;It looks like the SDK is so good about keeping the contents of index.yaml off your mind that you forget about the time it takes to build those indexes!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m sure it&amp;#8217;s written down somewhere but those of us that are so eager to get code out the door are clearly not the ones reading the fine print in the documentation&amp;#8230; The short version of all of this is&amp;#8230;&lt;/p&gt;
&lt;p&gt;When you have modifications to index.yaml (adding a new index for example), it takes time for App Engine to build those indexes. However, the code you deployed is running right away and that code needs those indexes &lt;strong&gt;right away&lt;/strong&gt;. So you end up with a nasty mean error all because you were a bit too hasty with kicking out your code (and the SDK is too busy pushing your files up to Google&amp;#8217;s servers to warn you: &amp;#8220;Hey wait a minute! This index is going to take a while to build&amp;#8230;&amp;#8221;)&lt;/p&gt;
&lt;p&gt;Anyway, I figured I&amp;#8217;d share the simple way I avoid getting bitten by this little annoyance&amp;#8230;&lt;/p&gt;
&lt;p&gt;First, I use git. If you&amp;#8217;re not using any sort of source control, you should probably start doing that now. Even if you don&amp;#8217;t want to share your source with anyone, having a local git repository is great&amp;#8230; &amp;#8220;Whoops! Let me revert back to where things were 10 minutes ago&amp;#8230;&amp;#8221;&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re using git, this problem is fixed by breaking apart your changes into two pieces: the index changes and the code that needs the index changes. If you&amp;#8217;re working on Feature X and there are changes to index.yaml (git diff index.yaml), I commit those changes first (git add index.yaml &amp;amp;&amp;amp; git commit -m &amp;#8220;Updating indexes&amp;#8221;) and then stash the other stuff on a new branch (git checkout -b feature-x &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git commit -m &amp;#8220;Feature X&amp;#8221;). Then switch back to your previous branch (git checkout master) and deploy JUST those index changes (make deploy*) and then wait!&lt;/p&gt;
&lt;p&gt;Go into the Data store Indexes page on the App Engine admin console and keep an eye on that page. It will show your new indexes building and queued and all that lovely stuff (which could take a while). &lt;/p&gt;
&lt;p&gt;Once you see that your new index is &amp;#8220;serving&amp;#8221;, just merge in your other branch (it should be a simple fast-forward) (git merge feature-x) and deploy again (make deploy). And you&amp;#8217;re all set!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m sure there are other ways of doing this so don&amp;#8217;t take this as the only way to handle the problem, but this way seems to work pretty well for me.&lt;/p&gt;
&lt;p&gt;Happy deploying (and indexing).&lt;/p&gt;
&lt;p&gt;* Deploying with &amp;#8220;make deploy&amp;#8221; is thanks to &lt;a href="http://github.com/jgeewax/appmake"&gt;AppMake&lt;/a&gt;. It makes deploying really simple&amp;#8230;&lt;/p&gt;</description><link>http://geewax.org/post/43823177795</link><guid>http://geewax.org/post/43823177795</guid><pubDate>Sat, 23 Feb 2013 14:22:00 -0500</pubDate><category>coding</category><category>python</category><category>appengine</category><category>indexing</category></item><item><title>Introducing Helipad</title><description>&lt;p&gt;First, let me apologize in advance: I really hate reinventing the wheel.&lt;/p&gt;
&lt;p&gt;OK, now that that&amp;#8217;s out of the way&amp;#8230;&lt;a href="http://github.com/jgeewax/helipad"&gt;Helipad&lt;/a&gt;&lt;span&gt; is a &lt;/span&gt;&lt;strong&gt;very light-weight&lt;/strong&gt;&lt;span&gt; framework built on top of &lt;/span&gt;&lt;a href="http://code.google.com/appengine/docs/python/tools/webapp/" target="_blank"&gt;webapp&lt;/a&gt;&lt;span&gt; (the framework built-in to &lt;/span&gt;&lt;a href="http://code.google.com/appengine/" target="_blank"&gt;Google App Engine&lt;/a&gt;&lt;span&gt;) that adds some of the stuff I felt was stalking me across all my projects:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Less boilerplate code for handlers (in particular for routes pointing to a file with only one handler)&lt;/li&gt;
&lt;li&gt;Simplified URL routing (prefixes, un-ordered URLs)&lt;/li&gt;
&lt;li&gt;Simple cookies&lt;/li&gt;
&lt;li&gt;Sessions (backed by App Engine&amp;#8217;s &lt;a href="http://code.google.com/appengine/docs/python/memcache/" target="_blank"&gt;Memcache&lt;/a&gt; service)&lt;/li&gt;
&lt;li&gt;Simple static file serving&lt;/li&gt;
&lt;li&gt;Easy templating with &lt;a href="http://jinja.pocoo.org/2/documentation/" target="_blank"&gt;Jinja2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If you just want to get down and dirty with the code, check it out on GitHub: &lt;a href="http://github.com/jgeewax/helipad"&gt;&lt;a href="http://github.com/jgeewax/helipad"&gt;http://github.com/jgeewax/helipad&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;strong&gt;&lt;!-- more --&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start with a simple example. Keeping with convention, we&amp;#8217;ll call this HelloHelipad.&lt;/p&gt;
&lt;p&gt;Start by creating a new application. To get started quickly, check out &lt;a href="http://github.com/jgeewax/appmake" target="_blank"&gt;AppMake&lt;/a&gt; and type the following:&lt;/p&gt;
&lt;pre&gt;$ curl -OL --silent &lt;a href="http://github.com/jgeewax/appmake/raw/master/Makefile"&gt;http://github.com/jgeewax/appmake/raw/master/Makefile&lt;/a&gt;
$ make helipad-project name=hellohelipad&lt;/pre&gt;
&lt;p&gt;After that, create your first handler in hellohelipad/handlers/hellohelipad.py (and don&amp;#8217;t forget to hook it up in app.yaml) like this:&lt;/p&gt;
&lt;p&gt;app.yaml:&lt;/p&gt;
&lt;pre&gt;application: hellohelipad
version: 1
runtime: python
api_version: 1

handlers:
- url: /
  script: hireforge/handlers/hellohelipad.py&lt;/pre&gt;
&lt;p&gt;handler.py:&lt;/p&gt;
&lt;pre&gt;import helipad

class HelloHelipadHandler(helipad.Handler):
  def get(self):
    self.response.out.write('Hello, Helipad!')

main, application = helipad.app(HelloHelipadHandler)

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;Cool &amp;#8212; that was pretty easy&amp;#8230; &lt;/p&gt;
&lt;p&gt;For comparison, here&amp;#8217;s the way webapp has you do a HelloWorld application:&lt;/p&gt;
&lt;pre&gt;from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Hello, webapp World!')

application = webapp.WSGIApplication([('/', MainPage)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;Take note of a few things that you didn&amp;#8217;t have to do:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Re-define the URL mapping in hellohelipad.py&lt;/li&gt;
&lt;li&gt;Manually create a WSGI application based on your handler&lt;/li&gt;
&lt;li&gt;Define a main method that serves your application&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Now that you have the basics, let&amp;#8217;s take a look at some of the other fun stuff :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simpler URL Routing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you have just a single route in app.yaml pointing at your script, you don&amp;#8217;t need to redefine the route in the file, but what if you have a wildcard pointing at your script? For example, say your app.yaml file looks like this:&lt;/p&gt;
&lt;pre&gt;application: hellohelipad
version: 1
runtime: python
api_version: 1

handlers:
- url: /about/.*
  script: hellohelipad/handlers/about.py&lt;/pre&gt;
&lt;p&gt;If you were using webapp, this would look like&lt;/p&gt;
&lt;pre&gt;from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class AboutMeHandler(webapp.RequestHandler):
  def get(self):
    self.response.out.write('About Me!')

class AboutCompanyHandler(webapp.RequestHandler):
  def get(self):
    self.response.out.write('About Company!')

application = webapp.WSGIApplication([('/about/me/', AboutMeHandler),
                                      ('/about/company/', AboutCompanyHander)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;With Helipad, you can do your routing the same way (with a list of tuples) like this:&lt;/p&gt;
&lt;pre&gt;import helipad

class AboutMeHandler(helipad.Handler):
  def get(self):
    self.response.out.write('About Me!')

class AboutCompanyHandler(helipad.Handler):
  def get(self):
    self.response.out.write('About Company!')

main, application = helipad.app([
  ('/about/me/', AboutMeHandler),
  ('/about/company/', AboutCompanyHandler),
])

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;or if the order doesn&amp;#8217;t matter to you (which in this case it doesn&amp;#8217;t) you can use a simple Python dictionary to map URLs to handlers like this:&lt;/p&gt;
&lt;pre&gt;import helipad

class AboutMeHandler(helipad.Handler):
  def get(self):
    self.response.out.write('About Me!')

class AboutCompanyHandler(helipad.Handler):
  def get(self):
    self.response.out.write('About Company!')

main, application = helipad.app({
  '/about/me/': AboutMeHandler,
  '/about/company/': AboutCompanyHandler,
})

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;Finally, if you have a common prefix across all your URLs (in this example, all of our routes are prefixed with &amp;#8220;/about/&amp;#8221;), you can define that prefix once and it will be automatically prepended to your URLs. This might make the previous handler look like this:&lt;/p&gt;
&lt;pre&gt;import helipad

class AboutMeHandler(helipad.Handler):
  def get(self):
    self.response.out.write('About Me!')

class AboutCompanyHandler(helipad.Handler):
  def get(self):
    self.response.out.write('About Company!')

main, application = helipad.app('/about/', {
  'me/': AboutMeHandler,
  'company/': AboutCompanyHandler,
})

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Finding and opening files&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One of the things that I realized I never have in my projects is a consistent way of finding and opening files. When I was working on Django applications I would always create a directory for my templates and add that relative to my project directory using os.path and __file__ which has started to feel like boilerplate code. To deal with this, I threw together a simple way of defining a root module and then two helper methods (find_file and open_file) which will get the file you request relative to your root module. That is, if Helipad is located at /home/jj/helipad.py, and you set the root to the Helipad module, &amp;#8216;path/to/myfile.html&amp;#8217; will resolve to &amp;#8216;/home/jj/path/to/myfile.html&amp;#8217;.&lt;/p&gt;
&lt;p&gt;This is extremely useful when you don&amp;#8217;t care where your project is on the disk, you just care about files relative to your project. For example, say the About Me page needed to read from a file&amp;#8230; (we&amp;#8217;re dropping the About Company page for now)&lt;/p&gt;
&lt;pre&gt;import helipad

class AboutMeHandler(helipad.Handler):
  def get(self):
    about_me = helipad.open_file('templates/about_me.html')
    self.response.out.write(about_me.read())

# This sets the root to our project module
helipad.root('hellohelipad')

main, application = helipad.app(AboutMeHandler)

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;This will let you read static content that you&amp;#8217;ve uploaded to App Engine and need to display in one way or another, or if you need to render a template you now don&amp;#8217;t have to worry &amp;#8220;where is my template file?&amp;#8221;. This actually brings us to our next topic&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Serving static files (with fancy URLs)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The example above shows you how to use helipad.root(), helipad.find_file(), and helipad.open_file() to access files you&amp;#8217;ve included with your project on App Engine, but that seems still like boilerplate code that you may end up copying and pasting around a lot. Keeping with the theme of DRY, Helipad provides a few different ways of serving static files without so much typing.&lt;/p&gt;
&lt;p&gt;The three ways to do this are&amp;#8230;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Using helipad.Handler.static() inside a regular handler&lt;/li&gt;
&lt;li&gt;Using helipad.static() to create a StaticApplication for serving a single file&lt;/li&gt;
&lt;li&gt;Using helipad.static() to create a StaticApplication with a URL mapping for many static files&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;For the first, instead of using helipad.open_file() and self.response.out.write(), you can just use self.static() like this&amp;#8230;&lt;/p&gt;
&lt;pre&gt;import helipad

class AboutMeHandler(helipad.Handler):
  def get(self):
    self.static('templates/about_me.html')

helipad.root('hellohelipad')

main, application = helipad.app(AboutMeHandler)

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;If there really is nothing else your handler needs to do besides serve a single static file, you can use helipad.static() to generate the boilerplate handler for you like this:&lt;/p&gt;
&lt;pre&gt;import helipad

helipad.root('hellohelipad')

main, application = helipad.static('templates/about_me.html')

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;You can even string together the helipad.root() and helipad.static() calls like this:&lt;/p&gt;
&lt;pre&gt;import helipad

main, application = helipad.root('hellohelipad').static('templates/about_me.html')

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;If we were to bring back the About Company page, you could map a bunch of URLs to static files just like you&amp;#8217;d map a bunch of URLs to handlers. You can do this with a list of tuples or, if order doesn&amp;#8217;t matter, with a Python dictionary. Additionally, just like with helipad.app(), you can use a URL prefix to be prepended to all of your URLs. Here&amp;#8217;s an example showing all of that:&lt;/p&gt;
&lt;pre&gt;import helipad

main, application = helipad.root('hellohelipad').static('/about/', {
  'me/': 'templates/about_me.html',
  'company/': 'templates/about_company.html',
})

if __name__ == "__main__":
  main()&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Handling templates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I had to make a call on templating and what to include, but I personally really like Jinja2. The syntax is pretty similar to Django&amp;#8217;s template language except it&amp;#8217;s a bit less restrictive. Because of my preference for Jinja2, this template language comes baked in to Helipad. Just like helipad.Handler.static(), you can use helipad.Handler.template(). The one extra piece is that if you get tired of defining your template directory over and over, you can define a template_root which is just prepended to all of your template file paths (which is then based on your helipad.root()). Perhaps this is best explained with an example&amp;#8230; (see comments in-line)&lt;/p&gt;
&lt;pre&gt;import helipad

helipad.root('hellohelipad').template_root('templates/')

class AboutMeHandler(helipad.Handler):
  def get(self):
    # This will render the template hellohelipad/templates/template.html
    # Where hellohelipad is wherever the hellohelipad module is located.
    return self.template('template.html', {
      'my_template_variable': 'This is a template variable!',
    })

main, application = helipad.app(AboutMeHandler)

if __name__ == '__main__':
  main()&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Cookies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Handling cookies with Helipad is really naive. helipad.Handler has three methods related to cookies:&lt;a href="http://github.com/jgeewax/helipad/blob/master/helipad.py#L77" target="_blank"&gt;set_cookie()&lt;/a&gt;, &lt;a href="http://github.com/jgeewax/helipad/blob/master/helipad.py#L84" target="_blank"&gt;get_cookie()&lt;/a&gt;, and &lt;a href="http://github.com/jgeewax/helipad/blob/master/helipad.py#L87" target="_blank"&gt;clear_cookie()&lt;/a&gt;. These should be self explanatory and take care of all the garbage with headers and whatnot which I got tired of having to reinvent every time I made a project. There may be some subtle bugs in here, but so far everything has been fine for me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sessions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sessions in Helipad are equally simple. helipad.Handler has a property called &lt;a href="http://github.com/jgeewax/helipad/blob/master/helipad.py#L66" target="_blank"&gt;session&lt;/a&gt; which gives you back a Session object which has a few methods for you to use: get(), set(), and delete(). The way this works is the Session generates a random key (stored in a cookie) which then serves as the namespace for Memcache operations (get, set, and delete). Since Memcache is behind all of this, expiration is out of our hands, but hopefully you&amp;#8217;re not putting anything critical in your sessions anyway&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion and future plans&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So far, Helipad has just been a place where I end up putting stuff I notice needing in every project (such as cookies, sessions, etc). The goal has mainly been to make it simpler to do the common stuff (like serving a static file) but still make it easy to bypass all of that stuff if I need to (for example, you can do anything you want in a handler&amp;#8230;) and I think that&amp;#8217;s worked out pretty well. There must be a few bugs here and there (particularly in the cookie and session area&amp;#8230;) so any help fixing those would be awesome, but otherwise Helipad seems to be meeting my needs, and hopefully it meets yours and can help to speed up your webapp development.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re interested in helping out at all, you can find all the code on GitHub at &lt;a href="http://github.com/jgeewax/helipad"&gt;&lt;a href="http://github.com/jgeewax/helipad"&gt;http://github.com/jgeewax/helipad&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43823103790</link><guid>http://geewax.org/post/43823103790</guid><pubDate>Sat, 23 Feb 2013 14:21:00 -0500</pubDate><category>coding</category><category>python</category><category>appengine</category><category>framework</category><category>webapp</category></item><item><title>Introducing AppMake</title><description>&lt;p&gt;Managing lots of different App Engine applications gets pretty tricky, so I threw together a little Makefile to make it easy to run the debug server, start the development console, deploy the application, etc.&lt;/p&gt;
&lt;div&gt;This Makefile turns running the development server from:&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;$ python /usr/local/google_appengine/dev_appserver.py -a 0.0.0.0 -p 9091 --datastore_path=./datastore --disable_static_caching .&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;into&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;$ make serve&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;The full list of commands is:&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;$ make help
AppEngine make file. Options are:
 test       Runs the test suite
 coverage   Runs the test suite and prints a coverage report
 deploy     Deploys the current project to AppEngine
 rollback   Rolls back a unclosed update to the application
 serve      Runs the development web server
 console    Opens a development console to your remote application
            (Only works if you've enabled the /remote_api URL)&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;The code is open sourced on GitHub at &lt;a href="http://github.com/jgeewax/appmake"&gt;&lt;a href="http://github.com/jgeewax/appmake"&gt;http://github.com/jgeewax/appmake&lt;/a&gt;&lt;/a&gt;, and to get started, all you have to do is type&amp;#8230;&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;curl -OL --silent &lt;a href="http://github.com/jgeewax/appmake/raw/master/Makefile"&gt;http://github.com/jgeewax/appmake/raw/master/Makefile&lt;/a&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;There&amp;#8217;s more documentation in the README file here:&lt;/div&gt;
&lt;div&gt;&lt;a href="http://github.com/jgeewax/appmake/blob/master/README.markdown"&gt;&lt;a href="http://github.com/jgeewax/appmake/blob/master/README.markdown"&gt;http://github.com/jgeewax/appmake/blob/master/README.markdown&lt;/a&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;</description><link>http://geewax.org/post/43822741366</link><guid>http://geewax.org/post/43822741366</guid><pubDate>Sat, 23 Feb 2013 14:17:12 -0500</pubDate><category>python</category><category>coding</category><category>appengine</category><category>Make</category></item><item><title>Acquired by Google</title><description>&lt;p&gt;In the early days of &lt;a href="http://www.invitemedia.com/"&gt;Invite Media&lt;/a&gt; we always talked about being acquired but I didn’t really think it would ever happen. Amazingly, back in June we were acquired by Google. (You can read about it in &lt;a href="http://doubleclickadvertisers.blogspot.com/2010/06/investing-in-exchange-bidding.html"&gt;the official DoubleClick blog post&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;We’re all still getting ourselves situated at Google — our &lt;span class="caps"&gt;NYC&lt;/span&gt; engineers are happily settling into Google’s &lt;span class="caps"&gt;NYC &lt;/span&gt;office and Google is setting up a new office in Center City for the Philly engineers — but for the most part the work is the same. I’m still trying to find my way around, but everybody I’ve met so far has been really helpful.&lt;/p&gt;
&lt;p&gt;Looks like I officially work for Google. Let the excitement begin…&lt;/p&gt;</description><link>http://geewax.org/post/43822649986</link><guid>http://geewax.org/post/43822649986</guid><pubDate>Sat, 23 Feb 2013 14:16:00 -0500</pubDate><category>google</category><category>startups</category></item><item><title>Default description value for Jira issues</title><description>&lt;p&gt;We use Jira for a whole lot of things, but one of the major uses is for Bug reports. That said, sometimes people forget important information when filing a bug so I wanted to have the default description for Bug reports have some prompts for what information we’d need to reproduce the bugs (sort of like Google Code’s bug report interface).&lt;/p&gt;
&lt;p&gt;Unfortunately, there’s no nifty UI to edit the default value for the description field in Jira, but there’s a nice &lt;a href="http://confluence.atlassian.com/display/JIRAKB/Setting+a+default+value+in+the+Description+field"&gt;Knowledge Base article&lt;/a&gt; which describes how you can do it by editing the template file used to render the description field.&lt;/p&gt;
&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;That file is: &lt;span&gt;/path/to/atlassian-jira/WEB-INF/classes/templates/jira/issue/field/description-edit.vm&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It wasn’t entirely clear how to do different things based on the issue type, etc so I had to poke around a bit to figure out what’s different, the section I wrote ended up as:&lt;/p&gt;
&lt;pre&gt;#if ($description == '' &amp;amp;&amp;amp; $issue.getIssueType().getString('name') == 'Bug')
#set ($description = "Steps taken to produce this bug:\
\
\
Expected Results:\
\
\
Actual Results:\
\
\
Extra Information:\
\
")
#set ($description = $description.replace('\', ''))
#end&lt;/pre&gt;
&lt;p&gt;This makes the entire &lt;code&gt;description-edit.vm&lt;/code&gt; file look like this:&lt;/p&gt;
&lt;pre&gt;jira@jira1:~$ cat ~jira/atlassian-jira/WEB-INF/classes/templates/jira/issue/field/description-edit.vm
#controlHeader ($action $field.id $i18n.getText($field.nameKey) $fieldLayoutItem.required $displayParameters.get('noHeader'))

## setup some additional parameters
$!rendererParams.put("rows", "12")
$!rendererParams.put("wrap", "virtual")

## Add our default value
#if ($description == '' &amp;amp;&amp;amp; $issue.getIssueType().getString('name') == 'Bug')
#set ($description = "Steps taken to produce this bug:\
\
\
Expected Results:\
\
\
Actual Results:\
\
\
Extra Information:\
\
")
#set ($description = $description.replace('\', ''))
#end

## let the renderer display the edit component
$rendererDescriptor.getEditVM($!description, $!issue.key, $!fieldLayoutItem.rendererType, $!field.id, $!field.name, $rendererParams, false)

#controlFooter ($action $fieldLayoutItem.getFieldDescription() $displayParameters.get('noHeader'))&lt;/pre&gt;
&lt;p&gt;Hopefully this helps someone else who wants to provide defaults for system fields like Description. In the meantime, please go vote on the &lt;a href="http://jira.atlassian.com/browse/JRA-4812" title="JRA-4812"&gt;feature request&lt;/a&gt; so that this blog post won’t be needed anymore.&lt;/p&gt;</description><link>http://geewax.org/post/43822616782</link><guid>http://geewax.org/post/43822616782</guid><pubDate>Sat, 23 Feb 2013 14:15:35 -0500</pubDate><category>coding</category><category>jira</category><category>workflow</category></item><item><title>Forking django-chronograph</title><description>&lt;p&gt;Keeping track of scripts that run regularly and e-mail the output is pretty simple when only one person is managing the schedules, scripts, and server. When you throw many more people into the mix, keeping track of who wants to see the output of which jobs and when jobs should run, you end up with a nasty crontab, and lots of cooks in the kitchen.&lt;/p&gt;
&lt;p&gt;I went looking around for a simple way to throw a &lt;span class="caps"&gt;GUI&lt;/span&gt; ontop of a crontab, and stumbled across the &lt;a href="http://code.google.com/p/django-chronograph/"&gt;Chronograph Django application&lt;/a&gt;. It had most of the stuff that we needed (including some really advanced scheduling options thanks to the &lt;a href="http://labix.org/python-dateutil"&gt;dateutil library&lt;/a&gt;) so I tried spinning it up. What came out was a really nice user interface where we could see just about everything we wanted.&lt;/p&gt;
&lt;p&gt;There were a few tweaks I wanted to make for my own purposes, but one major thing that was missing was a list of e-mail subscribers. This was surprisingly simple to throw in, and works really well since Django does pretty much all of the work for me.&lt;/p&gt;
&lt;p&gt;Anyway, I’m hoping these changes can get pulled back into the main repository on Google Code, but if not, I’ve got a fork going on GitHub for anybody that’s interested:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/jgeewax/django-chronograph"&gt;&lt;a href="http://github.com/jgeewax/django-chronograph"&gt;http://github.com/jgeewax/django-chronograph&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can install this via easy install:&lt;/p&gt;
&lt;p&gt;$ easy_install &lt;a href="http://github.com/downloads/jgeewax/django-chronograph/django-chronograph-0.1.2.dev.tar.gz"&gt;&lt;a href="http://github.com/downloads/jgeewax/django-chronograph/django-chronograph-0.1..."&gt;http://github.com/downloads/jgeewax/django-chronograph/django-chronograph-0.1&amp;#8230;&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what the fork looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://media.tumblr.com/843e95a55dd8b2bbc4dac09ac65f9dbc/tumblr_inline_miotcrHt2t1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/32721a5651a13ac55ab6494a38680e4c/tumblr_inline_miotd18esW1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/a9c5626f5a5c00098fb5443ae351c52b/tumblr_inline_miotd7iTrL1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/56048931df502f6e83a9fa211462bd8f/tumblr_inline_miotdcvmT41qz4rgp.png"/&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43822445962</link><guid>http://geewax.org/post/43822445962</guid><pubDate>Sat, 23 Feb 2013 14:13:21 -0500</pubDate><category>coding</category><category>django</category><category>django-chronograph</category><category>monitoring</category><category>cron</category><category>python</category></item><item><title>Agile git Workflow</title><description>&lt;p&gt;When we started using git to manage our source code at work, we actually jumped in a little bit too fast. It seems like there is a lot of writing about how you can do lots of really neat things with git, but no real guide about one particular way of using git for your project. This post is going to describe how we use git day to day on a reasonably large “agile-style” project.&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The general overview of how this works is:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Branch off of master to work on the feature&lt;/li&gt;
&lt;li&gt;Work, work, work, commit, commit, commit&lt;/li&gt;
&lt;li&gt;Pull down any updates to master&lt;/li&gt;
&lt;li&gt;Rebase and squash (with discretion) the feature branch to master’s &lt;span class="caps"&gt;HEAD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Merge the feature branch back to master&lt;/li&gt;
&lt;li&gt;Push up to the shared repository&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Also in this post are details about using release-candidate and production branches and merging features across those branches.&lt;/p&gt;
&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;
&lt;h2&gt;Working on a feature&lt;/h2&gt;
&lt;p&gt;Let’s imagine that you need to work on Issue #12. The first thing you’d do is create a feature branch from master for the issue. This keeps your work isolated, so that you can switch what you’re working on very quickly should the need arise.&lt;/p&gt;
&lt;pre&gt;(master)jj@im-jj:~/demo$ git checkout -b issue-12
Switched to a new branch 'issue-12'
(issue-12)jj@im-jj:~/demo$ &lt;/pre&gt;
&lt;p&gt;Now that you’re on the feature branch, you might do all sorts of work towards completing this issue:&lt;/p&gt;
&lt;pre&gt;(issue-12)jj@im-jj:~/demo$ echo "print 'hi'" &amp;gt;&amp;gt; feature.py
(issue-12)jj@im-jj:~/demo$ git add feature.py
(issue-12)jj@im-jj:~/demo$ git commit -m "Added feature"
[issue-12 765a6c0] Added feature
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 feature.py
(issue-12)jj@im-jj:~/demo$ git rm README.txt
rm 'README.txt'
(issue-12)jj@im-jj:~/demo$ git commit -m "Removed the README file"
[issue-12 e7829cb] Removed the README file
 0 files changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 README.txt
(issue-12)jj@im-jj:~/demo$ echo "this is a test file!" &amp;gt;&amp;gt; testfile.txt
(issue-12)jj@im-jj:~/demo$ git add testfile.txt
(issue-12)jj@im-jj:~/demo$ git commit -m "Added testfile.txt"
[issue-12 f9753df] Added testfile.txt
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 testfile.txt
(issue-12)jj@im-jj:~/demo$ echo "print 'hi again'" &amp;gt;&amp;gt; feature.py
(issue-12)jj@im-jj:~/demo$ git add feature.py
(issue-12)jj@im-jj:~/demo$ git commit -m "Updated feature"
[issue-12 4e39fc7] Updated feature
 1 files changed, 3 insertions(+), 1 deletions(-)&lt;/pre&gt;
&lt;h2&gt;Getting feedback on your feature&lt;/h2&gt;
&lt;p&gt;If you want to share all that work with someone else as a patch (maybe for code review or something), that is pretty simple:&lt;/p&gt;
&lt;pre&gt;(issue-12)jj@im-jj:~/demo$ git diff master&lt;/pre&gt;
&lt;p&gt;This is really saying, &amp;#8220;compare what’s currently on my branch with what’s on master and print it to standard out.&lt;/p&gt;
&lt;p&gt;You can redirect the output of that to a file (ie, &lt;code&gt;git diff master &amp;gt; issue12.diff&lt;/code&gt;) if you need.&lt;/p&gt;
&lt;h2&gt;Packaging up your work for the shared repository&lt;/h2&gt;
&lt;p&gt;When you’re ready to share this feature with the rest of your team, they &lt;strong&gt;probably&lt;/strong&gt; won’t care about all your interim commits (for example, you added and then changed feature.py). We can package up all the commits into one big commit (sort of like the one big patch against master you used before) by using git’s rebase command.&lt;/p&gt;
&lt;pre&gt;(issue-12)jj@im-jj:~/demo$ git rebase -i master&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;-i&lt;/code&gt; flag is “interactive” which allows you to specify what you want git to do with each of those interim commits. It should present a text editor that looks like this:&lt;/p&gt;
&lt;pre&gt;pick 765a6c0 Added feature
pick e7829cb Removed the README file
pick f9753df Added testfile.txt
pick 4e39fc7 Updated feature

# Rebase 309291d..4e39fc7 onto 309291d
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#&lt;/pre&gt;
&lt;p&gt;To pack all of these commits into a single commit, change all but the top one to &lt;code&gt;s&lt;/code&gt; or &lt;code&gt;squash&lt;/code&gt;. This says “keep the change from commit, but roll it into the parent commit”. The default as you can see is “pick” which if left alone would leave the commits separate. If for some reason you want to “undo” a commit that you already had, you can remove that line entirely. This makes will remove entirely the changes introduced in that particular commit.&lt;/p&gt;
&lt;p&gt;Keep in mind that you might not want to package everything as a single commit, and anything that you want to keep separate, just leave that line as &lt;code&gt;pick&lt;/code&gt; and it will be left alone. For the purposes of this article, we’re assuming that each branch is a completely isolated topic, where the intermediate commits are for your personal use, and not of any use to the rest of your team. This may not always be the case.&lt;/p&gt;
&lt;p&gt;To “package” up the branch into a single commit, our editor would look like this:&lt;/p&gt;
&lt;pre&gt;pick 765a6c0 Added feature
s e7829cb Removed the README file
s f9753df Added testfile.txt
s 4e39fc7 Updated feature

# Rebase 309291d..4e39fc7 onto 309291d
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#&lt;/pre&gt;
&lt;p&gt;Once you save that file, you’ll be prompted for a message to go along with the new “re-packaged” commit. Usually it’s best to start fresh from there and go with something about the feature, the prompt I got was:&lt;/p&gt;
&lt;pre&gt;# This is a combination of 4 commits.
# The first commit's message is:
Added feature

# This is the 2nd commit message:

Removed the README file

# This is the 3rd commit message:

Added testfile.txt

# This is the 4th commit message:

Updated feature

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD &amp;lt;file&amp;gt;..." to unstage)
#
#       deleted:    README.txt
#       new file:   feature.py
#       new file:   testfile.txt
#&lt;/pre&gt;
&lt;p&gt;Which you could change to:&lt;/p&gt;
&lt;pre&gt;Issue 12 - Added new feature XYZ

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD &amp;lt;file&amp;gt;..." to unstage)
#
#       deleted:    README.txt
#       new file:   feature.py
#       new file:   testfile.txt
#&lt;/pre&gt;
&lt;h2&gt;Keeping the shared repository linear&lt;/h2&gt;
&lt;p&gt;At this point, the “issue-12” branch consists of one single commit. However, if somebody else has pushed any changes to the shared repository, merging in the feature branch will have two commits: one for the feature itself, and another to merge the feature with whatever else was pushed by the rest of the team.&lt;/p&gt;
&lt;p&gt;All those “merged my local branch” commits will look like a lot of noise for no good reason, so git allows you to “replay” your commits against the master repository, with the end goal being to make your “re-packaged” commit to appear as though you branched right off the most updated version of the code.&lt;/p&gt;
&lt;p&gt;This is sometimes referred to as “changing history” because you are updating the parent of your current commit to be further along in the future than it actually was.&lt;/p&gt;
&lt;p&gt;To illustrate how this might work, you can make a small commit on master, and then use rebase to replay the commit against the updated master repository.&lt;/p&gt;
&lt;pre&gt;(issue-12)jj@im-jj:~/demo$ git checkout master 
Switched to branch 'master'
(master)jj@im-jj:~/demo$ echo "there was a typo" &amp;gt;&amp;gt; fixed_typo.txt
(master)jj@im-jj:~/demo$ git add fixed_typo.txt
(master)jj@im-jj:~/demo$ git commit -m "Added fixed typo"
[master c348893] Added fixed typo
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 fixed_typo.txt
(master)jj@im-jj:~/demo$ &lt;/pre&gt;
&lt;p&gt;Now master has one extra commit, and issue-12 has one extra commit, where each has the same parent. If you were to merge issue-12 into master you’d have the two commits we mentioned before (one for the “re-packaged” feature as a single commit, and another for the recursive merge). To get rid of that second commit that really doesn&amp;#8217;t provide much information to the team, we’ll rebase the commit to look like it happened &lt;em&gt;after&lt;/em&gt; the typo-fixing commit we just threw into master. This also will give us the chance to resolve any conflicts.&lt;/p&gt;
&lt;p&gt;This is one representation before we change the parent:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/246461fb8d916a9f8c11674fe031056e/tumblr_inline_miosypFQ8G1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;pre&gt;(master)jj@im-jj:~/demo$ git checkout issue-12 
Switched to branch 'issue-12'
(issue-12)jj@im-jj:~/demo$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Issue 12 - Added new feature XYZ&lt;/pre&gt;
&lt;p&gt;This is one representation after the rebase changed the parent:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/a90e075e2015948e0a0569d36cc394ee/tumblr_inline_mioszf8aL71qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Now we can merge the change back into master with a fast forward:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;(issue-12)jj@im-jj:~/demo$ git checkout master 
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit. # &amp;lt;-- Always be 1 commit ahead.
(master)jj@im-jj:~/demo$ git merge issue-12 
Updating c348893..d0e9912
Fast forward
 feature.py   |    3 +++
 testfile.txt |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
 delete mode 100644 README.txt
 create mode 100644 feature.py
 create mode 100644 testfile.txt&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;Now let’s double check that we can still fast-forward on the shared repository:&lt;/span&gt;&lt;/p&gt;

&lt;pre&gt;(master)jj@im-jj:~/demo$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits. # &amp;lt;-- 1 for issue-12, 1 for the typo-fix.
#
nothing to commit (working directory clean)
(master)jj@im-jj:~/demo$ git remote show origin 
* remote origin
  URL: my-server:/git/demo.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (fast forwardable) # &amp;lt;-- Always be able to fast-forward.&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Since we can fast forward, it’s just a &lt;/span&gt;&lt;code&gt;git push&lt;/code&gt;&lt;span&gt; away:&lt;/span&gt;&lt;/p&gt;

&lt;pre&gt;(master)jj@im-jj:~/demo$ git push origin
Counting objects: 8, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 699 bytes, done.
Total 7 (delta 0), reused 0 (delta 0)
To my-server:/git/demo.git
   309291d..d0e9912  HEAD -&amp;gt; master&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;And since we don’t need that issue branch anymore, we can delete it:&lt;/span&gt;&lt;/p&gt;

&lt;pre&gt;(master)jj@im-jj:~/demo$ git branch -d issue-12 
Deleted branch issue-12 (was d0e9912).&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;What if other people push stuff in the meantime?&lt;/h2&gt;
&lt;p&gt;If somebody else happens to push some code in the time between your rebase and your &lt;code&gt;git remote show origin&lt;/code&gt; (you’ll know this because the push won’t be “fast forwardable”) you should first pull down any changes, and then do another rebase. All this will do is (again) replay your commits ontop of the new ones that got pushed so that the shared repository doesn’t have lots of noise from merging your feature branch. Since you’ve already got the commit packaged up the way you like, you can leave off the &lt;code&gt;-i&lt;/code&gt; and just do:&lt;/p&gt;
&lt;pre&gt;(issue-12)jj@im-jj:~/demo$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Issue 12 - Added new feature XYZ&lt;/pre&gt;
&lt;p&gt;The moral of the story is that if you want to keep your shared repository full of only the important stuff, make sure all your pushes are fast-forwards. This is as easy as always remembering to rebase immediately before you push.&lt;/p&gt;
&lt;h2&gt;Staging and production&lt;/h2&gt;
&lt;p&gt;Now that you have the concept of feature branches down pat, another thing that we struggled with was how to deal with branches that signified different versions of our code.&lt;/p&gt;
&lt;p&gt;Ideally we’d like to have a “trunk” (aka master) and then a branch for the latest release-candidate (say “rc-1.0”) and then the official release branch (say “1.0”).&lt;/p&gt;
&lt;p&gt;The basic idea is to treat the release-candidate branch just like master (re-packaging commits, feature branches, etc) and then the production branch as a “merge-only” or “cherry-pick-only” branch. Some people prefer to use tags for this, however using a tag means that anything currently in testing will hold up moving things into production. This is a choice you’ll have to make, a branch gives a bit more independence from the RC than a tag.&lt;/p&gt;
&lt;h2&gt;Creating the branch&lt;/h2&gt;
&lt;p&gt;It seems like the first place to start would be to create the RC branch:&lt;/p&gt;
&lt;pre&gt;(master)jj@im-jj:~/demo$ git checkout -b rc-1.0
Switched to a new branch 'rc-1.0'
(rc-1.0)jj@im-jj:~/demo$ git push origin rc-1.0
Total 0 (delta 0), reused 0 (delta 0)
To my-server:/git/demo.git
 * [new branch]      rc-1.0 -&amp;gt; rc-1.0
(rc-1.0)jj@im-jj:~/demo$ git remote show origin 
* remote origin
  URL: my-server:/git/demo.git
  HEAD branch (remote HEAD is ambiguous, may be one of the following):
    master
    rc-1.0
  Remote branches:
    master tracked
    rc-1.0 tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local refs configured for 'git push':
    master pushes to master (up to date)
    rc-1.0 pushes to rc-1.0 (up to date)&lt;/pre&gt;
&lt;p&gt;Now you have a new release candidate branch that you can push changes to. Follow the same procedure discussed above to make sure that stays linear and everything should work out just fine.&lt;/p&gt;
&lt;p&gt;This is what you’re RC branch might look like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/966dd7c10f3018f93586df9f7c9cacf7/tumblr_inline_miot35rEbR1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;h2&gt;What if somebody else already created the branch?&lt;/h2&gt;
&lt;p&gt;Maybe someone else on your team already created the branch and you just need to check it out locally. This is pretty simple in git. The format is &lt;code&gt;git checkout -b mybranch -t origin/mybranch&lt;/code&gt;. For example, if someone already created the rc-1.0 branch, we could pull it down like this:&lt;/p&gt;

&lt;pre&gt;(master)jj@im-jj:~/demo$ git checkout -b rc-1.0 -t origin/rc-1.0 
Branch rc-1.0 set up to track remote branch rc-1.0 from origin.
Switched to a new branch 'rc-1.0'
(rc-1.0)jj@im-jj:~/demo$ git remote show origin 
* remote origin
  URL: my-server:/git/demo.git
  HEAD branch: master
  Remote branches:
    master tracked
    rc-1.0 tracked
  Local branches configured for 'git pull':
    master merges with remote master
    rc-1.0 merges with remote rc-1.0
  Local refs configured for 'git push':
    master pushes to master (up to date)
    rc-1.0 pushes to rc-1.0 (up to date)&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Merging between branches&lt;/h2&gt;
&lt;p&gt;If everything is going fine, there will come a point when it’s time to merge all the changes you made on your RC branch back to the master branch. This is nothing more than a &lt;code&gt;git merge&lt;/code&gt;. (Note that this is one place where you won’t be fast-forwarding, but always should have a merge commit to show that you merged the RC branch back to master.)&lt;/p&gt;
&lt;pre&gt;(rc-1.0)jj@im-jj:~/demo$ git checkout master
Switched to branch 'master'
(master)jj@im-jj:~/demo$ git merge rc-1.0 
Merge made by recursive.
 mynewfile.txt  |    1 +
 mynewfile2.txt |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 mynewfile.txt
 create mode 100644 mynewfile2.txt
(master)jj@im-jj:~/demo$ git push
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 331 bytes, done.
Total 2 (delta 1), reused 0 (delta 0)
To my-server:/git/demo.git
   af218a9..b4c7ac5  HEAD -&amp;gt; master&lt;/pre&gt;
&lt;p&gt;After things are merged back, your repository will look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/ffe0286db8071f02783113f7fb51609f/tumblr_inline_miot4xj6pl1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;h2&gt;Ready to release&lt;/h2&gt;
&lt;p&gt;When your release candidate has made it through all the testing it needs, you should be ready to create a production branch. This is just like the previous example where all you need to do is create the remote branch off of the RC branch.&lt;/p&gt;
&lt;pre&gt;(master)jj@im-jj:~/demo$ git checkout rc-1.0 
Switched to branch 'rc-1.0'
(rc-1.0)jj@im-jj:~/demo$ git checkout -b 1.0
Switched to a new branch '1.0'
(1.0)jj@im-jj:~/demo$ git push origin 1.0
Total 0 (delta 0), reused 0 (delta 0)
To my-server:/git/demo.git
 * [new branch]      1.0 -&amp;gt; 1.0&lt;/pre&gt;
&lt;p&gt;Usually this branch will stay up to date with the RC branch, and as bugs are fixed in the RC they are just merged over into the production branch.&lt;/p&gt;
&lt;pre&gt;(1.0)jj@im-jj:~/demo$ git checkout rc-1.0 
Switched to branch 'rc-1.0'
(rc-1.0)jj@im-jj:~/demo$ echo 'print "fixing a bug"' &amp;gt;&amp;gt; feature.py
(rc-1.0)jj@im-jj:~/demo$ git add -A &amp;amp;&amp;amp; git commit -m "Added bug fix"
[rc-1.0 52a6d49] Added bug fix
 1 files changed, 1 insertions(+), 0 deletions(-)
(rc-1.0)jj@im-jj:~/demo$ git push
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 338 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To my-server:/git/demo.git
   97a0f2a..52a6d49  HEAD -&amp;gt; rc-1.0&lt;/pre&gt;
&lt;p&gt;And once somebody verifies that the bug is then fixed:&lt;/p&gt;
&lt;pre&gt;(rc-1.0)jj@im-jj:~/demo$ git checkout 1.0 
Switched to branch '1.0'
(1.0)jj@im-jj:~/demo$ git merge rc-1.0 
Updating 97a0f2a..52a6d49
Fast forward
 feature.py |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
(1.0)jj@im-jj:~/demo$ git push
Total 0 (delta 0), reused 0 (delta 0)
To my-server:/git/demo.git
   97a0f2a..52a6d49  HEAD -&amp;gt; 1.0&lt;/pre&gt;
&lt;p&gt;The same thing applies when you want to pull back this new change into master:&lt;/p&gt;
&lt;pre&gt;(1.0)jj@im-jj:~/demo$ git checkout master
Switched to branch 'master'
(master)jj@im-jj:~/demo$ git merge rc-1.0 
Merge made by recursive.
 feature.py |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
(master)jj@im-jj:~/demo$ git push
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 285 bytes, done.
Total 2 (delta 1), reused 0 (delta 0)
To my-server:/git/demo.git
   b4c7ac5..4834481  HEAD -&amp;gt; master&lt;/pre&gt;
&lt;h2&gt;What if I just want one commit?&lt;/h2&gt;
&lt;p&gt;There may be times when the production branch &lt;strong&gt;needs&lt;/strong&gt; an important fix, but there are other features on the branch that haven’t been adequately tested. This problem is pretty well solved by “cherry-picking”. Merging won’t work because a merge carries with it all the parent commits until a common ancestor, which you definitely don’t want if those parent commits haven’t been tested.&lt;/p&gt;
&lt;p&gt;The basic idea cherry-picking is that git will take the change-set, package it up as a different commit, and move it over to another branch, without taking anything else.&lt;/p&gt;
&lt;p&gt;Let’s make two small bug fixes on rc-1.0, and then take the last one over with a cherry pick.&lt;/p&gt;
&lt;pre&gt;(master)jj@im-jj:~/demo$ git checkout rc-1.0 
Switched to branch 'rc-1.0'
(rc-1.0)jj@im-jj:~/demo$ echo '# bugfix1!' &amp;gt;&amp;gt; feature.py 
(rc-1.0)jj@im-jj:~/demo$ git add -A &amp;amp;&amp;amp; git commit -m "Added bugfix number 1"
[rc-1.0 92ab376] Added bugfix number 1
 1 files changed, 1 insertions(+), 0 deletions(-)
(rc-1.0)jj@im-jj:~/demo$ echo '# bugfix2!' &amp;gt;&amp;gt; feature2.py 
(rc-1.0)jj@im-jj:~/demo$ git add -A &amp;amp;&amp;amp; git commit -m "Added bugfix number 2"
[rc-1.0 1dec2d3] Added bugfix number 2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 feature2.py
(rc-1.0)jj@im-jj:~/demo$ git push
Counting objects: 8, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 629 bytes, done.
Total 6 (delta 3), reused 0 (delta 0)
To my-server:/git/demo.git
   52a6d49..1dec2d3  HEAD -&amp;gt; rc-1.0&lt;/pre&gt;
&lt;p&gt;If we just wanted to merge over bug fix number 2, the merge would also carry bug fix number 1 along with it since that’s the common parent. We haven’t tested bug fix number 1, so we’ll need to cherry pick number 2 over onto the 1.0 branch by itself.&lt;/p&gt;
&lt;pre&gt;(rc-1.0)jj@im-jj:~/demo$ git log --pretty=oneline --abbrev-commit
1dec2d3 Added bugfix number 2 # &amp;lt;-- This is the commit we want, note the short-hash.
92ab376 Added bugfix number 1
52a6d49 Added bug fix
97a0f2a Minor commit
099214d Minor commit
d0e9912 Issue 12 - Added new feature XYZ
c348893 Added fixed typo
309291d Initial Commit
(rc-1.0)jj@im-jj:~/demo$ git checkout 1.0 
Switched to branch '1.0'
(1.0)jj@im-jj:~/demo$ git cherry-pick 1dec2d3
Finished one cherry-pick.
[1.0 8e3a5f9] Added bugfix number 2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 feature2.py
 (1.0)jj@im-jj:~/demo$ git push
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 289 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To my-server:/git/demo.git
   52a6d49..8e3a5f9  HEAD -&amp;gt; 1.0&lt;/pre&gt;
&lt;p&gt;You now have the change-set from bug fix number 2, but it’s technically a fully different commit (with its own commit hash and everything). This allows you to move things over from the RC branch independently of other things in the branch. Also, when you do decide to merge over the rest of the RC branch, that shouldn’t be a problem at all since I guess git knows that the new commit has the same content and just a different parent.&lt;/p&gt;
&lt;h2&gt;Help, I broke things and want to start over&lt;/h2&gt;
&lt;p&gt;Another common thing I find myself doing all the time is having to “try again” after I accidentally merge over the wrong commit, or make a change that just isn’t right. This is where the &lt;code&gt;git reset&lt;/code&gt; command comes in handy.&lt;/p&gt;
&lt;p&gt;If you just committed before you were ready, the standard &lt;code&gt;git reset HEAD~1&lt;/code&gt; will work just fine. This is git-speak for “rewind things by 1 commit, but don’t change the contents of the files on disk”.&lt;/p&gt;
&lt;p&gt;If you do want to undo any changes to files locally, you can use the &lt;code&gt;--hard&lt;/code&gt; flag to change that as well: &lt;code&gt;git reset --hard HEAD~1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;HEAD~1&lt;/code&gt; is notation for the head of the current branch minus 1 commit. So &lt;code&gt;HEAD~4&lt;/code&gt; would mean “four commits ago”.&lt;/p&gt;
&lt;p&gt;You can also point out a specific commit by it’s short hash to rewind to that point in time. And remember the &lt;code&gt;--hard&lt;/code&gt; flag will bring you back to that point with the exact code from then as well.&lt;/p&gt;
&lt;pre&gt;(1.0)jj@im-jj:~/demo$ git log --abbrev-commit --pretty=oneline
8e3a5f9 Added bugfix number 2
52a6d49 Added bug fix
97a0f2a Minor commit
099214d Minor commit
d0e9912 Issue 12 - Added new feature XYZ
c348893 Added fixed typo
309291d Initial Commit
(1.0)jj@im-jj:~/demo$ git reset --hard 52a6d49
HEAD is now at 52a6d49 Added bug fix
(1.0)jj@im-jj:~/demo$ git log --abbrev-commit --pretty=oneline
52a6d49 Added bug fix
97a0f2a Minor commit
099214d Minor commit
d0e9912 Issue 12 - Added new feature XYZ
c348893 Added fixed typo
309291d Initial Commit&lt;/pre&gt;
&lt;h2&gt;I accidentally started my work on master…&lt;/h2&gt;
&lt;p&gt;Sometimes I’ll make a couple of small changes on master and one thing leads to another and all the sudden I realize I’ve got a lot of changes right on master instead of a feature branch. Let’s get into that situation real quick:&lt;/p&gt;
&lt;pre&gt;(rc-1.0)jj@im-jj:~/demo$ git checkout master
Switched to branch 'master'
(master)jj@im-jj:~/demo$ touch myothernewfile.txt
(master)jj@im-jj:~/demo$ git add myothernewfile.txt
(master)jj@im-jj:~/demo$ git commit -m "Added another new file"
[master 617f46d] Added another new file
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 myothernewfile.txt
(master)jj@im-jj:~/demo$ touch onemorefile.txt
(master)jj@im-jj:~/demo$ git add onemorefile.txt
(master)jj@im-jj:~/demo$ git commit -m "Added one more new file"
[master 23290ed] Added one more new file
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 onemorefile.txt&lt;/pre&gt;
&lt;p&gt;OK, now we are on master, with two commits that we accidentally did right on master instead of a feature branch. The way we’ll get these onto a feature branch, and get master back to normal is with by branching and resetting.&lt;/p&gt;
&lt;p&gt;First, we’ll create a branch from master which will have those two commits, then we’ll reset our master branch back to before we accidentally made those commits.&lt;/p&gt;
&lt;pre&gt;(master)jj@im-jj:~/demo$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
nothing to commit (working directory clean)
(master)jj@im-jj:~/demo$ git branch feature1
(master)jj@im-jj:~/demo$ git reset --hard origin/master 
HEAD is now at 4834481 Merge branch 'rc-1.0'
(master)jj@im-jj:~/demo$ git status
# On branch master
nothing to commit (working directory clean)&lt;/pre&gt;
&lt;p&gt;This keeps your changes off on the “feature1” branch, and then moves the “master” pointer back to the master pointer on the shared repository. If you checkout the feature1 branch, you’ll see that the changes you made originally on master are in place over there, and you can easily merge them back into master when the time comes to commit them.&lt;/p&gt;
&lt;h2&gt;That’s all&lt;/h2&gt;
&lt;p&gt;That’s all I have for now. If there’s anything missing that you’d like to see feel free to e-mail me at jj@(this website).&lt;/p&gt;
&lt;p&gt;Extra thanks to Mark Chadwick for being the inspiration behind this post. Also if you’re going to be working with lots of git repositories and lots of different branches, see my previous post (&lt;a href="http://geewax.org/2009/11/15/git-workspace-magic.html"&gt;&lt;a href="http://geewax.org/2009/11/15/git-workspace-magic.html"&gt;http://geewax.org/2009/11/15/git-workspace-magic.html&lt;/a&gt;&lt;/a&gt;) for how to make your PS1 update based on what branch you’re currently on.&lt;/p&gt;
&lt;h2&gt;Other discussions&lt;/h2&gt;
&lt;p&gt;There are a few discussions going on over at Reddit and HackerNews, some of the feedback has been incorporated into the article since then, but hopefully the comments on these forums can help you to adapt this workflow to best suit the needs of your team.&lt;/p&gt;
&lt;p&gt;You can find these discussions here:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.reddit.com/r/programming/comments/be5ih/agile_git_workflow/"&gt;&lt;a href="http://www.reddit.com/r/programming/comments/be5ih/agile_git_workflow/"&gt;http://www.reddit.com/r/programming/comments/be5ih/agile_git_workflow/&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.reddit.com/r/programming/comments/be5ih/agile_git_workflow/"&gt;&lt;a href="http://news.ycombinator.com/item?id=1195791"&gt;http://news.ycombinator.com/item?id=1195791&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><link>http://geewax.org/post/43822223029</link><guid>http://geewax.org/post/43822223029</guid><pubDate>Sat, 23 Feb 2013 14:10:00 -0500</pubDate><category>coding</category><category>agile</category><category>git</category><category>workflow</category></item><item><title>git Workspace Magic in bash</title><description>&lt;p&gt;I have lots of projects in PyDev in Eclipse all of which I navigate through with the terminal in Ubuntu (this blog’s source is one of them), so just recently with the help of a couple co-workers I put together some bash methods for moving around my projects easily.&lt;/p&gt;
&lt;p&gt;I found that the common pattern was:&lt;/p&gt;
&lt;pre&gt;jj@im-jj:~$ cd workspace/dashboard/src/
jj@im-jj:~/workspace/dashboard/src$ source environment/bin/activate
(environment)jj@im-jj:~/workspace/dashboard/src$ deactivate 
jj@im-jj:~/workspace/dashboard/src$ cd ../../reportingdb/src/
jj@im-jj:~/workspace/reportingdb/src$ source environment/bin/activate
(environment)jj@im-jj:~/workspace/reportingdb/src$ &lt;/pre&gt;
&lt;p&gt;The first thing I wanted was to know which project I was in and which branch in git that I was on. With a couple of helper methods this is actually pretty easy and just involves overwriting the PS1 environment variable.&lt;/p&gt;
&lt;pre&gt;# Git stuff:
function get_repository {
    pwd | grep $HOME'/workspace/.*/src.*' | awk -F/ '{print "("$5")"}'
}
function get_branch {
    git branch 2&amp;gt; /dev/null | grep \* | awk '{print "("$2")"}'
}

# Update PS1
PS1="\[\033[01;34m\]\$(get_repository)\[\033[31m\]\$(get_branch)\[\033[37m\]\[\033[00m\]\[\033[38m\]\u@\h:\w$ "&lt;/pre&gt;
&lt;p&gt;Now my prompt lets me know pretty acurately where I am in my source:&lt;/p&gt;
&lt;pre&gt;(environment)(dashboard)(master)jj@im-jj:~/workspace/dashboard/src$ git branch test
(environment)(dashboard)(master)jj@im-jj:~/workspace/dashboard/src$ git checkout test
Switched to branch 'test'
(environment)(dashboard)(test)jj@im-jj:~/workspace/dashboard/src$ &lt;/pre&gt;
&lt;p&gt;The next thing I decided to add in was a command called `jumpto` which would deactivate whatever environment I’m in, jump into the proper directory, and then activate the current virtual environment for me to start working. Also, I wanted just `jumpto` with no arguments to bring me back to my home directory and exit out of any virtual environments.&lt;/p&gt;
&lt;p&gt;The end result of this was the following:&lt;/p&gt;
&lt;pre&gt;function jumpto {
    if [ -z "$1" ]; then
        deactivate 2&amp;gt;/dev/null
        cd $HOME
        return 0
    fi

    local DIRECTORY=$HOME/workspace/$1/src

    if [ -d $DIRECTORY ]; then
        deactivate 2&amp;gt;/dev/null
        cd $DIRECTORY
        if [ -d $DIRECTORY/environment ]; then
            source $DIRECTORY/environment/bin/activate
        fi
    else
        echo "Invalid workspace! ($1)"
    fi
}&lt;/pre&gt;
&lt;p&gt;This made moving around pretty easy:&lt;/p&gt;
&lt;pre&gt;jj@im-jj:~$ jumpto dashboard
(environment)(dashboard)(master)jj@im-jj:~/workspace/dashboard/src$ jumpto reportingdb
(environment)(reportingdb)(master)jj@im-jj:~/workspace/reportingdb/src$ jumpto 
jj@im-jj:~$ &lt;/pre&gt;
&lt;p&gt;The next thing I wanted was to do tab-completion based on the projects that I had set up in my `~/workspace/` directory. After some research on how tab completion works in the first place, I ended up with the following:&lt;/p&gt;
&lt;pre&gt;_jumpto() {
    local IFS=$'\t\n'
    local dirs=("$HOME/workspace/")

    COMPREPLY=( $(
        for dir in "${dirs}"; do
            cd "$dir" 2 &amp;gt;/dev/null &amp;amp;&amp;amp;
            compgen -d -- "${COMP_WORDS[COMP_CWORD]}"
        done
    ) )
    return 0
}

complete -o filenames -o nospace -F _jumpto jumpto&lt;/pre&gt;
&lt;p&gt;This lets me do things like `ju[tab] das[tab]` and end up in the dashboard project with the virtual environment all set up and ready to go.&lt;/p&gt;
&lt;p&gt;I hope this helps somebody else out who’s working with lots of git projects with lots of different branches and virtual environments for each of them.&lt;/p&gt;</description><link>http://geewax.org/post/43821179961</link><guid>http://geewax.org/post/43821179961</guid><pubDate>Sat, 23 Feb 2013 13:56:40 -0500</pubDate><category>coding</category><category>bash</category><category>git</category><category>workflow</category></item><item><title>Creating iPhone Ringtones on Ubuntu</title><description>&lt;p&gt;I just had a hell of a time trying to turn a very short MP3 file into a ringtone for my iPhone. I ended up using &lt;a href="http://pacpl.sourceforge.net/"&gt;Perl Audio Converter&lt;/a&gt; and faac (Freeware Advanced Audio Coder) to turn the MP3 file into an m4a. After that I renamed as m4r and dragged onto the iPhone.&lt;/p&gt;
&lt;p&gt;The short version boils down to:&lt;/p&gt;
&lt;pre&gt;$ sudo apt-get install pacpl faac
$ pacpl --to m4a yourfile
$ mv yourfile.m4a yourfile.m4r&lt;/pre&gt;
&lt;p&gt;After that, just drag the m4r file onto the iPhone device in iTunes.&lt;/p&gt;</description><link>http://geewax.org/post/43821022071</link><guid>http://geewax.org/post/43821022071</guid><pubDate>Sat, 23 Feb 2013 13:54:34 -0500</pubDate><category>audio</category><category>faac</category><category>ubuntu</category><category>iphone</category></item><item><title>Easy-Installing SOAPpy 0.12.0</title><description>&lt;p&gt;I was recently working with virtualenv by Ian Bicking (which is awesome) and I ended up having quite a bit of trouble getting SOAPpy v 0.12.0 installed. It’s a standard EasyInstall package, so it should be no sweat, but it seems like SOAPpy (a deprecated package I believe…) has a few problems which appear to be “packaging” related.&lt;/p&gt;
&lt;p&gt;For example, the package does a couple of &lt;code&gt;from __future__ import ...&lt;/code&gt; calls, which in Python 2.5, must be the first line of the file. This seems fine, except the author(s) (I assume when they were packing the library up to share with the world) added copyright notices at the top of files as strings instead of comments. This means that importing the files (which EasyInstall does) will throw an Exception about the placement of the &lt;code&gt;__future__&lt;/code&gt;imports.&lt;/p&gt;
&lt;p&gt;There was also an issue with dependencies, where SOAPpy clearly requires the fpconst library, but doesn’t declare the dependency in it’s &lt;code&gt;setup.py&lt;/code&gt; file. This means that you install SOAPpy and then run into an ImportError for a package that EasyInstall should just grab for you.&lt;/p&gt;
&lt;p&gt;To remedy these things I repackaged SOAPpy 0.12.0 with the fixed &lt;code&gt;__future__&lt;/code&gt; imports and the proper dependency declarations. In case anyone else has a problem similar to this, you can find the file at&lt;a href="http://static.geewax.org/SOAPpy-0.12.0.zip"&gt;&lt;a href="http://static.geewax.org/SOAPpy-0.12.0.zip"&gt;http://static.geewax.org/SOAPpy-0.12.0.zip&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to use EasyInstall to do the work, you can do it with:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;sudo easy_install &lt;a href="http://static.geewax.org/SOAPpy-0.12.0.zip"&gt;&lt;a href="http://static.geewax.org/SOAPpy-0.12.0.zip"&gt;http://static.geewax.org/SOAPpy-0.12.0.zip&lt;/a&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description><link>http://geewax.org/post/43820965315</link><guid>http://geewax.org/post/43820965315</guid><pubDate>Sat, 23 Feb 2013 13:53:48 -0500</pubDate><category>coding</category><category>python</category><category>easy_install</category><category>SOAPpy</category></item><item><title>GAE Testbed Documentation Released</title><description>&lt;p&gt;I’d been looking to get familiar with Sphinx for a while, and couldn’t ever seem to find a project of mine that needed documentation enough to take the leap. This past week, I decided that even though &lt;span class="caps"&gt;GAE&lt;/span&gt; Testbed is a relatively small project, it could definitely use good documentation and finally got around to working with Sphinx.&lt;/p&gt;
&lt;p&gt;I must say that I’m really impressed with the package as a whole (running it both on my MacBook and my Windows machine), though it was a bit tricky to get set up and familiar with the layout.&lt;/p&gt;
&lt;p&gt;That said, feel free to take a look at &lt;a href="http://gaetestbed.geewax.org/index.html"&gt;the new &lt;span class="caps"&gt;GAE&lt;/span&gt; Testbed documentation&lt;/a&gt; which is located at&lt;a href="http://gaetestbed.geewax.org/index.html"&gt;&lt;a href="http://gaetestbed.geewax.org/index.html"&gt;http://gaetestbed.geewax.org/index.html&lt;/a&gt;&lt;/a&gt;. For those of you looking to get &lt;a href="http://github.com/jgeewax/gaetestbed"&gt;the code for &lt;span class="caps"&gt;GAE&lt;/span&gt; Testbed&lt;/a&gt; , it’s located on Google Code at &lt;a href="http://github.com/jgeewax/gaetestbed"&gt;&lt;a href="http://github.com/jgeewax/gaetestbed"&gt;http://github.com/jgeewax/gaetestbed&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;</description><link>http://geewax.org/post/43820912826</link><guid>http://geewax.org/post/43820912826</guid><pubDate>Sat, 23 Feb 2013 13:53:05 -0500</pubDate><category>coding</category><category>appengine</category><category>testbed</category><category>unittesting</category></item></channel></rss>
