Git commands

git reset

git reset: reset the HEAD and current branch to a different commit.

git reset is a command in Git used primarily to move the HEAD and the current branch back to a specific commit, effectively "rewinding" the project's history to a previous state. This command is useful when you need to undo commits that have been made to the current branch.

When you use git reset, it's like telling your Git repository to forget that some changes ever happened, and to consider an earlier state as the current state of your project. This is extremely useful for undoing changes, simplifying complex history, or even combining multiple commits into one before sharing them with others.

Historically, git reset was used for various purposes, including resetting the working tree and staging area. To this day, veteran developers still use git reset for these tasks. However, with the introduction of the git restore command in Git 2.23.0, it is now recommended to use git restore for managing the working tree and staging area, while git reset should primarily be used for moving the HEAD and current branch pointer.

When using git restore, you are less likely to accidentally break things, as it's more targeted and less destructive than git reset. However, for someone who is used to the old git reset command, it might take some time to get used to the new command. But if you're new to Git, it's a good idea to understand the difference and try to use git restore instead of git reset when appropriate.

Examples

Move the current branch back one commit and reset the staging area to match it, while leaving the working directory unchanged. The changes from the commit that is no longer in the branch history become unstaged changes.

A common use case is splitting a rushed commit into several focused commits or staging only part of it again:

git reset HEAD~1

Move the current branch back three commits without changing the staging area or working directory. The changes from those commits appear together as staged changes.

A common use case is replacing several small or messy local commits with one clean commit:

git reset --soft HEAD~3

Move the current branch back two commits and reset both the staging area and working directory to match that earlier commit. This discards the changes from those commits and any uncommitted changes to tracked files. Uncommitted changes can be lost permanently.

A common use case is abandoning a local experiment completely when you are sure you don't need its commits or tracked changes:

git reset --hard HEAD~2

In these examples, HEAD~1 means "one commit before HEAD." The number after ~ tells Git how many commits back to go, so HEAD~3 means "three commits before HEAD." You can also specify the destination using a commit hash, branch, or another commit reference.

Be careful when using git reset, especially with the --hard option, as it can permanently discard changes. Always double-check that you're resetting to the correct commit, and consider using git stash to save your uncommitted changes before resetting if you think you might need them later.

Note that git reset doesn't remove commits entirely; it actually just moves the branch pointer. The "removed" commits are still in the repository's history (accessible via their commit hash), but they're no longer reachable from the current branch. This means that you can recover them if needed, but they won't show up in the branch's history anymore.