<% Garbled

garbled = Blog.new(:author => 'Ben Hamill')

Vi Improved

I recently started using vim on my Linux machines for development (actually gvim and I just haven’t gotten around to installing it on my Windows partition). I’d tried to learn it some time ago with the understanding that it’s awesome, but it didn’t catch on. I know a lot of smart people who use it and it was always one of those things that I felt would be really valuable for me to learn, but—it was hard.

Well, now it’s easy. @adambair mentioned this blog post by Derek Wyatt. It’s a collection of videos he made introducing you to the most basic commands in vim. Enough to get your feet under you so that further research on your own has something to stick to. They’re awesome.

However, the reason they’re awesome is not just that he takes you step by step through the most important stuff or that he’s lighthearted and friendly-sounding. The awesome part is that he shows you why it is that vim is so raved about. If you try to learn vim thinking that it’s like TextMate or NotePad or something, you won’t get it. And until you get it, there’s very little impetus to get over the learning hump (or through the dip, depending on which way you chart things in your head).

The key to understanding, for me, was realizing this: You should not be spending most of your time with vim in insert mode. You should not be typing and selecting in the sense that Word teaches. You should be doing finds and replaces and yanks. You should be operating on your code with macros. If you’re writing new code, great. You’ll be in insert mode for a while, but even then, you’ll want to invoke something that’ll set up your class structure with maybe some default methods in it or something. And as soon as you’re done, you’ll want to be jumping around by line number, moving to a specific character in a line, replacing a segment of a line with two keystrokes. Really, just the movement possibilities blew my mind. So, go watch the introduction.

Feedback Wanted: Blog Topic

You read my blog, right? I mean—here you are reading it. I’ve been having an internal debate for a while about something, wondering what people who read my blog would think. Then I realized there’s a wonderful way to find out: ask.

So far, Garbled has been mostly about programming stuff. I also do a fair amount of table-top role playing and since I started blogging, some of my ideas on that topic have ended up sounding like they might be worth a blog post. But I don’t really have a role playing blog. In considering whether to post about both topics on Garbled, I’ve got two conflicting things going on:

  1. People say you should pick a topic and stick to it if you want to build readership. By this advice, I should talk only about programming here and find another place to post role playing thoughts.
  2. My thinking about programming and about role playing happen in adjacent or overlapping regions of my mind, so, to me, they are somewhat complimentary. I sort of feel like seeing both those lines of thought paints a (more) complete picture of me as a person.

So what are your thoughts? Would a rare or uncommon post about role playing in general or maybe GURPS in specific be alright? Considering that it would mostly probably be about plot construction and other GM related activities. Or should I stick to programming and programming-adjacent topics? Let me know in the comments.

New Side Project: HeyGoVote

National elections, especially the Presidential elections, get a lot of attention in the US. People talk for months about who might campaign before people even announce their candidacy. There are news stories all over the place covering them. On the other hand, more local elections (for state reps or city councils, etc.) get a lot less coverage (because it’s not CNN’s job, for instance). Right after this most recent Presidential election, I realized that I hadn’t voted at all since the previous Presidential election. In four years, I hadn’t cast a ballot, and I thought I should probably become somewhat more involved in local politics. Or, if not involved, at least aware.

One of the buildings adjacent to the one where I work is a polling location. In Texas, that means I can vote there during early voting. A few months ago, I was cutting through that lobby and saw voting booths set up. “Oh!” I thought to myself, “I wonder what we’re voting on today.” I could have voted right then, but I had no idea what was on the ballot, what the various opinions and angles were, etc. It would have been totally uninformed and random, so I refrained, but I started thinking about how I could be forewarned about elections so I could do my own research.

I could start watching the evening news or following local (or state-level) political blogs or take the local paper. But that’s a lot of overhead which I’ve already decided I don’t want to deal with… and just to get one piece of data. So I thought I’d solve my own problem and the way I’d solve it (and solve it for people other than me, who think in a similar way on this issue) was with Twitter.

The Pitch

My initial concept was that I’d set up an app that would store election dates and just tweet them. I quickly realized that it’s a little more complicated than that. If I just tweet on election day, I’ve just recreated the oh-what-are-we-voting-on-today problem. So I need to give some warning ahead of time. @JonLoyens pointed out that a tweet can be easily missed, so I should use direct messages. The beauty, here, is that I can build a reminder service and not have to manage who wants reminders: It’s all just based on who’s following the twitter account.

