Simple Bash Scripts for Lazy People | Part 1: Git

While the attribution may be hazy, the notion of laziness being an attribute of a good programmer is popular. I don’t know how good of a programmer I am, but I am really lazy.

So lazy that if I find myself doing something over and over, I write a script to do it for me the next time.

xkcd comic with graph of theory versus reality efficiency for automation, where reality winds up working only the automation and the original task never gets completed


This is a five-part series:

  • Part One (what you’re reading!) has examples for common daily tasks in Git.
  • Part Two has similar examples for Rails.
  • Part Three has some miscellaneous cases.
  • Part Four dissects an example of a failed attempt at a useful script.
  • Part Five concludes with a brief discussion of when to use Bash as opposed to some other scripting language. (Spoiler: I’m pro Bash for lots of use cases where many people choose something else.)

Most of the scripts in this series started as one-liners, and the longer ones grew to include more context as I tried to make them more generally applicable.

All of these scripts live in ~/bin (which is in my path, obviously, I’m too lazy not to have tab completion), and lest you forget, need to be chmoded to be executable.

TL;DR for the series:

  • Use one-liners to make something easy to remember for things hard to remember
  • echo -n to not include a newline is useful for prompting user input
  • xargs is your friend!
  • You don’t have to be a Bash or sed or awk magician to make useful scripts; even knowing only one feature of each of these tools gives you a great deal of power
  • basename and dirname are very handy
  • Prefer absolute paths to relative paths
  • Use environment variables to make a script portable
  • Using ssh with -- to pass a string of commands to execute is great for working with remote systems
  • Know how to use SSH keys
  • Be mindful of potential future growth of files or directories you might be searching or greping
  • Use comments (and proofread them!)
  • Get a substring: substr="${string:int_start_pos:int_length}" e.g.:
    $ foo='Hello World!'
    $ echo "${foo:0:1}"
    $ echo "${foo:6:6}"
  • Math!
    $ foo=1
    $ ((foo += 1))
    $ echo "$foo"
    $ bar=20
    $ ((foo = bar + 7))
    $ echo "$foo"
  • awk‘s regex matching is super useful and can make one-liners simpler
  • If your task involves only filesystem and OS-level tasks, Bash is probably a good fit
  • is your friend

The examples in this series assume a solid understanding of Bash basics, such as pipes, exit statuses, redirecting output, line continuation, and so on. If there’s syntax or usage that isn’t clear, please comment, and I’ll make an update to clarify.



I use this one a ton because typing git-o then tab completion is easier than remembering git log --pretty=oneline

git log --pretty=oneline

You could do the same thing by sticking alias git-one-line-log="git log --pretty=oneline" in your .bash_profile, but I have it as a script, I’d like to say for consistency, but really because the idea of doing it as an alias didn’t occur to me at the time.

lazy dog dreaming of 'git-o...'


Beezwax has really mature and standard dev practices, which means that many of our repos have lots of small branches that get automatically deleted once they’re merged. The downside is that your local checkout knows about lots of branches that no longer exist on origin. Enter git-branch-cleanup:

echo -n "main branch [staging] ";
read branch;
if [[ -z "$branch" ]]; then
git checkout "$branch" \
  && git pull \
  && git remote prune origin | grep pruned | sed -e 's/.*origin\/\(.*\)/\1/' | xargs git branch -d

echo -n outputs without a trailing newline, so the prompt looks like this:

$ git-branch-cleanup
main branch [staging] _

and I can hit enter to use the staging default, or type something else.

The input branch is whatever branch you generally merge down to (master — or something else — might be more applicable to your workflow).

The git pull on line 8 is to:

  1. make sure you’re not on one of the branches that might get deleted, and
  2. make sure whatever changes have been merged are pulled locally.

Without that you’d get a lot of:

error: The branch 'mobile-logout-link-position' is not fully merged.
If you are sure you want to delete it, run 'git branch -D mobile-logout-link-position'.

After pulling changes, git remote prune origin does exactly what it sounds like, pruning deleted branches on the remote from your local knowledge of origin. The output of this is greped for “pruned” (the bits from git remote‘s listing of what it’s pruning), and the sed substitution lops off everything from the start of the line through origin/, so all that’s left are the branch names. These are passed as arguments to git branch -d via xargs, and you’re left with nice tidy lists of only active branches.

xargs does way more than what I know to do with it, which is to take lines of standard input and make them into multiple arguments to a single command, but that alone is super powerful.

On to Part Two: Rails

Leave a Reply