Git Course 0%

The dangerous commands list

Advanced Git CLI ≈ 8 min

What you will learn

  • Which commands can lose work, and exactly what they take
  • The safe alternative or the safety check for each
  • Two questions that catch nearly every accident

After this lesson you can

  • I can recognize a dangerous command before running it, not afterwards

Why this matters

Git is far safer than its reputation, and the list of genuinely destructive commands is short enough to memorise. Everything not on this list is recoverable through the reflog (lesson 12.1). Knowing the seven means you can use the rest of Git without hesitating.

The two questions

Before any command on this page:

  1. Is there uncommitted work? git status answers it. If yes, commit or stash first; most of the damage on this page is to work Git never recorded.
  2. Has this been pushed? If yes, anything that rewrites history affects other people, and git revert is the alternative.

The list

1. git reset --hard

Takes: every uncommitted change in tracked files, staged or not. Also moves the branch.

Recovery: the commits are in the reflog; the uncommitted changes are gone.

Make it safe: git status first. git stash -u if anything is unfinished. Or use git reset --keep, which refuses when it would overwrite local changes.

2. git checkout -- <file> and git restore <file>

Takes: your edits to that file, permanently.

Recovery: none in Git. Your editor's local history may have it: VS Code's Timeline and IntelliJ's Local History both record saves independently of Git.

Make it safe: run git diff <file> first and read what you are about to discard.

3. git clean -fd

Takes: untracked files and directories, permanently. Git never had them, so nothing knows they existed.

Recovery: none.

Make it safe: always run git clean -nd first, which lists exactly what would be removed and deletes nothing. Note that -x additionally removes ignored files, which is how people delete their .env and their virtual environment in one command.

4. git push --force

Takes: whatever was on the remote branch, including commits colleagues pushed while you were working.

Recovery: from the other person's reflog, plus a conversation.

Make it safe: use --force-with-lease, which refuses when the remote has moved (lesson 12.8), and never force a shared or protected branch.

5. git rebase on a shared branch

Takes: nothing directly, but it replaces every commit with a new one, so anyone else's clone no longer matches. The damage arrives later, as everyone's confusing merges.

Recovery: git rebase --abort before it finishes; after pushing, it is a team-wide reconciliation.

Make it safe: rebase only branches nobody else has checked out. Rebasing your own feature branch onto an updated main is normal and encouraged.

6. git branch -D

Takes: the branch name, even when the branch holds commits that are not merged anywhere. The lowercase -d refuses in that case, which is why it exists.

Recovery: the reflog, or the hash Git prints as it deletes.

Make it safe: use -d and only reach for -D when Git has refused and you have understood why.

7. git filter-repo and friends

Takes: rewrites every commit in the repository, changing all their hashes. It is the right tool for removing a leaked secret from history (lesson 8.7) and a catastrophe when used casually.

Recovery: from a backup clone, if you made one.

Make it safe: never do it alone. It is a planned operation with the whole team, everyone re-clones afterwards, and the leaked credential is rotated regardless.

What is not dangerous

Worth stating, because fear of Git usually attaches to the wrong commands:

Command Why it is safe
git status, git log, git diff, git show They only read
git add Reversible with git restore --staged
git commit Reversible; the reflog remembers it either way
git fetch Downloads; changes nothing you are working on
git switch Refuses when it would lose changes
git merge Abortable with --abort
git revert Adds a commit; removes nothing
git stash Keeps your work; pop brings it back

The habits that replace caution

  • Commit early. A commit is the moment work becomes recoverable, and it is the single most effective protection on this page.
  • git status before anything with a flag in it.
  • Read the dry run. git clean -nd exists for exactly this.
  • Prefer the safe spelling: -d over -D, --force-with-lease over --force, restore --staged over restore.
  • Push your branch. Work that exists in two places is not lost by any command on this page.

How to do it

The three checks, in the order you would use them:

Terminal
$ git status
$ git clean -nd
$ git diff <file>

Each of them is free and takes a second, and between them they prevent every irreversible outcome on this page.

Common mistakes

  • -f before -n. The dry run is the whole point of git clean.
  • -x on git clean, which adds ignored files: exactly the ones that are hard to recreate.
  • --force typed from muscle memory.
  • -D because -d refused. The refusal was information.
  • Assuming the reflog covers uncommitted work. It covers commits.
  • Running a rewriting command on a branch someone else has.

Try it yourself

Goal: see the dry run save you, without losing anything.

  1. In your practice repository, create two untracked files: scratch.txt and a folder tmp/ with a file in it.
  2. Run git clean -nd and read the list. Nothing has been deleted.
  3. Run git clean -fd and confirm both are gone, and that git status shows nothing about them.
  4. Now create a .env file, add it to .gitignore, and run git clean -nd again: it is not listed.
  5. Run git clean -ndx and see it appear. Do not run the -f version.

Expected result: you have seen exactly what -n, -d and -x each contribute, on files that do not matter.

Show solution

Step 5 is the one to remember. -x is the difference between "remove junk" and "remove my local configuration", and the only way to tell them apart in advance is the dry run. Every dangerous command on this page has an equivalent way to look before acting.

Check yourself

1. Which command should always be run in its dry-run form first?
2. What can the reflog not recover?
3. Why is git branch -d preferable to -D?

Key terms

Rewriting history Working tree Untracked Reflog