So the idea is that you’ll follow @heygovote and it will direct message all its followers to warn that an election is coming up. Simple enough and if you want to opt out, you unfollow. Easy.

Three Rules

I want to keep these three things foremost in my mind while I’m working on this thing:

  • No Bias – I don’t want to help people decide how to vote, or influence their vote in any way. This is just about prodding people enough in advance that they can do their own research.
  • No Data – I don’t want to know who the users are and I don’t want them to have to trust me that I’m not selling information about them to some organization (related to the above, as well). So I don’t want to have to know anything about the user other than their Twitter user name and I don’t even plan on storing that, just asking Twitter who’s following @heygovote.
  • No Bother – I don’t want to hassle people. I want to remind people, not badger them. I also don’t want to have to mess with the thing myself to keep it running; it should be fire-and-forget.

Trouble Scoping

It pretty quickly became evident that I needed to decide who my target was. I’d intended to target “Austin”, but that doesn’t really scale gracefully to the county, state and national levels. After talking to my brother, who works on campaigns and the like, I’ve decided I’m going to target Travis County. That catches most of Austin (more to the point, it catches where I live, since this is solving my problem) and also scales up nicely.

For voting purposes, Texas breaks counties up into voting precincts. All the election dates for all the precincts in a given county are the same, so one tweet (or, rather, direct message) will apply to everyone in Travis County. If, beyond comprehension, this becomes wildly popular and other places want HeyGoVote to cover them, then I’ll deal with that as it occurs. My guess is that how elections are handled will be different enough from state to state that it would mean rebuilding the date-getting machinery for each, uh, constituency, as it were.

Where to Start

I haven’t started coding on anything yet; all work to date has been design thinking and research on how I can get a hold of the information I need. I’ve sent some emails back and forth with the Travis County Tax Office (which decides election dates, oddly enough), who’ve been helpful. They don’t seem to have a handy RSS feed of election dates that I can poll, so I’m still working out that side of things.

I will probably start on the reminder side of the application. If I design the DB schema intelligently, it can be very loosely coupled with the data gathering bit. Depending on how it goes, it also seems like the kind of thing that might make a useful Rails plug-in, too. So I might release that on it’s own.

That being said, I expect to use Rails as the tool set. That might seem like overkill since nothing I’ve described has needed a web interface to it, but I have the idea that, after I get the reminder working, it might be nice to build a tool or two that would help people figure out where their polling location is (for folks who skip early voting), what’s on the ballot for their precinct and things like that. If I can’t find existing, non-partisan tools to link to for this, I might have to build my own.

Expect to hear more about this as I work on it. If you have any suggestions or questions, leave a comment.

The New Breed of Hacker

In light of my last post, I got to thinking some more about old school hackers. Also, at my job, we’ve got some people who’ve been here a long time. One in particular, we’ll call him Steve, is very smart, but… And, see, that’s sort of the thing: I can’t put my finger on it exactly. Steve is blazingly smart. But there’s clearly a difference between he and I that isn’t, I think, just accounted for by the 20 or so (I’m guessing) year difference in our ages.

If I see something I dislike—something that could be better—I really want to see it change. I want to be involved in that change if not driving it. Steve is often watching and present. He’s paying attention mostly and if you ask him a question he’ll have an insightful answer. If someone proposes a change that’s actually a good one and addresses a real problem, etc. etc. he’ll be glad the change is coming. But he never pushes for it. He never starts a conversation (in the wider sense, I mean; he will say hi to you in the hall or whatever) and hardly chimes in unless addressed directly.

And I think Steve fits a sort of archetype. He’s very interested in low-level details (well, actually in almost any kind of technical detail). He seems to be pretty much interested in being left alone and tinkering in his shop to see how things work (to use a light metaphor, here). If something is bad or less than optimal for other programmers around him (and including him), he’ll either ignore it or work around it on his own. His solution wont be general enough to apply to everyone, though and he wouldn’t publicize it. He’s very internally focused. And I associate this stereotype with older programmers or, more accurately, with old school programmers (how long have you been coding, not how long have you been alive).

