One of my disaster recovery strategies is to switch my primary work
computer every week. I've got a Mac Mini, Intel Nuc and
Lenovo Laptop in the current rotation. Come Monday morning, I switch
off to a new device for the week. When one of these devices
inevitably fails, I can effortlessly switch to a new device and
continue my work day.
This strategy has worked well for years, but has one primary
annoyance. Back in the day, when most of my projects were Subversion
based, I'd occasionally forget to commit files. Mid-week
I'd discover the missing changes and I'd have to
scramble to find them on another device. It was always a pain.
Git exacerbated the problem by adding a new dimension: it's now
possible to not only forget to commit files, you can commit them and
forget to push them to a remote
server.
A few weeks ago it finally occurred to me that I could program my
way out of this annoyance. Right before I switch away from a device
for the week (typically Friday afternoon, or first thing Monday
morning), I now run these commands:
$ cd ~/dt/i2x/
$ svnassist repo-statuses .
M ./src
$ gitassist -a repo-statuses -n .
S ./i2x-website/src/master
M ./project-notes/src/main
Source code for my projects live in ~/dt/i2x so I use this
as the top level directory to search from.
svnassist looks for subdirectories that contain the
directory .svn. When it finds one, it runs an svn
status on that directory. If changes are found, it prints
out an 'M' next to the repo root to show that it has pending
modifications.
# root=$HOME/dt/i2x -- my project directory
find -L $root -name '.svn' -type d -prune -exec echo {} \; | while read sdir ; do
root=$(dirname $sdir)
modified=$(cd $root ; svn status)
if [ -n "$modified" ] ; then
echo "M $root"
fi
done
gitassist works in a similar fashion, but accounts for the
fact that a git repo can either have local changes that need to be
committed, or committed changes that need to be pushed.
# name=$HOME/dt/i2x -- my project directory
find -L $name -name '.git' -type d -prune -exec echo {} \; | while read gdir ; do
status="_"
root=$(dirname $gdir)
modified=$(cd $root ; git status -s)
if [ -n "$modified" ] ; then
status="M"
fi
if [ -z "$modified" ] ; then
branch=$(cd $root ; git branch --show-current)
stalled=$(cd $root ; git cherry -v origin/$branch 2>&1)
if [ -n "$stalled" ] ; then
status="S"
fi
fi
echo "$status $root"
done
git cherry was the best way I found to see if there were
changes to the local repository that need to be pushed to the
remote.
After running these commands, I've found that it takes just a minute
or two to either discard
the local changes or make them permanent.
Man, is this an improvement over discovering a missing set of changes and
having to scramble to find them.