views:

206

answers:

4

The section Last links in the chain: Stashing and the reflog in http://ftp.newartisans.com/pub/git.from.bottom.up.pdf recommends stashing often to take snapshots of your work in progress. The author goes as far as recommending that you can use a cron job to stash your work regularly, without having to do a stash manually.

The beauty of stash is that it lets you apply unobtrusive version control to your working process itself: namely, the various stages of your working tree from day to day. You can even use stash on a regular basis if you like, with something like the following snapshot script:

$ cat <<EOF > /usr/local/bin/git-snapshot
#!/bin/sh
git stash && git stash apply
EOF
$ chmod +x $_
$ git snapshot

There’s no reason you couldn’t run this from a cron job every hour, along with running the reflog expire command every week or month.

The problem with this approach is:

  1. If there are no changes to your working copy, the "git stash apply" will cause your last stash to be applied over your working copy.
  2. There could be race conditions between when the cron job executes and the user working on the working copy. For example, "git stash" runs, then the user opens the file, then the script's "git stash apply" is executed.

Does anybody have suggestions for making this automatic stashing work more reliably?

+6  A: 

I certainly wouldn't set up automatic stashing as described in that (otherwise excellent) article, for exactly the reasons you cite.

I prefer to use the stash as it is intended to be used, where I deliberately stash and apply changes as I'm working. For periodic backups, I use a proper backup solution. In my opinion, Git is not a substitute for a backup solution.

Greg Hewgill
+3  A: 

git stash is actually just a little shell script that creates a commit which is not referenced in any branch. You could emulate this behaviour without race conditions:

#!/bin/sh
GIT_DIR=$(git rev-parse --git-dir) || exit
ref_stash=refs/stash

w_commit=$(git stash create) # creates a commit for the wip

# gather some info
head=$(git log --no-color --abbrev-commit --pretty=oneline -n 1 HEAD --)
branch=$(git symbolic-ref -q HEAD)
branch=${branch#refs/heads/}
msg=$(printf 'WIP on %s: %s' "$branch" "$head")

# Make sure the reflog for stash is kept.
: >>"$GIT_DIR/logs/$ref_stash"

git update-ref -m "$msg" $ref_stash $w_commit

The script may need some polishing but I hope you get the idea :)

d0k
The script seems to work and I can see it being useful if you want to save your working changes without reverting back to HEAD. I'm convinced by Greg's response that we shouldn't rely on this for 'backup' purposes though :)
Readonly
+1  A: 

I prefer branch management before stash management: take a look here

Banengusk
A: 

For backing things up I'd recommend online backup service, similar to dropbox.com You literally don't need to do anything, it just tracks all the changes you make during the day for you.

I have it enabled for all my git repositories which just helps me focus on the actual task at hand.

Art