What's the difference between Git Revert, Checkout and Reset?

GitGit CheckoutGit ResetGit Revert

Git Problem Overview


I am trying to learn how to restore or rollback files and projects to a prior state, and don't understand the difference between git revert, checkout, and reset. Why are there 3 different commands for seemingly the same purpose, and when should someone choose one over the other?

Git Solutions


Solution 1 - Git

These three commands have entirely different purposes. They are not even remotely similar.

git revert

This command creates a new commit that undoes the changes from a previous commit. This command adds new history to the project (it doesn't modify existing history).

git checkout

This command checks-out content from the repository and puts it in your work tree. It can also have other effects, depending on how the command was invoked. For instance, it can also change which branch you are currently working on. This command doesn't make any changes to the history.

git reset

This command is a little more complicated. It actually does a couple of different things depending on how it is invoked. It modifies the index (the so-called "staging area"). Or it changes which commit a branch head is currently pointing at. This command may alter existing history (by changing the commit that a branch references).

Using these commands

If a commit has been made somewhere in the project's history, and you later decide that the commit is wrong and should not have been done, then git revert is the tool for the job. It will undo the changes introduced by the bad commit, recording the "undo" in the history.

If you have modified a file in your working tree, but haven't committed the change, then you can use git checkout to checkout a fresh-from-repository copy of the file.

If you have made a commit, but haven't shared it with anyone else and you decide you don't want it, then you can use git reset to rewrite the history so that it looks as though you never made that commit.

These are just some of the possible usage scenarios. There are other commands that can be useful in some situations, and the above three commands have other uses as well.

Solution 2 - Git

Let's say you had commits:

C
B
A

git revert B, will create a commit that undoes changes in B.

git revert A, will create a commit that undoes changes in A, but will not touch changes in B

Note that if changes in B are dependent on changes in A, the revert of A is not possible.

git reset --soft A, will change the commit history and repository; staging and working directory will still be at state of C.

git reset --mixed A, will change the commit history, repository, and staging; working directory will still be at state of C.

git reset --hard A, will change the commit history, repository, staging and working directory; you will go back to the state of A completely.

Solution 3 - Git

  • git revert is used to undo a previous commit. In git, you can't alter or erase an earlier commit. (Actually you can, but it can cause problems.) So instead of editing the earlier commit, revert introduces a new commit that reverses an earlier one.
  • git reset is used to undo changes in your working directory that haven't been comitted yet.
  • git checkout is used to copy a file from some other commit to your current working tree. It doesn't automatically commit the file.

Solution 4 - Git

  • git checkout modifies your working tree,
  • git reset modifies which reference the branch you're on points to,
  • git revert adds a commit undoing changes.

Solution 5 - Git

Reset - On the commit-level, resetting is a way to move the tip of a branch to a different commit. This can be used to remove commits from the current branch.

Revert - Reverting undoes a commit by creating a new commit. This is a safe way to undo changes, as it has no chance of re-writing the commit history. Contrast this with git reset, which does alter the existing commit history. For this reason, git revert should be used to undo changes on a public branch, and git reset should be reserved for undoing changes on a private branch.

You can have a look on this link- Reset, Checkout and Revert

Solution 6 - Git

If you broke the tree but didn't commit the code, you can use git reset, and if you just want to restore one file, you can use git checkout.

If you broke the tree and committed the code, you can use git revert HEAD.

http://book.git-scm.com/4_undoing_in_git_-_reset,_checkout_and_revert.html

Solution 7 - Git

I will try to answer the question with git restore added to it

Let's say you had the following commit history:

D
C
B
A

git revert:

Makes a reverse-commit. git revert commit-hash does not alter your commit history but makes a new commit that reverts the changes that were committed as part of the commit

git revert B, will create a commit that undoes changes in B. Git history post it would be

reverse-B
D
C
B
A

If commit C depends on commit B git revert B will result in a merge-conflict

Suggestion: git revert is designed to revert public commits. All the other ways to undo changes have the potential to alter commit history which might cause issues with other participants of the project. git revert is the way to undo changes without meddling with the commit history

git restore:

git restore helps you move files from commit/staging-area to worktree/staging-area

The command is git restore [--source=commit-hash] [--worktree] [--staged] [--] file

  • --worktree means make the restore to worktree
  • --staged means make the restore to --staged.
  • specify both --staged and --worktree to make the restore from --source to both the worktree and the staging-area
  • when --source is specified the restore is always from the source
  • when --source is not specified and --staged is given the restore is from the HEAD
  • when neither --source nor --staged are specified then the restore is from staging-area to the worktree

Suggestion - Use git restore to bring the files from

  • commit blob to staging-area and/or worktree.
  • staging-area to worktree

git checkout commit-hash:

please note that although there is a file-level implementation of git checkout which helps you pull files from commit into the staging area or worktree, we will not be discussing that since now that is the responsibility of the git restore command and it is designed precisely to declutter and make consistent the git checkout command.

  • git checkout commit-hash - Head is moved to point to the commit-hash. Always leaves you in a detached head state.
  • git checkout branch - Head is moved to point to the branch specified and this is now not in a detached state

Suggestion: Use git checkout to take a look at various commits around the tree and switch between branches

git reset commit-hash:

  • You were in a detached head state - git reset would move the HEAD to the specified commit-hash. Just like git checkout commit-hash
  • You were not in a detached head state - git reset would move the entire (HEAD -> branch) to the specified commit-hash. If this resulted in commits that no branch is ahead of then those commits are removed from git history

git reset also has three options --soft, --mixed, --hard. How should your worktree and Index(staging area) look like once you have moved your HEAD to a different commit?

  • --hard - Both the Worktree and the Index match the files in the new commit you moved to
  • --mixed (default) - Worktree remains as it was before you ran git reset and Index matches the files in the new commit you moved to
  • --soft - Worktree and Index both remain as they were before you ran git reset

git reset for the most part can be replicated using a combination of git checkout, git branch -D and git restore except that there is no easy way to control the contents of worktree and stagin-area as well except if you don't use git reset

Suggestion : Have you made a few commits that should not have been made and have not pushed the changes to the public repo? Is it best to just have as if these commits never existed? Use git reset. If you have pushed the changes to public repo then as discussed earlier you want to use git revert

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhazizView Question on Stackoverflow
Solution 1 - GitDan MouldingView Answer on Stackoverflow
Solution 2 - GitAkavallView Answer on Stackoverflow
Solution 3 - GitJonathanView Answer on Stackoverflow
Solution 4 - Gitdan_waterworthView Answer on Stackoverflow
Solution 5 - GitSachchidanand SinghView Answer on Stackoverflow
Solution 6 - GitLostMohicanView Answer on Stackoverflow
Solution 7 - GitMiloMinderbinderView Answer on Stackoverflow