Everyone makes mistakes: a wrong edit, a file added by accident, a typo in a commit message. The comfort of Git is that you can undo most mistakes, as long as you know which tool fits which situation. This lesson covers the common cases, from the safest to the most careful. You will practise each in a small project, and the session below is a real one.
$ git status -s
M menu.txt
$ git restore menu.txt
$ cat menu.txt
tea
coffee
$ git add menu.txt
$ git restore --staged menu.txt
$ git status -s
M menu.txt
$ git add menu.txt && git commit -m "Add soup"
[main 682019c] Add soup
1 file changed, 1 insertion(+)
$ git add menu.txt && git commit -m "Add jus"
[main 0b5d67b] Add jus
1 file changed, 1 insertion(+)
$ git commit --amend -m "Add juice"
[main 19ae32e] Add juice
1 file changed, 1 insertion(+)
$ git log --oneline
19ae32e Add juice
682019c Add soup
f8c6f07 Add menu
$ git revert --no-edit HEAD
[main 4029f99] Revert "Add juice"
1 file changed, 1 deletion(-)
$ cat menu.txt
tea
coffee
soup
$ git log --oneline
4029f99 Revert "Add juice"
19ae32e Add juice
682019c Add soup
f8c6f07 Add menu
1. Discard changes you have not staged: git restore
We added soup to menu.txt but changed our mind. git restore menu.txt replaced the file with the version from the last commit, and cat menu.txt shows only tea and coffee again. Warning: this throws away your edit for good, because Git never saved it. Use it only when you are sure.
2. Unstage a file: git restore --staged
We staged the file with git add and then realised it should not be in this commit. git restore --staged menu.txt moves it out of the staging area, but keeps your edit in the working folder. The status goes back from staged to M (modified). Nothing is lost.
3. Fix the last commit: git commit --amend
We committed with the message Add jus and noticed the typo. git commit --amend -m "Add juice" replaced the last commit with a corrected one. You can also use --amend to add a forgotten file: stage it, then run git commit --amend. Notice that the commit code changed from 0b5d67b to 19ae32e. Amend creates a new commit that replaces the old one.
4. Undo a commit safely: git revert
Suppose the juice commit was a mistake, and it is already shared. git revert HEAD makes a new commit that does the opposite of the last one. Look at the log: the old commit is still there, followed by Revert "Add juice", and the menu no longer has juice. The history stays honest, and nobody's copy breaks. Revert is the safe choice for anything that is already published. HEAD means the latest commit. You can also revert an older commit by giving its code, such as git revert 682019c.
The dangerous commands
- `git reset --hard` moves your branch and throws away all uncommitted changes. It can destroy work. Never use it unless you understand exactly what it will remove.
- `git push --force` overwrites the history on the remote. It can delete other people's work. Avoid it on shared branches. If you must use it on your own branch, prefer
--force-with-lease, which stops if somebody else pushed meanwhile. - `git clean -fd` deletes untracked files. They are not in Git, so they cannot be recovered.
- Before you try something risky, make a safety copy of your work, or create a new branch (lesson 4) so you can return to it.
A safety net: the reflog
Even after a bad reset, Git keeps a private log of where your branch was, called the reflog. git reflog lists recent positions, each with a code that you can go back to. It is a lifesaver for commits, but it cannot bring back uncommitted changes, and it is only kept for a limited time. Do not rely on it, but know that it exists.
Choosing the right tool
- Edited a file and want the old version back:
git restore file. - Staged something by mistake:
git restore --staged file. - Wrong message or forgot a file in the last commit, not pushed yet:
git commit --amend. - A bad commit that others may have:
git revert <commit>. - Not sure: run
git statusand read what Git suggests.
A note on the lines you see in the output: Git also prints a Date: line for --amend and revert. We left it out to keep the session short.
Your task
- Create a project with a file and one commit. Edit the file, then use
git restoreto throw the edit away. - Edit again, stage with
git add, and then unstage withgit restore --staged. - Make a commit with a typo in the message, and fix it with
git commit --amend -m. - Make a commit, then undo it with
git revert HEAD. Look atgit log --oneline.
How to check it worked
- After restore, the file has its old content.
- After
git revert, your log shows both the original commit and the revert commit. - You can say why revert is safer than reset for shared work.