How to revert commit revert
How to revert commit revert
How to revert commit revert
Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them. This requires your working tree to be clean (no modifications from the HEAD commit).
See «Reset, restore and revert» in git[1] for the differences between the three commands.
OPTIONS
With this option, git revert will let you edit the commit message prior to committing the revert. This is the default if you run the command from a terminal.
Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent.
Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.
With this option, git revert will not start the commit message editor.
Usually the command automatically creates some commits with commit log messages stating which commits were reverted. This flag applies the changes necessary to revert the named commits to your working tree and the index, but does not make the commits. In addition, when this option is used, your index does not have to match the HEAD commit. The revert is done against the beginning state of your index.
This is useful when reverting more than one commits’ effect to your index in a row.
GPG-sign commits. The keyid argument is optional and defaults to the committer identity; if specified, it must be stuck to the option without a space.
Add Signed-off-by line at the end of the commit message. See the signoff option in git-commit[1] for more information.
Use the given merge strategy. Should only be used once. See the MERGE STRATEGIES section in git-merge[1] for details.
Pass the merge strategy-specific option through to the merge strategy. See git-merge[1] for details.
Allow the rerere mechanism to update the index with the result of auto-conflict resolution if possible.
SEQUENCER SUBCOMMANDS
Skip the current commit and continue with the rest of the sequence.
Forget about the current operation in progress. Can be used to clear the sequencer state after a failed cherry-pick or revert.
Cancel the operation and return to the pre-sequence state.
EXAMPLES
Revert the changes specified by the fourth last commit in HEAD and create a new commit with the reverted changes.
Revert the changes done by commits from the fifth last commit in master (included) to the third last commit in master (included), but do not create any commit with the reverted changes. The revert only modifies the working tree and the index.
How do I «un-revert» a reverted Git commit?
Ideally, this should be done with a new commit, so as to not re-write history.
13 Answers 13
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
git cherry-pick
Will make a copy of the original commit, essentially re-applying the commit
Reverting the revert will do the same thing, with a messier commit message:
git revert
Either of these ways will allow you to git push without overwriting history, because it creates a new commit after the revert.
When typing the commit sha, you typically only need the first 5 or 6 characters:
git cherry-pick 6bfabc
Otherwise, reverting the revert is perfectly fine.
A revert commit is just like any other commit in git. Meaning, you can revert it, as in:
That obviously only makes sense once the changes were pushed, and especially when you can’t force push onto the destination branch (which is a good idea for your master branch). If the change has not been pushed, just do cherry-pick, revert or simply remove the revert commit as per other posts.
In our team, we have a rule to use a revert on Revert commits that were committed in the main branch, primarily to keep the history clean, so that you can see which commit reverts what:
This way, you can trace the history and figure out the whole story, and even those without the knowledge of the legacy could work it out for themselves. Whereas, if you cherry-pick or rebase stuff, this valuable information is lost (unless you include it in the comment).
Obviously, if a commit reverted and re-reverted more than once that becomes quite messy.
How to use Git Revert
How is git revert used?
This might sound like a duplicate question but when people ask it, the response is often, use git reset as per Revert to a commit by a SHA hash in Git?.
Before you know it, eight different people appeared with their own unique ways to save the OP’s ass, all of which is over your head.
A scenario: you’ve committed twice to master and it’s bad. You’ve pushed and other people have your bad changes.
This is what source control is all about. I’m sure it’s easy.
Obviously, you’ll need to push again and probably announce your balls-up to the team.
6 Answers 6
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
git revert makes a new commit
git revert simply creates a new commit that is the opposite of an existing commit.
It leaves the files in the same state as if the commit that has been reverted never existed. For example, consider the following simple example:
In this example the commit history has two commits and the last one is a mistake. Using git revert:
There will be 3 commits in the log:
So there is a consistent history of what has happened, yet the files are as if the bad update never occured:
Closing questions
do you have to do something else after?
A git revert is just another commit, so e.g. push to the remote so that other users can pull/fetch/merge the changes and you’re done.
Do you have to commit the changes revert made or does revert directly commit to the repo?
Obviously you’ll need to push again and probably announce to the team.
Use Git revert like so:
git revert creates a new commit with the changes that are rolled back. git reset erases your Git history instead of making a new commit.
The steps after are the same as any other commit.
The question is quite old but revert is still confusing people (like me)
As a beginner, after some trial and error (more errors than trials) I’ve got an important point:
git revert requires the id of the commit you want to remove keeping it into your history
git reset requires the commit you want to keep, and will consequentially remove anything after that from history.
That is, if you use revert with the first commit id, you’ll find yourself into an empty directory and an additional commit in history, while with reset your directory will be.. reverted back to the initial commit and your history will get as if the last commit(s) never happened.
To be even more clear, with a log like this:
Using git revert cb76ee4 will by default bring your files back to 01b56c6 and will add a further commit to your history:
git reset 01b56c6 will instead bring your files back to 01b56c6 and will clean up any other commit after that from your history :
I know these are «the basics» but it was quite confusing for me, by running revert on first id (‘first commit’) I was expecting to find my initial files, it taken a while to understand, that if you need your files back as ‘first commit’ you need to use the next id.
The reason reset and revert tend to come up a lot in the same conversations is because different version control systems use them to mean different things.
As for your actual questions about revert.
Okay, you’re going to use git revert but how?
git revert first-bad-commit^..last-bad-commit
And after running git revert do you have to do something else after? Do you have to commit the changes revert made or does revert directly commit to the repository or what??
By default, git revert prompts you for a commit message and then commits the results. This can be overridden. I quote the man page:
With this option, git revert will let you edit the commit message prior to committing the revert. This is the default if you run the command from a terminal.
Usually the command automatically creates some commits with commit log messages stating which commits were reverted. This flag applies the changes necessary to revert the named commits to your working tree and the index, but does not make the commits. In addition, when this option is used, your index does not have to match the HEAD commit. The revert is done against the beginning state of your index.
This is useful when reverting more than one commits’ effect to your index in a row.
Resetting, Checking Out & Reverting
It helps to think about each command in terms of their effect on the three state management mechanisms of a Git repository: the working directory, the staged snapshot, and the commit history. These components are sometimes known as «The three trees» of Git. We explore the three trees in depth on the git reset page. Keep these mechanisms in mind as you read through this article.
A checkout is an operation that moves the HEAD ref pointer to a specified commit. To demonstrate this consider the following example.
This example demonstrates a sequence of commits on the main branch. The HEAD ref and main branch ref currently point to commit d. Now let us execute git checkout b
This is an update to the «Commit History» tree. The git checkout command can be used in a commit, or file level scope. A file level checkout will change the file’s contents to those of the specific commit.
A revert is an operation that takes a specified commit and creates a new commit which inverses the specified commit. git revert can only be run at a commit level scope and has no file level functionality.
A reset is an operation that takes a specified commit and resets the «three trees» to match the state of the repository at that specified commit. A reset can be invoked in three different modes which correspond to the three trees.
Checkout and reset are generally used for making local or private ‘undos’. They modify the history of a repository that can cause conflicts when pushing to remote shared repositories. Revert is considered a safe operation for ‘public undos’ as it creates new history which can be shared remotely and doesn’t overwrite history remote team members may be dependent on.
Git Reset vs Revert vs Checkout reference
The table below sums up the most common use cases for all of these commands. Be sure to keep this reference handy, as you’ll undoubtedly need to use at least some of them during your Git career.
Command | Scope | Common use cases |
---|---|---|
git reset | Commit-level | Discard commits in a private branch or throw away uncommited changes |
git reset | File-level | Unstage a file |
git checkout | Commit-level | Switch between branches or inspect old snapshots |
git checkout | File-level | Discard changes in the working directory |
git revert | Commit-level | Undo commits in a public branch |
git revert | File-level | (N/A) |
Commit Level Operations
The parameters that you pass to git reset and git checkout determine their scope. When you don’t include a file path as a parameter, they operate on whole commits. That’s what we’ll be exploring in this section. Note that git revert has no file-level counterpart.
Reset A Specific Commit
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. For example, the following command moves the hotfix branch backwards by two commits.
The two commits that were on the end of hotfix are now dangling, or orphaned commits. This means they will be deleted the next time Git performs a garbage collection. In other words, you’re saying that you want to throw away these commits. This can be visualized as the following:
This usage of git reset is a simple way to undo changes that haven’t been shared with anyone else. It’s your go-to command when you’ve started working on a feature and find yourself thinking, “Oh crap, what am I doing? I should just start over.”
In addition to moving the current branch, you can also get git reset to alter the staged snapshot and/or the working directory by passing it one of the following flags:
It’s easier to think of these modes as defining the scope of a git reset operation. For further detailed information visit the git reset page.
Checkout old commits
The git checkout command is used to update the state of the repository to a specific point in the projects history. When passed with a branch name, it lets you switch between branches.
You can also check out arbitrary commits by passing the commit reference instead of a branch. This does the exact same thing as checking out a branch: it moves the HEAD reference to the specified commit. For example, the following command will check out the grandparent of the current commit:
Undo Public Commits with 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. For example, the following command will figure out the changes contained in the 2nd to last commit, create a new commit undoing those changes, and tack the new commit onto the existing project.
This can be visualized as the following:
You can also think of git revert as a tool for undoing committed changes, while git reset HEAD is for undoing uncommitted changes.
File-level Operations
The git reset and git checkout commands also accept an optional file path as a parameter. This dramatically alters their behavior. Instead of operating on entire snapshots, this forces them to limit their operations to a single file.
Git Reset A Specific File
When invoked with a file path, git reset updates the staged snapshot to match the version from the specified commit. For example, this command will fetch the version of foo.py in the 2nd-to-last commit and stage it for the next commit:
Git Checkout File
Checking out a file is similar to using git reset with a file path, except it updates the working directory instead of the stage. Unlike the commit-level version of this command, this does not move the HEAD reference, which means that you won’t switch branches.
For example, the following command makes foo.py in the working directory match the one from the 2nd-to-last commit:
If you stage and commit the checked-out file, this has the effect of “reverting” to the old version of that file. Note that this removes all of the subsequent changes to the file, whereas the git revert command undoes only the changes introduced by the specified commit.
Summary
Как отменить последний коммит
Допустим, вы работаете над кодом в Git и вдруг что-то пошло не по плану. Вам нужно отменить ваш последний коммит. Как это сделать? Давайте разберемся!
Отменить последний коммит можно двумя способами. В этой статье мы рассмотрим оба.
Команда git revert
Команда git revert создает коммит, который возвращает изменения, внесенные с указанным коммитом. С помощью этой команды можно отменить последний коммит:
Найти имя коммита, который нужно вернуть, можно при помощи команды git log. Первый коммит в выдаче и будет вашим последним созданным коммитом.
Вы можете скопировать его хэш (цифробуквенный идентификатор) и использовать его в команде revert.
Команда git reset
Отменить последний коммит можно также при помощи команды git reset. Но будьте осторожны: это изменит историю коммитов. Пользуйтесь этой командой пореже.
Эта команда смещает HEAD на последний коммит. По умолчанию используется опция —mixed. Все изменения после указанного коммита останутся в рабочем каталоге как неотслеживаемые.
Опция —soft позволяет сохранить незакоммиченные изменения (если они были) как staged.
Если вы хотите сбросить все до последнего коммита, а также удалить все неподготовленные изменения, можно использовать опцию —hard.
Таким образом вы вернетесь в положение до последнего коммита, но вместе с тем сотрете все изменения, не попавшие в коммит.
Что лучше использовать: reset или revert?
Используйте reset исключительно для сброса коммитов, существующих лишь локально. Эта команда меняет историю коммитов. А это может негативно сказаться на работе удаленных членов команды, которые могли основывать что-то на коммите, который вы сотрете.
Команда revert создает новый коммит, отменяющий изменения, и не перезаписывает историю коммитов. Так что, если коммит, который вы хотите вернуть, уже был запушен в общий репозиторий, лучше использовать revert.
Заключение
Мы разобрали два способа отменить последний коммит, а также разобрали, когда какой лучше использовать.
Теперь вы знаете, что делать, если вы вдруг заметите баг в вашем последнем коммите, или окажется, что изменения вовсе не должны были попасть в коммит!