Posts categorized as "tips"

Tell your PR reviewers they're wrong

Have you ever submitted a Pull Request and had the maintainer give you feedback that says something is wrong? This is of course, perfectly natural, and is why we do Pull Request reviews in the first place. But have you ever thought it was actually the maintainer doing the review who was wrong?

I'm the maintainer of a number of open source/free software projects and I have a message for you: tell this to the maintainer, even if you're new, even if you feel like you have no idea what you're doing.

I'm sure to some people more experienced this sounds like obvious advice, but when you're new to this stuff getting feedback can be really scary. Maintainers have often spent years in the free software community and are super comfortable with how things work, not to mention that they might be more experienced in the language or framework their project uses. So it's super easy to just take their word as gospel. But I think it's super important to remember that everyone's human just like everyone else, and everyone has something to learn.

As a concrete example, take this comment on a Pull Request I received. If you read it and the following comment, I seem like an expert on eval(), but what you don't see until you read all the way to the bottom is that I spent about 20 minutes composing that comment because I had to double-check MDN to make sure I was actually correct. And honestly, that was great. That Pull Request forced me to recheck what I thought about the way eval() worked, and the contributor learned from it too! So it ended up being a win-win. Even if I was wrong, that would have been great too, since I would've learned something new. Sometimes the thing being discussed is just a really tough or confusing problem, and getting feedback on a PR can be a really awesome chance for both you and the maintainer to collaborate more closely and figure it out together!

I'm sure this won't work in every community. But honestly, if it doesn't, the maintainer you're running into is probably an ass and not worth bothering with anyway. This is what doing things in the open is all about - freedom 1, after all, is "the freedom to study the source code and make changes", the operative word being "study". The fact that knowledge is shared out in the open with anyone who wants it is one of the most amazing parts of this community, and I want to encourage you to stay curious and ask lots of questions.

So if you've ever walked away from a Pull Request review feeling like something wasn't quite right, consider this your permission slip to politely tell your reviewer you think they're wrong[1] - just make sure to be polite and explain why you think so! And remember, whatever they say, they're not criticizing you personally. I hope you embrace it as an opportunity to grow.


[1]: Phrasing this as "I think you're wrong" instead of "you're wrong" is great for a lot of reasons, but one notable and less obvious one is that if the maintainer does end up being right, you won't feel silly.

Edited to clarify that I'm not advocating inpoliteness, to change the phrasing to "I think you're wrong", and to add some nice framing around a chance to collaborate on a difficult problem. Thanks to the Recurse Center folks whose feedback turned into these changes, particularly Sumana Harihareswara and Julia Evans.

How I passed 2k GitHub contributions

So the other day I logged into GitHub and saw something crazy:

Screenshot of my GitHub contribution graph showing 2,054 contributions over the past year

How in the hell did I end up with that many contributions? Well, I think I know why - it happened because of a couple related, small habits I have. I thought I'd share them with everyone else as a sort of trivia - maybe you can adopt these habits too! (Although hopefully because you think they're good ideas, not because you just want to make yourself look cool on GitHub.)

Fix typos

If projects are freedom-respecting, that means that anyone is welcome to contribute if they're able to offer something valuable. How many times have you seen a typo in some docs? GitHub makes it super, super easy to fix these (just click the pencil icon in the upper-right of GitHub file views), and they're a fantastic way to contribute a little back to projects. Even if you aren't reading docs on GitHub, it often doesn't take that much time to find where they're hosted (which is frequently GitHub anyway). Really good docs will even have a link to their source right on the generated page.

So whenever I see a typo, I send a Pull Request. It's become an automatic response to seeing something that needs fixing, and is pretty routine for me nowadays.

Oftentimes there are changes that aren't as easy as a typo, but are still super easy to fix. Take this Homebrew PR - I authored it on a tablet and it took me under 3 minutes to make the suggested change[1]. That's not a lot of effort, and it'll help lots of people looking for the Homebrew change log. The next time you find yourself thinking "it kinda sucks that..." ask yourself - can I fix this myself? And if you can, go for it! Even if you screw up, I promise most projects will want to help you out instead of making fun of you[2] - as someone who runs several freedom-respecting projects, I know that getting new contributors is very, very valuable and because of that I'll do a lot to make contributing a good experience. I would encourage everyone to, as Mike McQuaid puts it in that Homebrew PR, "be the change you want to see in the world."

[1]: of course, that's partly because I'm pretty good at git and grok things like rebase -i. But even if that's not you and it would take you longer, it sounds like a great opportunity to improve your git skills to me!

[2]: I feel obligated to point out that not every project is like this - there are some projects that have a terrible culture (*coughcough*Linuxkernel*cough*). Screw them. They're not that common in my experience and it's their loss, anyway. Don't let them deter you from trying to improve things outside of their bubble of suck.

File issues

I just talked about making small changes whenever you see something you can improve with a couple minutes' time. But what if you're in a hurry, or it would take longer?