On the other hand, I think think there’s a newer breed of programmer that’s becoming or has become very common. And I want to be very specific, here: I’m talking about hackers; folks who code because they enjoy it, not those who do it because its their job. People who would code to solve computer-related problems they have at home even if they were a news anchor or a trail guide. This new breed is more externally focused. We want our solutions to problems to be useful to other people. We want to have a conversation and (often) change the way things are done (for what we see as the better). We want powerful abstractions and like to live up away from the metal, generally.

I haven’t cataloged all the differences and, in particular, I’m having a hard time figuring out the attributes for my “new breed” of hacker are. Of course I’m talking about generalizations and stereotypes, here, but I don’t think that’s intrinsically bad. Basically, I get a sense of a certain amount of cohesion in personality type and behavior in these two groups and it struck me as interesting. What do you think, am I drawing a distinction where there is none? Is this distinction useful for anything? Is there some interesting point I’ve missed?

The Happy Hacker

You frequently hear (or I do, anyway) the advice that if you’re unhappy in your coding job, you should scratch your own itch, work on what you love… Work on something you’d be a user for. Because then you don’t have to do a bunch of requirements gathering and get them inevitably wrong, etc. etc. The idea seems to be that if you love the business process, you’ll love working on the code that enacts it. And, well, that’s fine. It seems to make a lot of sense, on the surface. But then I thought about history.

As programmers, we don’t have a lot of it (compare auto workers or, say, masons). History, I mean. But there’s some and in the days of Mel and COBOL Cowboys things were different from what they are now. Today we have all these powerful abstractions and high level languages. Folks (well, not all, but many) consider it to be ideal if you’re basically writing your code in a DSL specific to your business process. Which means your code is really tightly coupled to your business (on that layer, anyway). I don’t know that that’s a bad thing at all (in case I sounded critical). I just want to contrast it to what came before.

Those dudes were almost just writing ones and zeros. They were so far removed from the business processes they were enacting and the folks who were using their stuff that I wonder how much impact it had on them. Would Mel have been any more or less happy writing financial management apps for large companies than solitaire? I kind of think it wouldn’t have mattered to him; he was in it for the code and playing with numbers. He enjoyed all that low-level stuff.

So I wonder, is our (figurative us, here) unhappiness when dealing with business processes we aren’t personally invested in a symptom of all of our awesome high level languages and nice abstractions?

Git Tutorials Suck, A Sucky Git Tutorial

Context… Perhaps Too Much Of It

So I was reading this blog post about learning and explaining because @carl_youngblood tweeted about it. I think Carl’s right: I had a hard time learning git (by which I don’t mean to imply I’m some sort of expert now, but the learning is going easier now).

I think the main problem that I had was this: Having learned Subversion, with it’s central repository, it was a hard abstract thing to understand. And some (I feel many of the ones I read, anyway) of the tutorials out there try to start at the abstract. Little help that did me (see above-linked article. Really, it’s very good). And even ignoring those, I had to read a lot lot lot of the practical ones before things started sinking in.

So I’ve sort of come to understand that, actually, the tutorials don’t suck; learning abstract things just takes time and, at the time, that can be frustrating. So I’m going to offer my own little sucky tutorial, which will focus on the practical aspects and, if you read this and don’t get it, you can follow some links at the end to other articles I found helpful and maybe, after roughly a week, you’ll have your ‘ah-Ha!’ moment and think about how git is just like monads… whatever the heck those are.

A lot of tutorials for git newbies start out explaining the Staging Area with some kind of metaphor so that it seems friendly or, I suspect, out of some subconscious wish to actually obscure it from Subversion converts so that git seems more familiar—more like SVN, which it is not very much like at all. I’m not going to really talk about it much. When we get to the commands that affect it (shortly, here), I’ll explain what they do. You can make the abstraction your self.

I’m intentionally writing this off the top of my head for two reasons: If I have to look up a command, then you might as well read whatever tutorial I looked it up on and if I have to look it up, then I clearly don’t use it all the time and thus, you don’t need to know it to get going on Git.

The Tutorial

I’ve got six sections to this thing with (I hope) at least vaguely descriptive names. They are:
  1. Setup
  2. Initial Commit
  3. SitRep
  4. Staging Area
  5. Remote Repo
  6. Conclusion/Links
Setup

