Lee Green

Software developer. Time traveler.

Developer Superpower: Aliases

This is the second in a series of posts designed to help you supercharge your workflow.

In my last post I mentioned aliases in passing. A few readers asked me for more information, so I thought I’d write another post.

An alias is essentially a shortcut, or abbreviation, which lets you “remap” any command to run one or more other commands. Many developer / command-line tools support aliases, from command-line shells like bash, zsh, or PowerShell, to version-control systems like Git or Mercurial. I’ll give concrete examples for bash and Git in this post.

Before I do, though, I want to talk about the reasons one might create an alias. I find that the aliases I need can be classified into a few categories:


These aliases are all about speed, so they’re as short as possible. git diff takes too long to type? Alias it to gd. The most common example of this is the ll alias for ls -l, now included in many Linux distros by default.

I also include in this category aliases that cover common typos, for example:

  • cd.. instead of cd .. (leaving out the space)
  • rpsec instead of rspec (transposing the s and the p)
  • xs or vf instead of cd (off-by-one error)
  • gut or got instead of git (off-by-one error on the other hand)

Backwards compatibility

I started working as a software developer before Linus created Git, in what many consider “the dark ages”. As such, I spent a few years using RCS and CVS for version control. In RCS the commands for check out and check in are co and ci; these commands were preserved in CVS as aliases for checkout and commit respectively.

As Git became popular and our projects switched over to using it exclusively, a senior developer I worked with set up extensive aliases so he could continue using the same commands he’d been used to. I try not to go that far, but muscle memory is powerful — and aliases like this can save you a lot of pain.

Frame of mind

This one actually started as a backwards compatibility alias, but its role has really evolved for me over time. Most version-control systems have a command that shows you which user last modified each line in a file. In SVN, this commmand is called blame, but it has aliases: annotate and praise.

When we switched to Git, that same senior dev installed praise as an alias for blame. Even though I’ve never used SVN heavily, I still invoke praise every time, because it reminds me to be charitable with my fellow developers.


In Bash, aliases are created using alias, and destroyed with unalias:

alias ll='ls -l'
alias rpsec='rspec'

unalias ll
unalias rpsec

Personal aliases are typically defined in the ~/.bashrc file.

Note that aliases can cover or “shadow” existing commands. This can be both frustrating and awesome. For example, if you alias ls to ls -G, all your invocations of ls will hit the alias, not the base command.

tldp.org has more information on aliases in Bash.


There are two ways to create Git aliases. The first is via command line:

git config --global alias.co checkout
git config --global alias.ci commit

The second way is via editing a ~/.gitconfig (global) or .git/config (per-repository) file (this is my actual gitconfig file):

    ci = commit
    co = checkout
    st = status
    stat = status
    praise = blame
    sb = show-branch
    what = whatchanged
    br = branch -a --color

    # "merged branches" -- which branches are ancestors of the specified ref?
    mbr = branch -a --merged
    # "what branches" -- which branches contain the specified ref?
    wbr = branch -a --contains

    # typo
    difff = diff

    # list all aliases
    la = "!git config -l | grep alias | cut -c 7-"

You can shell out in a Git alias, by starting the alias with a ! character:

git config --global alias.visual '!gitk'

It’s worth noting that the awesome git-completion supports tab completion for aliases, as well as Git builtin commands. You should probably install it, if you haven’t already :)

For more information on Git aliases, see the Pro Git book (pay for it!), or check here.

Here are a few samples of real-world Git aliases. Check these out, steal them for your own use, and remix them to increase your productivity!

Developer Superpower: Z

This is the first in a series of posts designed to help you supercharge your workflow.

Anyone who uses a command-line interface needs to change directories on a regular basis. Even if your terminal emulator allows you to open new windows in the same directory as previous ones, you still need to move around to get work done.

The problem

Getting directory paths right can take a lot of time, especially within a new project or a new environment. Shell tab completion can help, but it still has to be navigated, and new entries mess with your muscle memory.

There are, of course, more creative solutions: I’ve seen developers who create aliases for each major project directory they work with, which is nice at first, but it doesn’t really scale.

The solution

As is typical in computing, we can stand on the shoulders of giants — Behold Z, a directory jumper which enables freaky-fast directory switching:

$ z blog; pwd

$ z bigco roi; pwd

$ z scipy 0.15; pwd

It chooses directories based on frecency, which is “a portmanteau of frequency and recency”. It has a few options, so check GitHub, but I usually just invoke it bare — in my experience, it pretty much always Does What I Mean.


If you’re on OS X, it’s available via Homebrew, or follow the instructions below.

Just save it to disk and source it in your shell files — e.g. for bash:

curl -o ~/.z.sh -sSL https://raw.githubusercontent.com/rupa/z/d5adc9a6239c2ee44309fd78bca68f301eb0d45a/z.sh
# examine the downloaded file, if all appears good:
echo '. ~/.z.sh' >> ~/.bashrc

