I like automating commands that I run often, and one of my favorite command line tools to use when automating scripts involving selection is FZF.
A very common task I do is create PR based on another git branch, or it's more advanced version: create a PR based on a Jira ticket, as I published in a previous post.
Here's a simple example using FZF and Github CLI:
gh pr create --base "$(git branch | fzf)" --draft --title "[DRAFT] Feature XYZ"Cool, right?! In this example the branch I select is likely going to be some integration branch different than my current branch and everything should work fine.
But what happens when I need to use the current branch name in a script? For example, let's say you are trying to push the current branch to a different remote branch1.
Easy! Let's use git branch and pipe it into fzf as before, right?
git push $(git branch | fzf):some-remote-branchNot so fast, cowboy! It's easy to forget that, but git branch is a CLI command
with output intended for humans, not scripts. Let's review again what happens if
we call git branch:
develop
* XYZ-123-smtp-client
ABC-456-shopify-apiIn this example git is trying to be helpful by showing you which branch is the
current one with the * character. Unfortunately, * is also a meaningful
character which is parsed by git as a wildcard 🙀. So if you ran this command
above, and selected the current branch this is going to be the actual command:
git push * XYZ-123-smtp-client:some-remote-branchWhich git then translates to "all local branches":
git push develop ABC-456-shopify-api XYZ-123-smtp-client XYZ-123-smtp-client:some-remote-branchYikes! This means that your local copy of ABC-456-shopify-api,
XYZ-123-smtp-client and develop (stale / with any changes they have over the
remote) will be unintentionally pushed to their default upstream branch as well!
And that's only if you have 2 stale branches locally, what if you have more?!2
The reason I didn't catch this for many years has been because I usually needed to grab the name of another branch.
Thankfully git branch has a --format option that allows returning just the
branch names with no "current" indicator:
git branch --format='%(refname:short)'Next time you use git branch in a script remember to use the --format flag to
avoid a mess!
- Maybe you think this is a contrived example because you can just type your branch name and call it a day. But what if you use this command often and your branch names are by convention long and annoying to type because they contain a ticket number and the ticket title.↩
- You may want to check out this other alias I use to clean remotely deleted branches locally.↩