Friday, March 25, 2011

Element in Array with Bash?

I recently found myself editing a rather long conditional evaluation in Bash that was essentially comparing a variable, $color, against several valid matches. If $color didn't match any of them, the condition evaluated to true. I was a little disappointed with the prospect of maintaining it and the stretch of ORs and ==s across my screen. In a "real" scripting language, I would just use an array and check if $color was an element. Then I realized that Bash lets me use an array, just a little differently. With a combination of echo and grep, I got the job done.

declare -a valid_colors=( 'green' 'red' 'blue' )

echo "${valid_colors[@]}" | grep -qv "$color"
if [ $? -eq 0 ]; then
  # Do your stuff

Tuesday, March 8, 2011

Oh Shit! Git Amend Ate My Changes!

Today a developer did a git commit --amend and accidentally overwrote his entire HEAD. (I'm not sure how, but it did happen.) I knew that since git saves (what seems like) everything, if we could find the commit hash for his previous HEAD that we'd be able to cherry-pick it. We scrolled up through his terminal but couldn't find any reference to it =/ So that meant we needed to try finding it the hard way: .git/

So then I started looking through the git-dir and after a little digging, we found therein a log file for each branch (.git/logs/refs/heads/*), the contents of which lists the last several commit hashes made to the branch respectively. Alright! Each file contains a somewhat chronological list of the hashes generated by each change to the tree (rebase, pull, commit, cherry-pick, etc.). We were able to use git show on the hashes near the end of our branch's log file and recover the change!

Conclusion, steps to recover:
  1. git branch -- # e.g. my-feature
  2. tail .git/logs/refs/heads/my-feature
  3. git show $hash # using the hashes from the log file until you find the one you want
So it turns out the easiest way to do this is to use git reflog, which will list all the changes to your HEAD for the past X changes. Way easier!

Monday, March 7, 2011

Bash PS1 Colors and More Space

Below is a script I use for adding some jazz and meta information to my prompt in bash. Although I do use oh-my-zsh now-a-days, a nice Bash prompt is still useful when I am on a server without zshell.

I'm not sure if this is best way to achieve this, but I use `echo` in order to add the color variables in the PS1 string, which should be evaluated only per PS1, not at the time of definition. I originally was using double quotes to surround the entire thing, but then realized that `git_ps1` was getting executed only when PS1 was being defined, instead of when PS1 was being evaluated.

On most systems, you can save this script at /etc/profile.d/ and it will be automatically evaluated. If you do set your PS1 using oh-my-zsh, then whatever value was set here will be overridden.