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
fi

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
UPDATE:
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/prompt.sh 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.