No description, website, or topics provided.
Switch branches/tags
Nothing to show
Pull request Compare This branch is 4 commits ahead of nothingmuch:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
README.markdown

README.markdown

git snapshot

This command is provides a snapshotting mechanism for refs/workdirs.

Synopsis

Routinely run git snapshot to save undo points:

% vim quxx.txt
% git snapshot
# ...
% git add . && git commit -am "new commit"
% git snapshot

Later, if you need to recall any recorded information:

% git log refs/snapshots/HEAD
% git log refs/snapshots/refs/heads/master
% git checkout refs/snapshots/refs/heads/master:quxx.txt

Rationale

Often times I find myself sketching out projects without wanting to actually record a revision history yet.

Even though the history has no organizational value I could run:

git add . && git commit -m "$(date)"

every once in a while in order to record an edit history, sort of like an on-disk undo log.

git snapshot provides something less messy than this ad-hoc approach, and safer than simply not recording anything at all.

Behavior

When invoked git snapshot will run git snapshot-ref HEAD, and if HEAD is a symbolic ref, also git snapshot-ref refs/heads/master or whatever HEAD is referring to.

git-snapshot-ref starts by running git snapshot-tree, which reads the current working tree into a temporary Git index file, uses git write-tree to record that data in the object database, and prints the sha1 of the recorded tree.

git-snapshot-ref then checks if the previous snapshot (recorded in refs/snapshots/$source_ref, i.e. refs/snapshots/HEAD, refs/snapshots/refs/heads/master, ...) is up to date. If the tree has changed or new commits have been made on the ref, then a new commit is recorded into the snapshots ref.

If you're working on a large patch, you can also snapshot an explicit ref:

git snapshot-ref topic_branch

Once you've created your commits, and then squashed and merged them you can: delete the snapshot log for that branch:

git update-ref -d refs/snapshots/topic_branch

Usage

By routinely running git snapshot (for instance from within a crontab) you get a fully versioned history that is somewhat similar in usefulness to git reflog; if you made a mistake in recording your changes, or if you accidentally modified a file before comitting it, you can recall a previous version from the snapshot history:

git log refs/snapshots/...
git checkout refs/snapshots/...:the/file/i/want.txt

With Spotlight

On MacOS X you can use the Finder's Get Info dialogue to add a spotlight comment or a label to project directories.

Then you can use one of the following commands in your crontab to automatically snapshot it:

# snapshot every directory with 'git-snapshot' in its comment
mdfind -0 "kMDItemFinderComment == '*git-snapshot*'" | xargs -0 -n 1 git-snapshot

# snapshot every directory under ~/code that has the red label
mdfind -0 -onlyin ~/code "kMDItemFSLabel == 6" | xargs -0 -n 1 git-snapshot

With Inotify

On Linux, just run git snapshot-watch in the directory you want to keep snapshots of. Every time you make a change to your project, it will automatically be snapshotted. When you don't want this to happen anymore, just Control-C the process.

See Also

  • git help rev-parse for specifying time based revisions (e.g. refs/snapshots/HEAD@{yesterday})
  • git commit --amend in conjuction with git reflog can provide a similar safety net.