There are two kinds of "destructive" here -- commands that are destructive to your git history and commands that discard changes in your working copy.
Commands that discard work tree changes:
git reset
git checkout
As others have mentioned, the combination of the reflog and the fact that git objects don't immediately get discarded (unless you turn on automatic cleanup) means that you can usually undo operations like git reset/rebase/merge
.
These commands, though, actually discard git objects, eliminating the ability to undo:
git gc
(by default, this prunes unreachable objects that are at least 2 weeks old)