Bash newbie starts to learn his shell for git and profit

Since I’ve started using git I do a lot more work in the bash console for Windows it installs with, and recently I’ve been trying to lean a bit more on bash to make my life easier. Here’s a couple of basic commands to help use git (et al.) from the command line. It will all be old news for people that have used bash in anger before, but it might help those who, like me, have not yet found the time to really start trying to learn it.

Find

One problem I’ve had is specifying files to pass to git commands when they’re defined somewhere deep within my solution’s folder structure. One option is to use the find command for this:

git gui blame `find . -name MyFile.cs`

This will evaluate find . -name MyFile.cs, which will recursively search from the current path for a file with that name (use -iname for case-insensitive matching). Assuming there is only one match, this works great. If we want to keep operating on that file we can store it in a variable:

f=`find . -name MyFile.cs`
echo $f #check which files we matched. Good idea before destructive cmds ;)
git annotate $f
git gui blame $f

Loops and filtering

If we want to match multiple files, we can iterate over the output of find:

for match in `find . -name *File.cs`; do git gui blame $match; done

# Same thing, but in multiple steps and expanding the loop over multiple lines
# to show what's happening:
$matches=`find . -name *File.cs`
for match in $matches
do 
    git gui blame $match
done

We can also do filtering within this loop. The following example deletes all WIP branches: (use with caution!):

for b in `git branch`; do if [[ $b == WIP* ]]; then git branch -D $b; fi; done

xargs

I always struggle to remember the loop syntax, and it’s not exactly aesthetically pleasing. There is another option: xargs. Xargs is used to build-up lists of argument and execute commands using those arguments. Say we want to delete all our WIP branches again (again: this deletes stuff! Use with caution!):

git branch | grep 'WIP' | xargs -n1 git branch -D

Here we pipe the output of git branch through grep and just pick the branches that contain ‘WIP’. We then pipe this into xargs. The -n1 option tells xargs to execute our git branch -D command once for each argument received (we could pass 3 args into the command using -n3, so the command would execute once for every 3 args). This is a more functional approach, and starts to show the strength of the Unix philosophy of composing many small utilities that all do their jobs well.

I’m only just beginning to get to grips with xargs, but if you read through Things you (probably) didn’t know about xargs and xargs: How to control and use command line arguments you should get more of an idea of what it can do.

Get to know your shell

I recall The Pragmatic Programmer advising to learn a shell really well to help you get more productive. While I’ve only just started looking at this, the more I look the more doors seem to open for automation and getting trivial little operations done more quickly (and importantly, without causing much of a mental context switch from what you are currently working on). Whether you use bash, zsh, PowerShell or even lowly old cmd, I’d really recommend getting better acquainted with what your shell has to offer.

Comments