部分内容翻译自:Resetting,Checking Out & Reverting
Introduction
在git中以下三个命令可以帮助代码回滚。
- git reset
- git checkout
- git revert
checkout和reset通常是进行local或者private的撤销。当push的时候会很容易发生冲突。
revert是一个对public撤销安全的操作。因为会创建一个新的commit。
Prerequirements
可以看做three trees。
不同的操作对工作目录、暂存区和commit history的影响。(index为暂存区)
Checkout
checkout可以把当前的HEAD指向某个具体的commit。
是commit级别或者文件级别的操作。文件级别会把文件内容变成要求的commit的内容。
git checkout
是commit histroy树的更新。
Example
HEAD和Main当前都指向d
![Move the HEAD ref pointer to a specified commit](/Volumes/D/zhangjunyu/笔记/Git/git代码回滚.assets/01 git-sequence-transparent kopiera.png)
git checkout b
Revert
会用一个新的commit来撤销指定的commit上的更改。
是commit级别的操作。不能用在文件级别。
Reset
reset会重置three trees到要求的commit。
git reset --hard commit_id
提交:
git push origin
回退到上一个版本:
git reset --hard HEAD^
Sum
总结三个命令的常用场景。
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
Git reset和git checkout的scope由传给他们的参数决定。如果没有指定file path,那么就是commit-level。
Reset A Specific Commit
把hotfix分支移动到两个commit之前。
git checkout hotfix git reset HEAD~2
reset通常用来撤回没有和别人共享的commit。
除了撤回到之前的commit,也有可以用通过设置下列参数来更改暂存区或者工作目录。
- --soft:不会改变暂存区或者工作目录。(即原本的更新内容还在工作目录和暂存区,但是commit id回到之前的。可以重新git commit)
- --mixed:暂存区会更新到指定的commit。但是工作目录不受影响。默认参数。(可以重新编辑、然后add和commit)
- --hard:暂存区和工作目录都会更新到指定的commit。(即指定commit之后的更新会全部消失)
Checkout old commit
checkout通常可以用来切换分支,即HEAD会从一个分支切换到另一个分支:
git checkout hotfix
因为可能会覆盖本地的更改,所以git会强制我们commit或者stash所有的更改。
也可以用checkout来切换到之前的commit。例如:
git checkout HEAD~2
以为没有任何的分支引用,所以这种情况的HEAD处于游离状态。如果这个时候添加新的commit会非常危险,因为如果你切换到了其他的分支就没有办法再切回来了。所以HEAD处于游离状态的时候,一定要新建一个分支来进行操作。
Undo Public Commits with Revert
revert会通过添加一个新的commit来撤销一个commit。这是一个非常安全的撤销操作。因为它不会更改原来的commit历史。
git checkout hotfix git revert HEAD~2
这个操作会撤销两个commit之前的更新,但是是建立一个新的commit来实现的。
总的来说,git reset适合在private branch上使用,git revert适合在public上使用。
File-level Operations
Git Reset A Specific File
git reset会根据指定的commit id更新暂存区的内容。
git reset HEAD~2 foo.py
这个命令会按照两个commit之前的内容来更新foo.py文件。
--soft、--mixed和--hard在file level上不会有任何影响。
Git Checkout File
git checkout会更改工作目录。不会更改HEAD的引用。
git checkout HEAD~2 foo.py
请注意,这会删除对文件的所有后续更改,而 git revert 命令仅撤消由指定提交引入的更改。