Foreword:
After mastering the basic operations of a Git local repository, “how to correct erroneous commits,” “how to recover accidentally deleted files,” and “the risks and solutions for version rollback” become key topics for developers to advance. In code development, accidental changes to configurations, committing redundant files, and deleting core code are unavoidable. Git’s version rollback, undoing changes, and file deletion mechanisms are precisely designed to solve these problems . This article will focus on these advanced operations, breaking down their principles, scenarios, and practical details to help you accurately and safely bring your version back on track when code deviates from its intended path.
I. Key Git Capabilities: Version Revert and Undo Changes
During the development phase, it is inevitable that there will be situations such as writing code errors or committing mistakes. Git provides a comprehensive version rollback and undo mechanism, which can be flexibly handled according to the stage of the modification.
Version 1.1 rollback
git reset Version rollback can be achieved via commands. The core principle is to locate the target version using commit id an OR pointer. The command format is:HEADgit reset 【--soft | --mixed | --hard】【HEAD】
Key parameter descriptions :
| parameter | effect | Risk level |
|---|---|---|
--mixed | The default parameters only revert the staging area to the specified version; the working directory content remains unchanged. | Low |
--soft | Only the repository is rolled back; the contents of the staging area and working directory remain unchanged. | Low |
--hard | The staging area, working directory, and repository are all reverted to the specified version. | High (Code not committed to the workspace will be lost). |
- HEAD Explanation:
- You can directly write the commit ID, which indicates that the version to be rolled back is specified.
- HEAD indicates the current version.
- HEAD^ Previous version
- HEAD^^ Previous version
- And so on…
- It can be represented using ~ numbers:
- HEAD~0 indicates the current version.
- HEAD~1 Previous Version
- HEAD^2 Previous version
- And so on…
Practical Use:
To facilitate explanation and testing of the rollback function, we need to do the following preparatory work: Update the ReadMe to three versions and commit each version three times, as shown below:
# Submit the first modification
[root@VM-4-4-centos gitcode]# echo "hello version1" >> ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
[root@VM-4-4-centos gitcode]# git add ReadMe
[root@VM-4-4-centos gitcode]# git commit -m "add version1"
[master 40bc6e6] add version1
1 file changed, 1 insertion(+)
# Submit second revision
[root@VM-4-4-centos gitcode]# echo "hello version2" >> ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
[root@VM-4-4-centos gitcode]# git add ReadMe
[root@VM-4-4-centos gitcode]# git commit -m "add version2"
[master 1a083cf] add version2
1 file changed, 1 insertion(+)
# Submit the third revision
[root@VM-4-4-centos gitcode]# echo "hello version3" >> ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
[root@VM-4-4-centos gitcode]# git add ReadMe
[root@VM-4-4-centos gitcode]# git commit -m "add version3"
[master b592a38] add version3
1 file changed, 1 insertion(+)
# View History
[root@VM-4-4-centos gitcode]# git log --pretty=oneline
b592a387a176cfb00c56cd3cbc1d3faca9ba2cee add version3
1a083cf93e6f21ba0bf5419f32125875aa787255 add version2
40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1
……
Now, if we commit version 3 and then find errors in it, and want to revert to version 2 and start writing again based on version 2, we need to use parameters since we want to revert the workspace content to version 2 as well. --hard An example is shown below:
[root@VM-4-4-centos gitcode]# git log --pretty=oneline
b592a387a176cfb00c56cd3cbc1d3faca9ba2cee add version3
1a083cf93e6f21ba0bf5419f32125875aa787255 add version2
40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1
…………
# Rollback to version 2
[root@VM-4-4-centos gitcode]# git reset --hard 1a083cf93e6f21ba0bf5419f32125875aa787255
HEAD is now at 1a083cf add version2
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
We can see that ReadMe the file content has now reverted to version 2! If we git log check the commit log again, we’ll find it HEAD points to version 2, as shown below:
[root@VM-4-4-centos gitcode]# git log --pretty=oneline --decorate
1a083cf93e6f21ba0bf5419f32125875aa787255 (HEAD, master) add version2
40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1
…………
This concludes the demonstration of the rollback function. But what if I regret it and want to go back to version 3? We can continue using git reset commands to roll back to a previous version3 version, but we must explicitly version3 specify commit id the version to roll back to.
However, we see that git log it cannot be printed out version3 . commit id If we’re lucky, we can find the previous record in the terminal; if we’re unlucky, commit id we’ve already lost it.
It’s worth mentioning that Git also provides a git reflog command to recover from this; this command is used to record every command executed locally.
[root@VM-4-4-centos gitcode]# git reflog
1a083cf HEAD@{0}: reset: moving to 1a083cf93e6f21ba0bf5419f32125875aa7
b592a38 HEAD@{1}: commit: add version3
1a083cf HEAD@{2}: commit: add version2
40bc6e6 HEAD@{3}: commit: add version1
eb85e67 HEAD@{4}: commit: delete
54cffd0 HEAD@{5}: commit: add 3 file3
1e3f5b8 HEAD@{6}: commit: commit my first file
fcce812 HEAD@{7}: commit (initial): add first file
(END)
This way, you can easily find all your operation records, but b592a38 what is this? This is a part version3 of the commit id Git version. When rolling back Git versions, you can also use a part commit id to represent the target version. Example:
# Go back to version 3
[root@VM-4-4-centos gitcode]# git reset --hard b592a38
HEAD is now at b592a38 add version3
# View workspace
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
# View log
[root@VM-4-4-centos gitcode]# git log --pretty=oneline --decorate
b592a387a176cfb00c56cd3cbc1d3faca9ba2cee (HEAD, master) add version3
1a083cf93e6f21ba0bf5419f32125875aa787255 add version2
40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1
…………
But often, the ideal is far from reality. In actual development, due to long development periods, versions might become commit id unavailable. What if one day I suddenly want to go back to version 3? How do I do that? It seems impossible now.
Additional explanation :
Git version rollback is extremely fast because Git internally uses a HEAD pointer to the current branch (in this case, master), and refs/heads/master the file stores master the latest version of that branch commit id . When we roll back a version, Git simply refs/heads/master stores a specific version in the file, which can be simply understood as shown in the following diagram:
1.2 Cancel Modification
Depending on the current stage of the modification (working area/staging area), select different undo commands:
Scenario 1: Modifications only occurred in the workspace and were not executed. git add
Use git checkout -- [file](this is - - very important; omitting it will change the meaning) to discard workspace changes and restore the workspace to its most recent git addor git commitcurrent state.
Friendly reminder : Don’t try to git diff xxx manually delete changes by finding the differences; if there are many changes, it will take forever and be incredibly tiring.
# Add a new line of content to ReadMe
[root@VM-4-4-centos gitcode]# echo "It is shift" >> ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
It is shift
# Restore to the previous add or commit
[root@VM-4-4-centos gitcode]# git checkout -- ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
Scenario 2: Modifications have been executed git add in the staging area, but not yet… commit
After adding, the data is still saved to the temporary storage area. How can I undo this?
# Add a new line of content to ReadMe
[root@VM-4-4-centos gitcode]# echo "It is shit" >> ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
It is shit
# Add and store in temporary storage area
[root@VM-4-4-centos gitcode]# git add ReadMe
# git status
[root@VM-4-4-centos gitcode]# git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: ReadMe
#
git reset So what should we do? Let’s recall the rollback command we learned earlier . If this command is used --mixed with parameters, it can revert the contents of the staging area to a specified version, but the working directory file remains unchanged. We can then use the method from Scenario 1 above to solve this.
In short: first, undo the changes in the staging area to the working directory, then discard the changes in the working directory.
# First, undo the modification of the temporary storage area to the workspace. -- mixed is the default parameter and can be omitted
[root@VM-4-4-centos gitcode]# git reset HEAD ReadMe
Unstaged changes after reset:
M ReadMe
# git status
[root@VM-4-4-centos gitcode]# git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: ReadMe
#
no changes added to commit (use "git add" and/or "git commit -a")
# Discard modifications to the workspace
[root@VM-4-4-centos gitcode]# git checkout -- ReadMe
[root@VM-4-4-centos gitcode]# git status
# On branch master
nothing to commit, working directory clean
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
Recovery successful!!!
Scenario 3: Modifications have been committed to the repository (but not pushed to the remote repository).
You can simply git reset --hard revert to the previous version.
Note : If you have already pushed to a remote repository, this operation will cause inconsistencies between the local and remote versions, so please be careful. We will discuss this remote repository later.
# Add a new line of content to ReadMe
[root@VM-4-4-centos gitcode]# echo "I like coding" >> ReadMe
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
I like coding
# Add + Submit
[root@VM-4-4-centos gitcode]# git add ReadMe
[root@VM-4-4-centos gitcode]# git commit -m "test quash"
[master 1a0a253] test quash
1 file changed, 1 insertion(+)
# Go back to the previous version
[root@VM-4-4-centos gitcode]# git reset --hard HEAD^
HEAD is now at b592a38 add version3
[root@VM-4-4-centos gitcode]# cat ReadMe
hello Lotso
hello version1
hello version2
hello version3
II. Deleting Git Files: Permanent Deletion and Recovery from Accidental Deletion
In Git, deleting a file is also a “modification operation,” and you need to choose between “permanently delete” or “recover accidentally deleted files” depending on your needs:
2.1 Accidentally deleted files in the workspace need to be recovered.
[root@VM-4-4-centos gitcode]# ls
file1 ReadMe
[root@VM-4-4-centos gitcode]# rm file1
rm: remove regular empty file ‘file1’? y
Deleting them directly like this is actually useless and only adds to the trouble. git status The command will immediately tell you which files have been deleted.
[root@VM-4-4-centos gitcode]# git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: file1
#
no changes added to commit (use "git add" and/or "git commit -a")
At this point, the working directory is quite different from the repository. To delete a file, you now need to delete not only the files in the working directory but also the files in the repository. Of course, if the deletion was accidental , you can directly use [ git checkout -- file method name] to recover it, as mentioned before (deletion is also considered modification).
[root@VM-4-4-centos gitcode]# ls
ReadMe
[root@VM-4-4-centos gitcode]# git checkout -- file1
[root@VM-4-4-centos gitcode]# ls
file1 ReadMe
2.2 Confirm file deletion and synchronize to the repository.
It is possible to restore it here, as mentioned above.
# Delete file1 from both the workspace and temporary storage area simultaneously
[root@VM-4-4-centos gitcode]# git rm file1
rm 'file1'
[root@VM-4-4-centos gitcode]# git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: file1
#
# Submit deletion operation to version repository
[root@VM-4-4-centos gitcode]# git commit -m "deleted file1"
[master c213450] deleted file1
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 file1
[root@VM-4-4-centos gitcode]# git status
# On branch master
nothing to commit, working directory clean