Filing issues is a super easy way to solve this. Get into the habit of filing issues for everything that irks you[3] - you're not allowed to say "such-and-such a project sucks because it's buggy!" when you haven't told the developers about the bug you're experiencing!

Filing issues also takes very little time and is super helpful to the developer. Probably a lot of the people who read this blog are software developers, so I'm betting you can understand how great it is to receive an issue that gives you lots of details that you can then use to fix a bug or a design problem. So why not give the gift of issues? Just make sure to search for duplicates! (This accounts for a significant amount of those 2,000 contributions on my GitHub profile. Over the course of my time on GitHub, I've filed 619 issues, 438 of which were on other people's projects. Of course, that's just on GitHub - I also do this frequently outside of GitHub.)

Again, every time you find yourself saying, "why doesn't it..." or "I wish it..." or "it's so annoying when...", let the developer know! You'll help them make their project better.

[3]: this is not to suggest that you file ridiculous issues that don't really say anything or just complain. But a focused bug report describing something concrete that's problematic is awesome.

Publish by default

This is the last and biggest habit I have that I think led to those 2k contributions: I publish everything by default, no matter what. It doesn't matter how bad or hacky or ugly I think a software project is, I just publish it. Because honestly, why not?

Keeping projects public doesn't get in anyone's way. It's not like someone will look at your GitHub and be annoyed that you give so much software to the world. And there's even a chance that your hacky script may actually be useful to someone. Even if I think a project is "bad" I'll still publish it because the reality is that no one is going to go around GitHub specifically trying to find people to make fun of.

Publishing projects also gives me incentive to clean them up - write a README, write tests, and keep a change log (if relevant). My standards are higher because I know all my work is all in the open - not because I'm afraid of other people telling me I'm doing it wrong, but because I want to create high quality code that has a better chance of being useful to the wider community.

In summary

All of these habits are related. The tl;dr is this: engage by default. Get used to being involved instead of shrugging off a problem and moving on. Put your work out there for other people to see. The open source/freedom-respcting software community belongs to everyone - and that means we can all contribute to improving it. We just have to start.

Getting started with version-controlled configurations

Hey everyone, welcome to the inaugural Unix & Linux community blog post. Let’s get started.


If you’re like me, you work on many different kinds of computers. I have two Darwin machines that I regularly work on; I have about four different installs of Arch GNU/Linux, and I am planning to add even more esoteric distributions to one of my boxes. I work in Cygwin. And I have a Debian Sid box, which needs to be converted to something else.

My point is not that I like distribution-hopping. My point is that many of us use very diverse environments, and even if we don’t use very diverse environments, we all have a lot of environments that we work in. I’m also guessing that most of us here have at least some basic configurations accumulated, and many of us have extremely tricked-out shells. Wouldn’t it be nice if there was a coherent way to manage all of your configurations?

Enter version control. Not only can you use version control to synchronize your configurations between computers, but you’ll also inherit all the other benefits of (hosted) version control:

  • A nice history of everything you’ve ever done to your configurations – and if you write good, proper commit messages, a nice history of why you made those changes!
  • The ability to link to your configuration when you’re asking for help, so that people can see the overall context of the snippets that you post
  • Nice ways to track subprojects (e.g. frameworks like oh-my-zsh)
  • Show off your stuff way more easily

In this post, I’ll show you how to recreate the exact setup that I use to control my configurations. I prefer to use git, but you should be able to adapt most (if not all) of this guide to your preferred VCS. The only reason you might run into trouble is if your VCS has no equivalent of git submodules.

The initial import

First, create your repository online. The details will, of course, vary depending on what VCS host you use. Personally, I use GitHub, but again, anything will work.

Next, we need to import all our stuff to the repository. First create a local clone.

git clone

If you don’t like whatever name you chose for the repository, you should rename it now, before you do anything else.

mv dots configs

Now, copy all the configs that you like into the repository.

cp .z* configs/ # copies all the zsh stuff

Take care to ensure that you create the directory structure properly and safely. For example, the following is a terrible idea:

cp -r .gnupg configs/

If you do this, you may accidentally commit .gnupg/secring.gpg into git! This is obviously something that you don’t want to do. Instead, do this:

mkdir configs/.gnupg
cp .gnupg/gpg.conf configs/.gnupg/

Another thing that you should definitely watch out for is the .ssh directory, but you may have other tools that store secret data next to config files. Just be smart.

That’s it! We’re done importing. Now let’s commit.

cd configs
git status # double-check what you're commiting
git commit -m "Initial commit"
git push

We’re done. Your configuration is live on the internet. There’s just one problem…

Hooking up your configurations

…and that is that all of your real configurations are separate from your version controlled configurations! If you make changes in one, it won’t do anything to the other.

When I was originally setting all this up for myself, I put my configurations straight into ~. This is a horrible idea for two reasons:

  • Every directory that’s a child of your home, indirect or direct, will be considered a part of a git repository, because a parent of that directory (said parent being ~) has a .git directory.
  • You either risk accidentally introducing tons of crap from your home directory into your repository, or you have to maintain a large and ugly .gitignore.

