Hardscrabble 🍫

By Max Jacobson

git repl

30 Nov 2014

The other day I mentioned coming upon a neat set of git extensions called ‘git extras’ by TJ Holowaychuk. Since then I’ve become slightly obsessed with it. It’s so useful, including as a terrific learning tool. Take ‘git repl’ as an example.

First of all, what is it?

allow me to answer with a GIF:

vim auto indent gif

In short: if you’re gonna be doing a bunch of git operations in a row, why keep typing git over and over when you can go into a git repl and just let it assume that everything you’re doing is going to be a git command?

It plays well with vim, too – the commit message editor seamlessly pops into vim and then back into the git repl on quit.

So how does it work? I looked at it and assumed that it must be so much code and way beyond my understanding. But that’s totally wrong! It’s just 43 lines of bash and it’s fairly readable.

The really interesting part is read, which has a comment indicating that it’s powered by Readline, which is one of those words that I’ve seen fly around while existing in the world of software, but have never heard defined. Well, here’s the wikipedia page for it: GNU Readline. It was originally written by Brian Fox, who also created bash. Ruby’s various REPLs (eg rails console, irb, pry) are probably using it under the hood via Ruby’s standard Readline library, which makes writing a REPL super simple, while maintaining the behaviors you may be used to. For example, I compulsively press control+l to clear the screen; this works in a readline REPL but not in something like this:

loop do
  print "> "
  input = gets.chomp
  puts input

Filename tab completion works as well! Whoa!

Here’s my first readline program, inspired by the git repl code:

function extensions {
  read -e -r -p "find files with extension: " extension
  find . -name "*.$extension"

Try pasting that into your terminal then entering extensions to run it and to explore your projects. It should prompt you for a file extension (try entering rb in a Ruby project, for example) and then spit out the list of files with that extension in the current directory (and its subdirectories).

Not a particularly great program! I’m mostly just happy to see how simple and demonstrative the git extras code was.


29 Nov 2014

HTTP GET requests are supposed to be idempotent, but they often have the side effect of appending some request details to a log file, which can eventually grow so large that it fills the disk and takes down the server.

git fresh branch

28 Nov 2014

Tonight while clicking around the web I discovered tj/git-extras, a set of useful git tools maintained by TJ Holowaychuk1. Once installed, your git command is overloaded with a bunch of new, useful commands.

It’s easy to install, but it does add quite a lot of stuff, and I was worried for a moment that it would clobber some existing aliases of my own. One, git squash, comes dangerously close to my beloved git squasher, but doesn’t actually conflict.

If you are worried about it, you can safely pick and choose which extras you want by saving individual scripts and just making sure they’re all on your PATH and executable.

The readme explains their purposes nicely, but I want to emphasize one in particular: git fresh-branch <branch name> which does stuff I didn’t know was possible.

Let’s say you’re maintaining an open source library that has existed long enough to accumulate many commits and files. Let’s say you want to create a github page for that library to explain what it’s all about and how to use it. The way github pages works, you should create a new branch in the same repo with the branch name gh-pages, and on that branch you keep a set of assets that will become a static website. But when you create a new branch, it will have all of the code from your open source library, and an entire history of commmits. I can imagine doing something like this:

# create a new branch
git checkout -b gh-pages
# delete all of the existing files
git ls-files | xargs rm
# stage those deletes
git add -A
# commit the change
git commit -m 'BURN IT DOWN'

# create the first version of the site
echo 'hello! use my gem!' > index.html
git add index.html
git commit -m 'gh-pages init'
git push origin gh-pages

And then I’d wait for GitHub to do its magic and expect to see my great page online in a few minutes.

It’s kind of awkward having a ‘BURN IT DOWN’ commit, but I didn’t know there was an alternative. With git extras, that could look more like this:

# create a new branch WITH NO HISTORY AT ALL
git fresh-branch gh-pages

# create the first version of the site
echo 'hello! use my gem!' > index.html
git add index.html
git commit -m 'gh-pages init'
git push origin gh-pages

How the heck does it work? We can look at the fresh-branch script online, but I’ll include the latest version here for reference:



test -z $branch && echo "branch required." 1>&2 && exit 1

git symbolic-ref HEAD refs/heads/$branch
rm .git/index
git clean -fdx

I guess a lot of the work is being done by symbolic-ref.

While researching this post, I noticed that git-extras also offers a gh-pages script that is even more tailored to the use case from my example. Of course! :leaves:

edit: I probably should have slept on this post and actually explored more how it’s working under the hood. But I did not.

  1. Formerly ‘visionmedia’ on GitHub