Is there something like `git reset --hard --dry-run`?

438 Views Asked by At

As I know that git reset --hard can potentially cause unwanted data loss because it may make changes that cannot be undone, is there a way to check what it would do before I execute it? Basically I'm looking for something that would be logically

git reset --hard --dry-run

or

git reset --hard --verbose --dry-run

which unfortunately do not work with currently existing Git because reset doesn't support --dry-run.

4

There are 4 best solutions below

0
On

git reset --hard doesn't have dry run mode but this should get you close to the same information:

#!/bin/bash
echo "Changes that would be executed to working directory files:"
git diff -R HEAD
echo "Staged changes that would be lost:"
git diff --cached --stat

or as a single-liner:

git diff -R HEAD && git diff --cached --stat
2
On

Since you seem to be looking for an option you can avoid data loss with, let me present you with a different option.

git stash allows you to check out HEAD while saving them to the stash. You can then undo it with git stash pop.

So, instead of git reset --hard, you can do git stash and it will mostly have the same result. If you don't like the changes, you can undo it with git stash pop or if you are fine with it, you can delete the changes from the stash (which is a destructive action) using git stash drop.

If you also want to include untracked files (which git reset --hard doesn't do by default), you can use git stash --include-untracked.

If you don't want to reset to HEAD (i.e. you want to do git reset --hard some_ref), you can first stash the local changes, get the current commit hash using git show-ref and then run the git reset --hard. If in doubt, you can reset to the commit again (uness you run git gc or something like that which cleans up dangling references). However, at that point, you might want to create a branch or a tag as a backup as well.

# Stash your local changes
git stash # add --include-untracked if you want to stash untracked files as well
# get the current commit hash AND SAVE IT somewhere
git show-ref # this will output the commit hash of HEAD
# reset to some ref
git reset --hard some-ref
# In case you want to undo it, reset to the commit hash from git show-ref again and load the local changes from the stash again
git reset --hard YOUR_HASH_FROM_SHOW_REF # replace YOUR_HASH_FROM_SHOW_REF with the hash from git show-ref
git stash pop

In any way, I would recommend you to create a copy of the repository including all changes that are important (just copy the entire directory) in case something goes wrong, especially if you are unsure about the commands.

Also note that git stash allows you to stash your local changes, check out or reset another ref and then apply these changes back on the newly checked out/resetted ref.

2
On

I would dispute the premise of the question. I hard reset nimbly and freely all day long and I don't risk anything. If everything is nicely tucked into bed in a commit, hard reset is perfectly safe and undoable (especially if you make a placeholder branch first). So it's just a matter of making sure that everything is tucked in. git status will tell you that.

Also, consider git switch --det as an alternative. It does much the same thing as a hard reset but it has safety checks built in. You can always switch first and move the branch name later. Again, I do this a lot.

Finally, I should just add that I have an alias that lets me say git snapshot to make assurance double sure:

snapshot = !git stash push --include-untracked --message \"snapshot: $(date)\" && git stash apply \"stash@{0}\" --index

If you snapshot first, the next move is safe, because you can always get back to the commit you were on and apply the stash.

1
On

To just see what effects git reset --hard has, you could create a backup of your branch and restore to it should you not be happy:

git branch backup 
git reset --hard <commitid>

If you are not happy at this point, restore the backup:

git reset --hard backup

Otherwise remove the backup

git branch -D backup