Have you ever wished to have a finer control over your Heroku git repository? There’s a neat little Heroku plugin that gives you just that: heroku-repo.
Around the first release of my current project, things were happening in a frenzy. There were plenty of last minute fixes, and each of them would get built and pushed to our staging instance. On occasions, when people couldn’t wait for the build to finish (wasn’t a particularly long build though), or when the build was a bit flaky, they’d push directly to the Heroku staging repo. At some point, Heroku started rejecting our pushes, because it’s git tree had diverged from ours. It wasn’t nice, but we resorted to doing force pushes to the Heroku git repo from then on.
Once the release frenzy was over, I started investigating the issue. I started by trying to get a local clone of the Heroku repo, to see if I’d find something there, but it kept timing out. I opened a shell on the staging instance and tried searching for a repo somewhere there, but in vain. Heroku doesn’t host the repo from there. I had pretty much decided to blow up the staging app and recreate it, when I found this plugin.
It’s a plugin for the Heroku toolbelt that, in a sense, gives you raw access to the git repo that your Heroku application uses. Using this, I managed to download the git repo locally, which took quite a while because the repo had grown to some insane size (was a few hundred MBs, nearing a GB). Digging into the repo, I found a huge pack file that was causing all the issues. I suspected it to be because of a huge binary accidentally checked in by a team member, but my git-fu isn’t really good enough to say for sure. Running a gc on the repo using the plugin didn’t really help. So, I was still left with having to blow up and recreate the staging app.
I thought it’d be nice if I could just reset the Heroku git repo, and start over instead of having to recreate the app (and then add all the addons to it, which was a bit of a hassle since there were paid addons and I’d have to contact the instance owner to re-enable them). So, to figure out where the repo is hosted and how the plugin manages access it, I went through the plugin source code. Turns out, the repo is hosted on S3, and Heroku toolbelt exposes the S3 URL to it’s plugins. Better yet, the plugin itself had an undocumented command to reset and upload an empty git repo back to S3 🙂
This is pretty amazing. I can now start over with a clean repo in case my Heroku repo is messed up for any reason. On top of that, I can now deploy an entirely new app into my Heroku instance without leaving any dangling commits (not that it’s a common usecase, or even a useful one). See this protip for details: https://coderwall.com/p/okrlzg.
To install the plugin, do:
$ heroku plugins:install https://github.com/lstoll/heroku-repo.git
Here’s a few commands that I found useful:
- Download the Git repo as an archive (useful when you can’t clone from Heroku)
$ heroku repo:download -a appname
- GC the repo (on Heroku)
$ heroku repo:gc -a appname
- Reset the repo and upload an empty repo
$ heroku repo:reset -a appname
The plugin has a few more useful commands. Do check it out on GitHub: https://github.com/lstoll/heroku-repo. Also, I’d recommend going through it’s source code to see how it works. I thought it was pretty neat.