You have a project you just started in a directory called ‘notes’. This isn’t even code, it’s just notes about something that you want to version control and back up. It’s a collection of text files and the directory structure is something like this.

$ pwd
~/notes/
$ ls
contact_info.txt  general.txt  outline.txt

After installing git as appropriate for your operating system, you start out by typing in the command line git init. This will create a directory called .git in notes/. There’s some stuff in there, but for the most part, you can ignore this for now. Suffice to say it’s where git does it’s book-keeping. What you’ve got now is a local git repository or, as the kids say, a “local repo”, but nothing’s in it.

Initial Commit

So you do a git add . (note the trailing period). This will toss everything (that’s what the period means) in notes/ into the staging area (including stuff that’s in directories that’re in directories that’re in notes/ etc.). The repo is still empty. To actual save stuff once it’s been staged, you do like this:

$ git commit -m 'Initial commit.'
[master (root-commit)]: created 7db8343: "Initial commit." 
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 contact_info.txt
 create mode 100644 general.txt
 create mode 100644 outline.txt

The -m option says you’re going to specify your commit message right after. Sometimes, you’ll want to leave a longer message, in which case, you forget the -m and git will automatically fire up a default text editor where you can put in longer stuff. Since a lot of that varies widely from OS to OS, I’m going to skip it and you can read more details on other tutorials (see below). Notice that you get a list of what’s changed (you created 3 new files in the repo) and you get your comment back in the output. Splendid.

SitRep

Now you’ve made your initial commit, and your stuff is in version control. Go into contact_info.txt and add something (doesn’t matter what for these purposes). Imagine you’ve made that change and then walked away and forgotten about it. You can use git status to see what’s new, thusly:

$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   contact_info.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

Using git status is just like a reminder. It doesn’t tell you much, but it can jog your memory about what you’ve already staged or what you changed and didn’t stage or what files you added. To get the real scoop about how a file changed, you use git diff. When you run git diff contact_info.txt the output will vary depending on what you had initially and what you added, but the gist is this: It will show you the changes (all of them) with a + before the line for additions and a – before the line for deletions. Generally, it gives a few lines before and after a change for context.

So let’s add our new contact_info change to the staging area and commit it, yeah? Do git add contact_info.txt and then git commit -m 'Updated contact info' or similar. Whatever comment you write is fine. Note we could’ve used git add . but I wanted to show the single-file syntax.

Staging Area

Now let’s put in some stuff into the outline.txt. Whatever you want. Just some stuff. Save it. But wait! We should also add some stuff to the general notes, just a quick overview at least, so put some stuff in there. We’ll finish the outline changes in a second. This is so much more pressing. Obviously.

Now, it’s good repo etiquette to only commit stuff atomically, which is to say that all the changes have to do with each other. Some people will say that you should only commit stuff that works (code compiles or whatever), but with git that’s less of a concern. I’ll come back to this point. What I’m getting at now is that you started one change and realized another needed to be made before you finished the first one. Now you want to commit only the second one, right? Simple: git add general.txt then git commit -m 'Added overview'. Because you never staged the outline (with your half-way-made changes), it doesn’t get committed. Later, if you need to revert that commit or whatever, you won’t have to worry that something else is mixed in there. Now, go ahead and finish your outline changes, and commit them. You should be able to do it on your own now.

Remote Repo

So, then… we’re version controlling this stuff. What if you want to get at it from another computer or let someone else get at it or… something? Pop on over to Git Hub which is my remote repo host of choice. There are others. Shop around, if you like. After you create an account, you can create a new remote repo called whatever you want. You’ll then be shown a page with some directions. Follow the ones under the heading “Existing Git Repo?”

The git remote add origin git@github.com:<username>/<project>.git command basically tells git where your remote repo is. You can have more than one if you like and, actually, do all sorts of crazy things with naming if you like, but I just want to handle the default, assumed case with this tutorial. One interesting thing: Github gives you two addresses for each repository (other hosts may do the same, I don’t know). The one that starts git@github.com is your read/write address and there’s one that starts git://github.com which is your read-only address. Since this is your own repo, you want to make sure to use the read/write address.

