A checkpoint tool for your Git working directory. Save your current state, keep working, restore if things go wrong.
git stash isn't quite right for checkpointing:
| git stash | git-snapshot | |
|---|---|---|
| Clears working directory | Yes | No - keeps your changes in place |
| Preserves staged vs unstaged | No - everything becomes unstaged | Yes - restores exact staging state |
| Naming | stash@{0}, stash@{1} |
my-feature.a1b2c3d4 |
| Use case | "Put this aside, do something else" | "Checkpoint this, keep experimenting" |
The workflow git-snapshot enables:
# You're working on a feature, things are looking good
git-snapshot working-nicely
# Keep experimenting...
# Try a risky refactor...
# Oh no, it's broken
# Get back to your checkpoint
git-snapshot restore working-nicely
# Your code is back exactly as it was - staged files still staged"Why not just commit?"
You could, but:
- Sometimes you're not at a commit-worthy point - code works but isn't clean/complete
- Commits are permanent history; snapshots are disposable checkpoints
- You might have carefully staged specific hunks for a future commit - committing now loses that curation
- You want to try something without polluting your branch with "WIP" or "temp" commits
# One-line install
curl -fsSL https://raw.githubusercontent.com/mhm13dev/git-snapshot/main/install.sh | bash
# Or with custom directory
curl -fsSL https://raw.githubusercontent.com/mhm13dev/git-snapshot/main/install.sh | bash -s -- ~/.local/bin
# Or clone and install locally
git clone https://github.com/mhm13dev/git-snapshot.git
cd git-snapshot
./install.shgit-snapshot # snapshot with hash only
git-snapshot my-checkpoint # snapshot with custom name
git-snapshot create my-name # explicit create (if name matches a subcommand)git-snapshot list # snapshots for current repo
git-snapshot list --all # all snapshots (all repos)git-snapshot show my-checkpointOutput:
Snapshot: my-checkpoint.a1b2c3d4
Hash: a1b2c3d4
Name: my-checkpoint
Repo: my-project
Branch: main
Commit: e5f6g7h8
Created: 2026-01-26 14:30:52
Staged files:
src/app.js
Unstaged files:
src/utils.js
Untracked files:
src/new-helper.js
git-snapshot restore my-checkpoint # restore by name
git-snapshot restore a1b2c3d4 # restore by hash
# Selective restore
git-snapshot restore <name> --staged-only # only staged changes
git-snapshot restore <name> --unstaged-only # only unstaged changes
git-snapshot restore <name> --untracked-only # only untracked filesgit-snapshot delete <name> # delete one
git-snapshot delete <name1> <name2> # delete multiple
git-snapshot prune # delete all snapshots for current repogit-snapshot rename old-name new-name
# my-feature.a1b2c3d4.snapshot -> new-name.a1b2c3d4.snapshot- Staged files - full contents of files/hunks you've
git added - Unstaged files - full contents of modifications to tracked files not yet staged
- Untracked files - new files not yet added to git (respects
.gitignore)
Each is stored separately and restored to its original state.
Snapshots are stored in ~/.local/share/git-snapshots/ (XDG-compliant).
File format: name.hash.snapshot (e.g., my-feature.a1b2c3d4.snapshot)
Each .snapshot file is a tarball containing:
metadata.json # snapshot info (repo, branch, commit, timestamp, file lists)
staged/ # full contents of staged files
unstaged/ # full contents of unstaged files
untracked/ # full contents of untracked files
- Always works - stores full file contents, not patches. Restores work even after commits.
- Repo-aware - snapshots are tied to their repository. Cannot accidentally restore to wrong repo.
- Non-destructive - creating a snapshot doesn't touch your working directory.
- Preserves staging - staged files restore as staged, unstaged as unstaged.
MIT