The solution that I now use is simply symlinking all my configurations into ~ (or wherever). If you find that this approach incurs too much overhead, you may want to look into a framework to do this for you, as I mention in the “taking it further” section. That being said, I’d encourage you to try simply symlinking, at least at first. It’s surprisingly robust.

Anyway, creating your symlinks is dead-simple. Watch out for things that fail (you’ll want to remember them; if you’re feeling especially forgetful, redirect stderr to a file or something).

cd ~
ln -s configs/.* configs/* .

This will symlink everything that’s in configs/ into your home directory. This is probably not exactly what you want, so let’s do some cleanup:

# pwd is still ~
rm .git # if you don't remove this, git will think that ~ is a repository!
rm COPYING # license information that doesn't need to be in your home directory

Notice that we haven’t removed .ssh and .gnupg. Why? These (probably) didn’t get symlinked when you ran ln because they’re (probably) already there. You’ll have to fix these manually, along with anything else that failed when you ran ln.

ln -s configs/.gnupg/gpg.conf .gnupg/
ln -s configs/.ssh/config .ssh/
# you'll have a fair amount of stuff in .config; anything that respects XDG_CONFIG_HOME puts stuff there
ln -s configs/.config/awesome/ .config/awesome

All done! You’re now managing your configurations with git.

Adding a framework

If you’re like me, you use a framework, like the excellent oh-my-zsh, or something like liquidprompt, or whatever other whizzbang what-have-you project you have a preference for. What you’ve probably done right now is simply copied the directory of your framework straight into your repository. This means that whenever your framework updates, you have to commit all the new stuff into your repo. Not only that, but when you clone to a new computer, you have to do some black magic to restore the “repository state” on the new computer, because git automatically ignores any .git directory that isn’t a direct child of the root of your current repository. (It all gets very confusing to talk about at this point.)

The solution is to use git submodules. If you’ve never used git submodules before, I’d encourage you to read up on them, either by invoking man git-submodule or by reading the relevant page of Pro Git. I won’t go into details here, since it would just be duplicating information, but the tl;dr is that git submodules let you embed another git repository into your main repository, but in the Right Way(tm).

Let’s take my old .oh-my-zsh setup and fix it to use git submodules.

First, we simply get rid of the old stuff.

# pwd is ~
cd configs/
rm -r .oh-my-zsh

Then we add it back as a git submodule:

git submodule add git:// .oh-my-zsh

And then we commit the result into the repository:

git add .gitmodules .oh-my-zsh
git commit

And you’re done! Just push.

Oh your other computers, you’ll have to initialize the submodule after you pull. This is also super easy. Just run:

git submodule init # only needs to be run the first time
git submodule update

Taking it further

There are a number of things that you can do (one of which you should do) to take your version-controlled configurations to the next level.

License your stuff (this is the thing that you should do)

Your configurations are now public and usable by other people. That means that you should add a license, otherwise people aren’t legally allowed ot reuse your stuff. At risk of starting a flame war, I’ll state that my personal preference for small projects like this is the WTFPL.

Please, please do this. The public thanks you.

Getting something to manage it for you

There’s a bunch of stuff in our new setup that you need to run manually. You need to pull. If there are new files, you need to link them. If there are submodule updates, you need to run git submodule update. Wouldn’t it be nice if something could do all this for you?

There are a bunch of solutions to this problem. Some people write makefiles. Some people write shell scripts. Some people use a real framework. It’s all up to you.

Personally, I used this problem as an excuse to learn to use make. With the Makefile that I’m in the process of writing, I can pull, update my submodules, and reinstall all my symlinks, all with a simple invocation of

cd configs/

However, like I said, it’s all up to you. If you prefer to use a framework, you should check out Zach Holman’s dotfiles (he has a Rakefile that helps you manage this stuff), Homesick (which is an even more organized framework), Ben Alman’s dotfiles (which has a more casual, loose organization), Eduardo Lundgren’s dotfiles (which has a Grunt-powered configuration tool), ghar, and vcsh (this may be especially interesting if you just hate the fact that you have to have a separate directory for your config repo). fresh is also pretty neat – it’s like a package manager for dotfiles.

While I haven’t used any of these myself, they’re all excellent projects.

Further reading is an excellent resource for all this stuff (and, in fact, it’s where I pulled the above list of frameworks from). You may also be interested in a list of all dotfiles repositories on GitHub, sorted by popularity. is also a place where people share dotfiles, albeit in a much less organized fashion. I’ve never used it myself, but I’d encourage you to try it out.


git is awesome. Configurations are awesome. Sketchy rsync scripts aren’t the best when you could have organization (and history!) instead.

Good luck and have fun! Let me know in the comments if you run into problems, find new resources, or have anything else to say. (Flames to /dev/null, but constructive criticism welcomed.)

Thanks to @terdon for editing this post prior to publication.