Programming

These are a few git aliases I’ve made recently to make my life a little easier. The first two are for displaying the log, and the rest for merging. See the Git wiki for more on how to add aliases.

Logs

I pretty much always want the one-line log, so this is the basic version of that:

ls = log --oneline --decorate

--decorate shows any labels on commits, such as branch names. Sometimes I want the above but with the graph view turned on:

lg = log --oneline --decorate --graph

Merging

Merges in git fall into two basic categories: fast-forward merges in which the branch label is simply updated to a new commit (but no new commit is made), and all other merges in which a new commit is made with multiple parents.

By default the merge command will attempt to do a fast-forward merge. If that won’t work it will move to some other “real” merge strategy. I think the difference between fast-forward and the other merges is sufficient that they shouldn’t happen with the same command so I’ve set up aliases to separate them. First the alias for doing a fast-forward. This will fail if a fast-forward is not possible:

ff = merge --ff-only

And then an alias for forcing a non-fast-forward merge even in situations where a fast-forward would be possible:

mrg = merge --no-ff

(This is the sort of merge GitHub does when you merge a pull request.)

Pulling

The pull command is really fetch + merge so it takes most of the same options. When I do a pull I generally only want it to succeed if it’s possible to fast-forward my local branch. If git must do a real merge something is probably wrong, so I have a fast-forward-only pull alias:

There are many, many command line converters for turning Markdown into HTML, but for the most part these make HTML fragments, not full documents with CSS styling. That’s fine most of the time (e.g. when I’m writing blog posts), but sometimes I want a full, pretty document so I can print it out (typically for presentation notes).

To fill this hole I put together a small script that converts Markdown and wraps the HTML result in a template that includes Bootstrap CSS. I set the fonts to sans-serif and monospace so that they are taken from the defaults for your browser, making it easier to use your favorite fonts.

Over the past year or so I have on a few occasions taught git to people
accustomed to using Subversion. These are experienced software developers so it
seems like it should be easy, but it is almost always a difficult process
filled with acrimony, resistance, and gasps. (And this from people who seem
to use Emacs, vim, and Linux without complaint.)

And yet when I teach git to people who don’t already have a preferred
version control system it seems to go pretty well. It takes time, and there
may be confusion, but we demo and practice and learn as with any topic.
There is no hate. I think I’m beginning to understand the situation:

Git isn’t just a little different, it’s completely different. But, dear
svn users, git is not different because it doesn’t like you. Git is different
because it’s optimized to facilitate the collaboration of a number of
developers working on a rapidly changing code base. Some examples:

Branching is easy in git so that you can work in peace isolated from
upstream changes until you are ready to send your work back.

When it’s time to merge back git provides rebase to facilitate cleanly
integrating upstream changes.

Git is distributed so that you and everyone else can make all manner of
branches and experiments without dirtying up the master repo.

Git is different from svn, but it does well what it is designed to do.
This brings me back to the Lao Tsu quote from the top and a simple message
to svn users learning git: You will have to drop your svn workflow to make
the most of git, but it’s not because git is bad, it’s just different. Yield,
use git in the way it was meant to be used, and be happy.

Normally when I do a push in git I do something like git push origin master, which really means push from the local branch named master to the remote branch named master. If you want to push to a remote branch with a different name than your local branch, separate the local and remote names with a colon:

Learning to program and learning the basics of control flow can be tricky business for novices. I wanted to make something that provided immediate, visual feedback to students as they practice things like for loops and if statements so they can see precisely what their code is (or isn’t) doing. So I wrote ipythonblocks.

The IPythonNotebook makes it possible to display rich representations of Python objects using HTML (among other things). That allowed me to make a Python object whose representation in the Notebook is a colored table. Students can index into the table to change the color properties of individual table cells and then immediately display their changes.

With ipythonblocks instructors can give coding problems like ‘turn every block in the third column red’ or ‘turn every blue block green’ and by displaying their blocks students can see right away whether their code is having the desired effect.

This week I was in a job interview and one of my interview questions turned into a pretty interesting puzzle. I was asked the following question:

Assume a character encoding a = 1, b = 2, c = 3, … , z = 26. Given a string of numbers (e.g. '123456'), figure out how many different ways that string could be decoded.

I didn’t arrive a complete solution in the few minutes I had during the interview but I kept thinking about it afterwards because I couldn’t shake the feeling there was really a math problem here, not just a programming problem.

The difficult part of this challenge is figuring out how many decodings there are when there are overlapping possible groupings of numbers. For example, the string '111' can be decoded as ['1', '1', '1'], ['11', '1'], or ['1', '11']. I never figured out a formula for calculating the number of decodings but by manually figuring out the number of decodings for the strings '1', '11', '111', '1111', '11111', '111111', etc. I noticed that the number of decodings follow the Fibonacci sequence starting with 1, 2, 3, 5, 8…! Unfortunately I don’t have a good explanation for why that is the case. (Though it makes gut level sense in the way the Fibonacci sequence is a sum of everything that has come before.) Please leave a comment if you can explain this!

So, my strategy for solving this problem follows these basic steps:

Break the given string down into substrings such that each substring is one digit, '10' or '20', or cannot be broken down further because it has an unknown number of possible decodings. These substrings can be considered independently for the purposes of this problem.

For each substring figure out the number of decodings. For single digits, '10', and '20' this is just 1. For other substrings this is the Nth value in the Fibonacci series 1, 2, 3, 5, 8… where N is the length of the substring.

Multiply together all of the number of decodings for the individual substrings to get the number of of decodings for the original string of numbers.