Posts Tagged - shell

A Rails 7 compatible bin/dev for heroku local

Rails 7 introduced a new bin/dev wrapper to launch and manage your Rails server, CSS watcher, and JS bundler into a single process, managed by foreman. This is quite handy for running everything with a single command. But what if you’re deploying to Heroku and using the Heroku CLI’s heroku local to run things locally? Or if you’re a fan of one of the other tools that manage processes based on your Procfile?

I’ve got you covered!

bin/dev for heroku local

The biggest, and most obvious change is swapping out the executable. Mostly this is to do with heroku local using the :<subcommand> style CLI interface. Let’s compare foreman, heroku local, and bin/dev doing similar things to see how their CLIs differ.

# start the web and css processes
$ foreman start web,css
$ heroku local:start web,css
$ bin/dev web,css

It turns out bin/dev explicitly calls the foreman start command. So a quick heroku local version of the same would be:

Read on →

Verbose Shell Scripts for Future You

Command line tools and shell builtins can offer both a short- and long-form way to specify options. Sometimes these are also called short and long flags, respectively. The upshot is a user experience with two ways to specify the same option. A short and terse way. And a longer, more verbose way.

$ curl -HLsS
# ⬆ is the same as ⬇
$ curl --head --location --silent --show-error

Both ways are useful, neither right nor wrong, and each with their own trade offs to consider.

Why Both?

Meme: Girl shrugging and asking, "Why don't we have both?" Why are there two ways to say the same thing?

It’s a good question. One I’ve asked too. But I’ve not found a definitive answer. Perhaps the truth is lost to history at this point?

From what I can tell, originally (i.e., the early/original *nix flavored OSes) there were only single-character options. At some point multi-character options were added, possibly via GNU.

Along the way the sheer number of options also grew, a lot. Is this a cause and effect relationship, a correlation, or pure happenstance? I don’t know. But today we have A LOT of options, and often multiple ways to express them.

Let’s talk about the trade offs and when to use each style.

Read on →

Git Clean: Delete Already-Merged Branches


To delete local branches which have already been merged into main:

$ git branch --merged main | grep -v "\* main" | xargs -n 1 git branch -d

You can omit the main branch argument to remove local branches which have already been merged into the current HEAD:

$ git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Breaking it down

We start by getting a list of local branches which have already been merged into the current branch (i.e. HEAD)

$ git branch --merged

* main

We then pipe that to grep to match on the "\*" character, inverting that match via -v to get all merged branches sans the current one.

$ git branch --merged | grep -v "\*"


Finally we pipe that list in to xargs so we can strip apart the input and pass it on to a new command. We use -n 1 to ensure at most one argument is taken from the input to be passed to the invocation of the new command. The resulting commands that xargs will invoke are effectively

$ git branch -d add_new_user_gravatar_links
$ git branch -d assign_unique_key_to_uploads
$ git branch -d remember_the_last_activity_per_user
$ git branch -d update_kaminari_to_thread_safe_version

Pulling it all back together, we have

$ git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Deleted branch add_new_user_gravatar_links
Deleted branch assign_unique_key_to_uploads
Deleted branch remember_the_last_activity_per_user
Deleted branch update_kaminari_to_thread_safe_version

And there you have it. Go forth and clean up!

Read on →