The git push origin master command is what actually moves your commits to the remote repo. This is where I recommend you adhere to the “only stuff that works” doctrine. If this is code, and you’re sharing the repo with your team or whatever, this is where they can get at it, so you don’t want to hand them broken stuff or half-finished ideas or whatever. So only push code that compiles/works. Pushing your code updates the remote repo with all the commits you’ve made since your last push.

The way you (or someone else) gets commits out of a repo is by using git pull. It takes the same arguments as git push. It will pull the commits down and then try to reconcile those changes with any that you’ve made since the last time your local repo was in the same state as the remote repo.

Conclusion/Links

I feel like this has gotten pretty long and I don’t want to put too much information all at once. That should be enough to get you started and, really, just try it out for a while and get comfortable with the basics. Don’t be afraid, if you get something out of whack and realize you’ve done something wrong, to kill your .git directory (which will delete the local repo) and start again from the top. I’ve intentionally left a lot of stuff out (like push/pull and branches and multiple remote repos can get kind of hairy), so here’s some documentation, blog posts and articles that I’ve found helpful. These are in no particular order and some are more advanced than others, so just start clicking and see what you like:

If you want to ask me about git or whatever, feel free to email me or leave something in the comments. Also, if you spot a mistake or something here doesn’t make sense, please let me know. Hope this is helpful to someone.

Version Control Your Computer

I’ve mentioned @carl_youngblood here before. Someone once was trying to buy him something with his name on it. I think it was a key chain. You know the kind, right? However, then didn’t have “Carl” only “Carlos”. So we joked that, one day, he needs to write an operating system and name it CarlOS. Aren’t we funny? I know. I’m sorry. Anyway, the other day, we actually got into some OS discussion that I thought had some interesting enough ideas to post here.

So how many computers do you own and use? I’ve got a desktop at home, a laptop and a machine at work. It’s sort of a bummer to have different stuff or different versions of stuff, or stuff with different preferences on different computers. At least, for me it can really jack up my work flow. Especially if there is some application I use a lot with non-default preferences. Man, that bugs me! Remembering it all, bleh.

One thing Carl’s fantasized about is having a computing environment the same everywhere you go. That’s sort of a mainframe or dumb-workstation idea, which is not new at all. However, what if your whole computer were version controlled? You could branch it (so you don’t have your work apps at home, etc.) and merge changes from one branch to another, if you wanted. You could check out a different branch on one machine and it would feel like you were on another.

Clearly an OS would have to be built from the ground up for this idea. You’d also have to have some kind of provision about storing the non-checked out branches locally. Also cloning the repo would be a hassle at current average (even high speed) connection speeds. But how cool would it be to install, say, Textmate at work and get all your settings right, etc. and then go home and merge that change in (You could merge it from work, I guess and then just pull from home. Whatever.)? You could get diff data (hard to implement, but with metadat not impossible):

1
2
3
4
5
$os diff gaming HEAD
+ Steam
+ Half-Life 2
+ X-Fire
-Textmate

Or whatever. You get the idea. Reverting would making backing up and creating, uh… what does Windows call them? Recovery Points? It would make all that easy and moot. Clearly Linus Torvalds needs to be in on this “project”; he has the experience in both OS design and version controlling that would be invaluable. Not that, you know, Carl or I are actually considering doing anything with this idea. It’s an interesting thought experiment, though.

My Twitter Project: atreply

I use Twitterfox to read and create tweets most of the time. I follow enough people that, when I open my browser for the first time for the day, more than 20 tweets have accumulated and, really, I don’t want to go back and read all 60-odd or whatever that have accumulated overnight. Twenty, I should note, is just what Twitterfox picks up when it first turns on.

Occasionally, I’ll come in and see the last few tweets in a conversation between two people I’m following (I only see @replies by others who are to people I’m also following). If it seems interesting enough, I’ll go back and page through to see what they were talking about, reading in reverse order. Sort of like reading a chat log written by the guys that made Memento. It’s not horrible, but neither is it ideal.

So I had an idea about it and I’ve started work. Twitter tracks what tweet (technically called a “Twitter status”, apparently) any given tweet was a reply to. And, I figured, it would be relatively simple to, given a Twitter status ID, recursively follow the reply chain back and get the whole conversation. Turns out, I was right.

A proof of concept:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
require 'rubygems'
require 'twitter'
 
