Friday, July 29, 2022

Your Code is Safely Stored In The Cloud. Right?

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"

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
  root=$(dirname $gdir)
  modified=$(cd $root ; git status -s)
  if [ -n "$modified" ] ; then

  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

  echo "$status $root"

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.

No comments:

Post a Comment