有两种方法:git reset 和 git revert
一. 问题
- 如果提交了一个错误的版本,怎么回退版本?
- 如果提交了一个错误的版本到远程分支(一个人用),怎么回退版本?
- 如果提交了一个错误的版本到公共远程分支,怎么回退版本?
二. 本地分支版本回退
- git reflog 找到要回退的版本 commit id:xxxxx
- git reset --hard xxxxx 回退版本
三. 自己远程分支版本回退
- 首先回退本地分支:
1. get reflog
2. git reset --hard xxxx
- 接着强制推送到远程分支:
git push -f
四. 公共远程分支版本回退
考虑这样一种情况:假如你的远程 master 分支情况是这样的:
A1-A2-B1
其中A、B分别代表两个人,A1、A2、B1代表各自的提交。并且所有人的本地分支都已经更新到最新版本,和远程分支一致。
这个时候你发现 A2 这次提交有错误,你用 reset 回滚远程分支 master 到A1,那么理想状态是你的队友 Tony 一拉代码 git pull,他们的 master 分支也回滚了,然而现实却是,Tony 会看到下面的提示:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working directory clean
也就是说,Tony 的分支并没有主动回退,而是比远程分支超前了两次提交,因为远程分支回退了嘛。
这时,Tony 应该:
1. git reflog 找出 B1 的 commitid
2. git checkout tony_branch 回到自己的分支
3. git reset --hard B1 回到被覆盖的B1的提交
4. git checkout -b tony_backup 拉个分支,用于保存 B1
5. git checkout tony_branch 回到自己分支
6. git reset --hard 0bbbb 回到自己分支最前端
这时,B1的那次提交被找回来了,接着要将本地 master 与远程 master 保持一致:
git reset --hard origin/master
这时,Tony 的 master 分支才算真正回退了,也就是说你的回滚才对 Tony 生效,这时 Tony 的本地 master 是这样的:
A1
接着 Tony 要再次合并那个被丢掉的 B1 到 master:
git checkout master
git merge tony_backup
这时,Tony 的 master 是这样的:
A1-B1
五. 公共远程分支回退使用 git revert
使用 git reset 回退公共远程分支的版本后,需要其他所有人手动用远程 master 分支覆盖本地 master 分支,显然,这不是优雅的回退方法,下面我们使用另个一个命令来回退版本:
git revert HEAD //撤销最近一次提交
git revert HEAD~1 //撤销上上次的提交,注意:数字从0开始
git revert 0ffaacc //撤销0ffaacc这次提交
git revert 命令意思是撤销某次提交。它会产生一个新的提交,虽然代码回退了,但是版本依然是向前的,所以,当你用 revert 回退之后,所有人 pull 之后,他们的代码也自动的回退了。
但是,要注意以下几点:
- revert 是撤销一次提交,所以后面的 commit id 是你需要回滚到的版本的前一次提交
- 使用 revert HEAD 是撤销最近的一次提交,如果你最近一次提交是用revert 命令产生的,那么你再执行一次,就相当于撤销了上次的撤销操作,换句话说,你连续执行两次 revert HEAD 命令,就跟没执行是一样的
- 使用 revert HEAD~1 表示撤销最近2次提交,这个数字是从 0 开始的,如果你之前撤销过产生了commi id,那么也会计算在内的。
- 如果使用 revert 撤销的不是最近一次提交,那么一定会有代码冲突,需要你合并代码,合并代码只需要把当前的代码全部去掉,保留之前版本的代码就可以了.
git revert 命令的好处就是不会丢掉别人的提交,即使你撤销后覆盖了别人的提交,他更新代码后,可以在本地用 reset 向前回滚,找到自己的代码,然后拉一下分支,再回来合并上去就可以找回被你覆盖的提交了。
六. 如果错的太远,revert 又要解决大面积冲突,可以从错误提交的前一次拉取一份代码放到其他目录,然后将 master 的代码全部删除,把那份新的代码放上去,然后提交。
参考文章:
[Git高级教程(二)] 远程仓库版本回退方法 讲的真清楚,赞。