class Reply
  attr_accessor :text, :author, :in_reply_to, :time, :atreply
  
  def initialize status_id
    status = Twitter::Client.new.status :get, status_id
    
    self.text = status.text
    self.author = if status.user.name then status.user.name else status.user.screen_name end
    self.time = status.created_at
    self.in_reply_to = status.in_reply_to_status_id
    self.atreply = Reply.new self.in_reply_to unless self.in_reply_to.nil?
  end
  
  def each_reply &block
    reply_chain.each do |reply|
      yield reply
    end
  end
  
  def to_s
    self.author + ' - ' + self.time.to_s + "\n" + self.text
  end
  
  protected
  
  def reply_chain
    return [self] unless self.atreply
    
    self.atreply.reply_chain << self
  end
end

This has a dependency on Joshuamiller’s version of twitter4r. My medium-term plan is to make a one-trick-website that will take an ID or twitter URL and give you the replies all pretty-like. Maybe make a bookmarklet for convenience’s sake. I plan on using Rails, even though that’s overkill because I figure it’ll be a good learning experience on that front. Find it on Github.

A Hub for Gits

I’ve recently started using git to version control my personal projects. I’ve also recently started using GitHub for hosting remote repos of that stuff. So I’m new to it all and I might be wrong, here. But, having read a few articles here and there and talked to some other people (most notably, another git newbie @carl_youngblood), aren’t cherry picking and rebasing really, really horrible things to do to a repo? Even if it’s just your local one? They destroy history, which is sort of the point of version control, no?

I’ve seen, in the last few days, two articles on GitHub that make me wonder which of us (me or GitHub) doesn’t get it. My inclination is to assume it’s me who’s missing something. If so, I’d love for someone to tell me exactly where I’ve missed a step.

The first article I want to talk about is the Fork Queue announcement. It’s basically a tool that makes it really easy to see which of the people that’ve forked your project have pushed commits you don’t have in your repo and then to cherry pick them in. You can pick your branch, etc. This is to keep you from having to create a lot of remotes, I guess. It’s supposed to “[allow] you to do a email patch style workflow without actually having to deal with patches over email”. I thought that part of the point was that that work-flow was a pain? I also feel like it’s missing the part where the person making the patch tells you about it, rather than you going and getting it from them. A pull-request is much more like that.

I don’t know… I sort of feel like we should be putting roadblocks in the way of cherry picking; make it harder for people to adopt work-flows where cherry-picking is common. My understanding (and again let me stress that this may be incorrect) is that the best work-flow is for the patcher to fetch your code (because it represents some kind of “core” or “official” release, yes?), merge it into a new branch, make his(her, etc.) changes, test them, fetch your code again to make sure he has the latest, perhaps retest, then issue a pull request. When you’re acting on the pull request, you fetch his stuff down to a new branch, test, possibly merge in any changes you’ve made to master since he issued the pull request, then merge into master. This preserves all the history. It’s all fetches and merges.

So the other article is the Changing Git History article. This one is about going and messing with old commits. I’ll try not to rant as much on this one. I’m not as adamant, but I do find it kind of silly, this idea of making a commit a perfect little gem. I can see fixing a typo in the commit you just made, so git commit --amend doesn’t seem so bad. However, the git rebase -i portion after that… bleh. I realize this isn’t a GitHub feature like the above; it’s a part of Git, but I wonder why. If the commits were that horrible, revert them all and do it over. If they weren’t that bad, just live with the typo. No? Even if you haven’t pushed it, rebasing just seem icky and to be avoided, especially if it’s just to fix commit messages.

Okay… So, maybe I’m out of line or off base or insane. It’s entirely possible. Some would say probable. It wouldn’t surprise me if I’ve failed in some very basic way to understand the Git philosophy. It also might be that I’ve misunderstood what GitHub’s written and that the clash between these articles and Git philosophy is all imagined by me. I’m open to these possible realities. Correct me or soliloquize or slam me in the comments, if you like. I am all ears… or eyes. Whatever.

Update: Before anyone gets the wrong idea, here… I’ve been loving using git and GitHub. They’re both spectacular. Without them, I wouldn’t have found enki for use in powering this blog. This post is about trying to understand something confusing in something great; I’m not trying to imply that either should be done away with or that I could do better. I just wanted to head off the most major take-it-the-wrong-way that occurred to me on the way in this morning.