During software development, it is common to create commits that are later deemed unnecessary, buggy, or part of a failed experiment. When you want to discard unwanted local changes or roll back a branch history completely to a previous stable state, Git provides the git reset command.
git reset is a powerful Git command used to undo changes by moving the current branch pointer (HEAD) to a specific historical commit. Unlike git revert, which creates a new commit that applies the inverse of changes, git reset rewrites history by moving the tip of the branch backwards.
Depending on the flag used, git reset modifies the three trees of Git (Working Directory, Staging Area, and Commit History) in different ways:
| Reset Mode | Moves HEAD / Branch pointer? |
Resets Staging Area (Index)? | Resets Working Directory? | Safety Level |
|---|---|---|---|---|
--soft |
Yes (moves to target commit) | No (changes remain staged) | No (local files remain intact) | Safe: No work is lost. Changes since the target commit are staged and ready to be recommitted. |
--mixed (Default) |
Yes (moves to target commit) | Yes (unstages all changes) | No (local files remain intact) | Safe: Changes since the target commit are preserved in your working directory but need to be restaged (git add). |
--hard |
Yes (moves to target commit) | Yes (clears index changes) | Yes (wipes working directory) | Dangerous: Any uncommitted changes and all commits after the target hash are permanently discarded from the working directory. |
graph TD
subgraph "Before Hard Reset"
A["Commit A"] --> B["Commit B (Target State)"]
B --> C["Commit C (Unwanted Test)"]
C --> D["Commit D (HEAD -> master)"]
end
subgraph "After git reset --hard B"
A2["Commit A"] --> B2["Commit B (HEAD -> master)"]
B2 -.-> C2["Commit C (Orphaned)"]
C2 -.-> D2["Commit D (Orphaned)"]
end
style B fill:#bbf,stroke:#333,stroke-width:2px
style B2 fill:#4ade80,stroke:#333,stroke-width:2px
style C2 stroke-dasharray: 5 5,fill:#f9f9f9
style D2 stroke-dasharray: 5 5,fill:#f9f9f9
git reset is best for local branches where commits have not yet been shared with others. Since it rewrites history, pushing a reset branch requires a force push (git push --force), which can disrupt other developers if done on a public, shared branch.git revert is best for shared public branches (like master/main). It preserves history by appending a new “revert” commit to undo changes, making it safe for other team members to pull.ststor01)natasha/usr/src/kodekloudrepos/newsmasterFrom the Jump Host, SSH into the Nautilus storage server as natasha:
ssh natasha@ststor01
Switch directory to the designated local Git repository:
cd /usr/src/kodekloudrepos/news
Display the list of commits in the repository to locate the target commit hash:
git log --oneline -n 10
Example commit log showing unwanted commits on top:
f8e9d2c (HEAD -> master, origin/master) Remove temporary test logs
a1b2c3d Add buggy script to news
7d8e9fa Add data.txt file
1d2f3e4 Initial commit
The target commit we want to keep is 7d8e9fa (“Add data.txt file”). We want to discard all commits above it (a1b2c3d and f8e9d2c).
Execute the hard reset command targeting the commit hash identified in Step 3:
git reset --hard 7d8e9fa
(Replace 7d8e9fa with your actual target commit hash from git log).
Expected output:
HEAD is now at 7d8e9fa Add data.txt file
Because the local branch’s commit history has changed, a normal git push will be rejected by the remote repository. Enforce the update using the --force (or -f) flag:
git push origin master --force
Expected output:
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 282 bytes | 282.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /opt/news.git
+ f8e9d2c...7d8e9fa master -> master (forced update)
Verify that the branch tip is now pointing at the target commit and that all unwanted commits have been removed:
git log --oneline
Expected output:
7d8e9fa (HEAD -> master, origin/master) Add data.txt file
1d2f3e4 Initial commit
Ensure the working directory is clean and files introduced by the deleted commits (if any) are discarded:
git status
Expected output:
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
Log out of the Storage Server:
exit