Git 代码回滚
Synopsis
git reset
, git checkout
, git revert
是git
工具箱中最常用的工具.它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用与特定的某个文件.
git仓库由上图三个部分组成,__Working Directory__ 工作目录, Staged Snapshot 缓存区, Commit History 提交历史.
提交层面的操作
git reset
, git checkout
的参数决定了它们的作用域.如果没有包含文件路径,这些操作对于所有的提交生效,这一节探讨提交层面的操作,git revert
没有文件层面的操作.
Reset
在提交层面,reset将一个分支的末端(HEAD)指向另一个提交历史.这可以用来移除当前分支的一些提交.比如,下面的这两条命令让_hotfix_分支向后回退了两次提交.
git checkout hotfix
git reset HEAD~2
现在hotfix分支末端的两次提交变成了悬挂提交.也就是说,下次Git进行垃圾回收的时候,这两个提交将被删除.换句话说,如果你提交了错误的代码,想要抹除掉自己已经提交的内容,你可以用git reset
来丢掉你已经提交的代码,但是默认不会修改你的工作区的代码,所以回退之后你的工作区代码没有任何变化,但是git status
会变化.
走一遍流程:
git init
初始化一个仓库echo "init commit" >> README.md
git status
查看仓库状态git add .
跟踪文件并提交至缓冲区git commit -m 'init commit'
提交修改按照上述流程再增加一个提交,下面直接写
shell
代码
echo "first commit" >> README.md
git add .
git commit -m 'first commit'
下面是当前仓库的状态图
提交历史的状态
git reset HEAD~1
回退代码
此时的仓库的状态变成了这样:
缓冲区和提交历史区域的代码全部被丢弃,仓库的状态也发生了改变.此时提交历史是这样的:
末尾的一次提交变成了悬挂提交.
除了默认的丢弃掉缓冲区和提交历史的代码,git reset
还有其他的选项决定该命令的作用范围.
--soft
工作目录的代码和缓冲区的代码都不会改变 可以称之为软撤销--mixed
默认的方式,只会保留工作目录的代码--hard
丢弃掉工作目录,缓冲区,提交历史中的代码,可以称之为硬撤销
这些标记常常和git reset
一起使用,--mixed
在你不想完全舍弃自己的代码,--hard
在你想完全的丢弃自己的代码.
注意: 当你传入除HEAD以外的提交历史的时候要格外小心,因为git reset
操作会重写你的提交历史,这意味着你之前的提交找不回来了,如果在公共分支上面这样做,会导致其他人的提交代码丢失,切忌在公共分支上面这样做.
Checkout
这个应该是最常用的命令了,当传入一个分支名是,git可以切换到那个分支.
git checkout hotfix
上诉命令从当前分支切换到hotfix
分支,git只不过是将HEAD的指向切换到hotfix的末端,然后更新工作目录.因为这个操作可能会覆盖当前工作目录的内容,所以git在切换之前会强制要求你提交当前工作目录或者是缓冲区中的修改,不然在checkout
的时候这些修改将会丢失.和git reset
不同的是,git checkout
并没有修改这些分支.仅仅是切换了HEAD的引用.
除了分支以外,你还可以传入提交的引用来checkout
到任意的提交.这和checkout
到任意的分支是一样的: 切换HEAD的引用到特定的提交.比如,下面这条命令会checkout
到当前提交的祖父分支:
git checkout HEAD~2
这对于查看当前分支的历史记录非常重要.但如果你当前的HEAD没有任何分支的引用,那么这会造成HEAD的分离.这是非常危险的,如果你接着提交新的提交,然后切换到其他分支之后就没有办法回到之前添加的那些提交.因此,在为分离的HEAD添加新的提交之前你应该创建一个新的分支.
revert
Revert撤销一个提交的同时会创建一个新的提交。这是一个安全的方法,因为它不会重写提交历史。比如,下面的命令会找出倒数第二个提交,然后创建一个新的提交来撤销这些更改,然后把这个提交加入项目中。
git checkout hotfix
git revert HEAD~2
未完待续 2017.5.26
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。