Blog5 min read
+Your agent ran git reset --hard. Here is how to get your work back.
+Git can bring back commits. It cannot bring back work you never committed. A save point made just before the command can.
+The Time Machine team
+An agent is tidying up a messy branch and decides the quickest way out is git reset --hard. The command runs, your files now match the last commit, and an hour of changes you had not committed yet are gone.
This post covers what that command throws away, why Git's own way back does not reach it, and how to get it back with Time Machine, step by step.
+ +What git reset --hard throws away
+Git's documentation describes --hard like this: "Overwrite all files and directories with the version from <commit>, and may overwrite untracked files. Tracked files not in <commit> are removed so that the working tree matches <commit>. Update the index to match the new HEAD, so nothing will be staged."
In plain terms:
+-
+
- every change to a tracked file that you had not committed is replaced by the committed version +
- tracked files that are not in that commit are deleted +
- files Git does not track are not the target, but the documentation warns they may be overwritten too +
- nothing stays staged +
The reflog does not help with the first point. Git's documentation says reflogs "record when the tips of branches and other references were updated in the local repository." That makes the reflog a good way back to a commit the reset moved away from. Work you never committed was never at the tip of any branch, so the reflog has no entry for it.
+ +What Time Machine does before the command runs
+With the Claude Code hooks installed, through the Time Machine plugin or tm hook install, Claude Code asks Time Machine about every shell command before the agent's Bash tool runs it. If the command is on Time Machine's list of risky commands, it saves a save point first.
That list includes git reset --hard, git clean -f, git checkout ., git restore, git stash drop, git branch -D, git rebase, git push --force, rm -rf, DROP TABLE and a few others.
A save point holds your code, including uncommitted changes to tracked files, and files not in Git yet, unless your .gitignore skips them. That is the part a reset throws away. Each save point is a Git commit pinned at refs/tm/ and a Git bundle in ~/.timemachine, outside your project.
When it saves, Claude Code shows you one line:
+Time Machine saved cp-0007 before git reset --hard.+
The cp-0007 part is the save point's ID. The command is shown as the agent wrote it, clipped to about 60 characters, or as "a risky command" when it holds a secret. If nothing changed since the last save point, Time Machine does not save again and shows nothing, because the newest save point already holds those files.
Getting your work back
+1. Find the save point.
+$ tm timeline
+This lists your save points, newest first. The one the hook made has the note "Before risky command:" followed by the command. Its verdict will usually say "not checked", because the hook saves before the command and does not run your check.
+2. See what the reset threw away. tm diff compares 2 save points, so save the state you are in now, then compare. Say the new one is cp-0008:
$ tm checkpoint -m "after the reset" +$ tm diff cp-0007 cp-0008+
Each code line is a file that differs between the two, marked with Git's letters A, M and D. Saved files not in Git are marked +, - and ~.
3. Recover.
+$ tm recover cp-0007
+This saves your current state first. Then it puts cp-0007 on a new branch, tm/recover/cp-0007, with a recovery copy of the project next to your folder. Your folder and your current branch are not touched. Nothing is pushed, merged or deployed. The report ends with the steps left for you, such as setting secret values again.
Open the recovery copy, check that your work is there, and commit what you want to keep. If you picked the wrong save point, tm recover --undo cp-0007 removes the branch and the copy, as long as neither has changed.
If you only need 1 or 2 files, tm restore cp-0007 -- src/app.js puts them back into your folder instead. It saves your folder first, deletes nothing and commits nothing.
What it cannot do
+-
+
- It has to be set up before the command runs. The hooks act only in a project where you ran
tm initon this computer, and only once they are installed. Nothing can save a state after it is gone.
+ - The hook sees commands the agent runs through Claude Code's Bash tool. A
git reset --hardyou type in your own terminal does not go through it.
+ - It matches a list of commands. A destructive command that is not on the list gets no save point first. Then your newest save point may be the one from before your last prompt, and the agent's work since then is not in it. +
- Secret values are never saved. Time Machine keeps the key names from files like
.env, and a recovery lists each one to set again by hand.
+ - Databases, deployed versions and external services are not captured. +
- Files your
.gitignoreskips, installed dependencies likenode_modules, symbolic links and files over 5 MB (the default limit) are not saved. Lockfiles are, so an install brings dependencies back.
+ - On a Git older than 2.36 the hooks save nothing. +
The short version
+The reflog brings back commits. It cannot bring back work you never committed. If your agent can run git reset --hard, set up the hooks before it does. When you see "Time Machine saved cp-0007 before git reset --hard.", your work is in cp-0007, and tm recover cp-0007 brings it back on its own branch.