Afterwards, you may have to open a new terminal, or restart.

Note: The above snippet uses HTTPS and a fixed Git SHA, but do be careful here, since we’re basically piping curl to shell.

Fix Tar Errors on OS X

I’ve worked on a lot of software projects over the past 10 years, and on many of them, developers worked on OS X (or a Linux VM, using Vagrant), while the code was deployed on Linux. This can cause issues when extracting tar.gz files on Linux that were created on OS X.

If you’ve ever seen an error like this, you know what I’m talking about:

tar: Ignoring unknown extended header keyword `SCHILY.dev'
tar: Ignoring unknown extended header keyword `SCHILY.ino'
tar: Ignoring unknown extended header keyword `SCHILY.nlink'
tar: Error exit delayed from previous errors

What’s going on?

There are a few issues at play here:

  • On OS X, the default tar version is BSD, whereas on Linux it is GNU.
  • OS X encodes file attributes as extended headers in tar. BSD tar supports this, GNU tar does not.
  • Some versions of GNU tar have a bug where, when they encounter extended headers, the exit code indicates failure — even though the files extracted just fine.

When combined, these will cause problems for automated scripts or, for that matter, anyone who cares about clean execution logs. :)

How do we fix it?

There are several possible solutions:

Tell BSD tar not to insert the extended headers

This is probably the easiest method, and can be done at least two ways:

Environment variable
tar -czf $your_tar_gz $your_files
Command-line argument
tar --disable-copyfile -czf $your_tar_gz $your_files

Use BSD tar on Linux

This is not such a great option. For one, you need to make the change on your servers, as opposed to your development machines; secondly, you then need to keep track of which files are created with which version of tar.

Use GNU tar on OS X

This is my preferred option. No change to the server, and you get the assurance that the same version of tar will be used on both ends.

In fact, for a long time, OS X shipped with GNU tar installed! If you’re running a release before Mavericks, you can stop here and just invoke gnutar on OS X. This is easily scriptable:

Use GNU tar on OS X

if [ "$OS" == "Darwin" ]; then

For whatever reason, though, Apple stopped shipping GNU tar with OS X as of Mavericks. Not a problem — we’ll just lean on our old friend Homebrew!


Homebrew is a command-line package manager for OS X, which always has everything I’m looking for. I love Homebrew, even if they do tell you to pipe curl into Ruby (see here).

Once you have Homebrew installed, installing GNU tar is as easy as:

brew install gnu-tar

This installs GNU tar as gtar. If you’d like it available as gnutar like on previous versions of OS X, that’s just one line as well:

sudo ln -s /usr/local/opt/gnu-tar/libexec/gnubin/tar /usr/bin/gnutar


I found the following links useful here. You might, also.


Print Random Line(s) From a File

Occasionally, I have a need to pull a random line (or lines) from a file.

To make the example real, let’s say we’re parsing server logs, and the file contains one server name per line. If we want to test a change to our parser, we might want to choose a random server and parse the logs for only that server.

shuf, from GNU textutils, makes this easy:

server=`shuf -n 1 $source_file`
echo "The server we chose is: $server"

./our_parser $server

The -n parameter controls the number of lines returned: in this case, 1.

For more info on shuf, check Wikipedia or its man page.

How to Change Your Octopress Favicon

It seems like every Octopress blog eventually includes a post about customizing Octopress itself. If my previous post didn’t count, this one certainly will.

I see too many sites still running the stock Octopress favicon (pictured at left) — even sites that are otherwise completely customized! This is one of the easiest changes you can make to customize the appearance of your site. Here’s how to change it:

Create an image file

Save your preferred icon as a 32x32 (pixels) PNG file. Historically speaking, favicons are 16x16, but High-PPI displays (“Retina”, in Apple’s marketing language) are now the norm.

Replace the existing one

Replace the existing Octopress favicon in source/favicon.png with your newly created one.


Assuming you saw the default one before, the new one should show up without any issues.

If it doesn’t, ensure your theme has a link to the favicon. This is typically in source/_includes/head.html, although it may vary depending on your theme. There should be a line that looks like this:

Favicon link
<link href="/favicon.png" rel="icon">

Note: When testing, use a different browser, or a private-browsing window, to avoid cache issues.

Windows Chrome, Why Do My Fonts Look So Bad?

Anyone who knows me will tell you that I don’t exactly have great fashion sense. I don’t wear bespoke suits. Our house is not “exquisitely decorated”, or “tastefully appointed”. I focus more on the practical than the aesthetic. That said, when I started this blog, I knew I couldn’t leave it looking like every other Octopress blog (you know, like this).

Easy tweaks

I started (and finished) with the low-hanging fruit — colors and fonts.

The color scheme was easy — only the best color scheme ever, Solarized. My iTerm is Solarized dark, my graphical Vim is Solarized light, let’s keep this train a-rollin’.

I quickly found two great fonts: Montserrat (headings) and Varela Round (body). Both are available on Google Fonts via the SIL Open Font License — what’s not to love?

The problem

As it turns out, the answer is “Google Chrome on Windows”, especially with Google Fonts. For whatever reason, Chrome (only on Windows) doesn’t render TTF or WOFF fonts well. Click the image below for a more detailed view:

This is especially frustrating because Google Fonts prioritizes TTF and WOFF fonts over others (they are listed earlier in the @font-face rule). If you use Google Fonts, you just load their CSS into your page, so there’s no way to change the order.

The solution

Now, if you host your own fonts, or you can at least control your CSS, there is a fix. Chrome will render SVG fonts acceptably, so you just need to get Chrome to load the SVG font. You can do this in one of two ways. You can simply place the SVG earlier in the @font-face rule:

@font-face {
    font-family: 'my-webfont';
    src: url('/fonts/my-webfont.eot');
    src: url('/fonts/my-webfont.eot?#iefix') format('eot'),
        url('/fonts/my-webfont.svg#myWebFont') format('svg'),
        url('/fonts/my-webfont.woff') format('woff'),
        url('/fonts/my-webfont.ttf') format('truetype');
    font-weight: normal;
    font-style: normal;

Or you can create a separate @font-face rule that applies to Chrome only:

@font-face {
    /* your existing font-face rule here, with SVG last */

@media screen and (-webkit-min-device-pixel-ratio:0) {
  @font-face {
      font-family: 'my-webfont';
      src: url('/fonts/my-webfont.svg#myWebFont') format('svg');

It seems like the second method (Chrome-specific media query) is more widely accepted, and it should (in theory) work with Google Fonts, although you’ll obviously need to host the SVG file yourself.

Convert fonts with Font Squirrel (April 2014)

Since I wrote this up as a comment, I thought I’d include it in the article:

The easiest way to convert your web fonts (including SVG) is to use the Webfont Generator at Font Squirrel. It doesn’t do SVG by default, so you’ll need to switch over to Expert and enable SVG output. Then, you can either edit the order of the @font-face rule or add the Chrome-specific media query as you see fit.

There are lots of free / open fonts out there, so don’t use this tool to infringe!

Update (July 2014)

Supposedly, this issue is resolved with Chrome 37 (now available). I haven’t had the chance to update my Windows machine yet, but we’ll see if this is finally fixed!


These links were very helpful in solving this issue: Fontspring, Adtrak
Here’s the Chromium issue (now resolved): Chromium issue #137692

Nitrous.io : Collaborate in the Cloud

Over the past few months, I’ve been helping some friends learn more about software development, working in Ruby and (eventually) covering most of the web stack. In this post, I’ll talk a little about the tools we’ve used to collaborate online, and about the one we’ve been using most: Nitrous.io.

‘Learn to Code’?

I was playing around with Google Trends the other day, and I discovered something interesting for the terms “learn programming” and “learn to code”.

Look at those spikes!

A Shameful First Post

So there you are, deep in the zone, cranking away on your project. You run your thing, and a minor invocation error causes it to spew 3-byte files all over your working directory.


Well, no problem, that’s what find is for, right?

find . -size 3 | xargs rm

… Right? Wrong. From the man page:

  -size n[cwbkMG]
      File uses n units of space.  The following suffixes can be used:

      ‘b’    for 512-byte blocks (this is the default if no suffix is used)
      ‘c’    for bytes

Of course, this is the case for most *nix and OS X machines. Hope all those 1500-byte files were under version control!

Get to the point!

I’m not here to issue a screed against find — the 512-byte block is a longstanding default, and you can’t always change your public interface — but to make the point: know your tools, and skip the shortcuts.

Sometimes, with technology, we have a tendency to take shortcuts, to act first and think second. One very personally relevant example is piping a find command directly to xargs/rm, rather than checking the output first. Another one is running a command with a wildcard, without first checking the evaluation of that wildcard.

These practices are especially dangerous for sysadmins, but we all can fall prey to the temptation of the easy way.

Other posts

I’ve read a few posts recently that highlight similarly dangerous practices:

Don’t Pipe to your ShellHN thread

This one seems like common sense, but the author’s right: this pattern is simply everywhere. His experiment with netcat leaves out a couple of details (like the fact that most HTTP servers are going to send a Content-Length header), but his point is spot on.

Copy-Paste from Website to TerminalHN thread

This one is especially devious! I think most people’s answer to this will be to copy/paste into an editor. This is all well and good, unless you use vi and the attacker knows it ;)


The shameful part about this first post is that, once upon a time, I knew very well that 512-byte blocks were the default for find. But, because I got so used to specifying a filesize in kilobytes (or more), I let myself get tempted into a shortcut.