Skip to content
目录

git 各个场景下的代码撤销和回滚操作

在日常工作中,基本都是 git 管理代码,避免不了的一个问题就是代码的插销和回滚了,比如做的修改不需要了,线上代码出现问题需要及时回退等。

撤销

撤销工作区的修改(尚未进行 git add 操作)

比如今天上班的时候,产品跟您说改需求,你高兴的做到工位上开始修改

快下班的时候,你准备 git add 提交代码下班了,产品笑眯眯的跑过来跟你说,早上说的需求不做了,这时你心里一万只草泥马飘过,就需要将今天写的代码撤销掉了。

因为还没进行 git add 添加到暂存区,所有只需要通过 git checkout -- index.html 来撤销修改了。

git checkout -- index.html //撤销index.html单个文件
git checkout -- .   //撤销所有文件

git checkout -- filename checkout 后面一定要加--,不加就是切换分支了

撤销暂存区的修改(已经 git add 尚未 git commit)

如果不幸把不需要的代码通过 git add 提交到了暂存区,需要通过 git reset 来撤销

git reset HEAD index.html //撤销index.html单个文件
git reset HEAD . //撤销所有文件

注意

这里需要特别注意,因为只是撤销暂存区的修改,所以执行了 git reset HEAD 命令后,工作目录看上去是没有任何变化的

经过这一步,暂存区里面的文件就是 add 之前的文件了,现在只需要撤销工作区的文件了(心里想想,还记得怎么做么)。没错,就是刚才讲过的,使用 git checkout filename 来撤销工作区的文件

撤销本地仓库中的修改(已经 git commit 尚未 git push)

使用 git reset 前,先查看下提交记录 git log --oneline

shell
git log --oneline

6869000 git reset --hard id
242f6ab 引入reset.css样式文件
907996a git add后使用git reset HEAD filename撤销修改
2ebc649 撤销工作区的修改,直接使用git checkout -- filename(还没git add)
cdbda2d 修改title为move-tack
13e4cb9 first commit

如果我们想回到上一次的提交,直接 git reset --hard HEAD^就行了

注意

git reset --hard HEAD^ 表示退回到上一次提交 HEAD^^表示回退到上上次提交,HEAD^^^^^表示回退到前 5 次提交,当然这样写起来太不方便了,可以直接 HEAD~100,表示回退到前 3 次提交,也可以直接通过 commitId 来回退到指定版本 git reset --hard 242f6ab

这里又引入了一个新参数 --hard 是什么?

其实 git reset 后面可以接三个参数:

参数描述
git reset --mixed
(默认,相当于 git reset),回退到指定版本,工作区的内容会保留,暂存区会回退,比如在上一次 commit 后,新增了 a.html 文件并 add 到暂存区,同时修改了 b.html 文件,没有 add 提交,那么在使用 git reset 后,工作区的内容会保留,在 b.html 文件中做的修改还存在,但是暂存区的内容不会保留,如果需要再提交,需要重新执行 git add a.html 将 a.html 添加到暂存区,再执行 git commit
git reset --hard强制回退到指定版,工作区和暂存区的内容会被重置(有风险,工作区和暂存区的修改都不会保留),比如在上一次 commit 后,新增了 a.html 文件并且 git add 到暂存区,同时修改了 b.html 文件,没有 add 提交,那么在使用 git reset --hard 后,暂存区中的 a.html 文件和工作区的 b.html 文件都会被清除。
git reset --soft回退到指定版本,工作区和暂存区的内容会被保留。比如在上一次 commit 后,新增了 a.html 文件并且 add 到暂存区,同时修改了 b.html 文件,没有 add 提交,那么在使用 git reset --soft 后,暂存区和工作区的内容还在,工作区对 b.html 文件的修改会保留,同时 a.html 也在暂存区中,如果需要再提交,直接 git commmit 就行

撤销远程仓库的修改(代码已经 git push)

git revert 回滚

注意

使用 git reset 回滚是直接删除指定版本后的提交记录,使用 git log 看不到后面的记录了,(如果需要回到回滚前的版本,可以使用 git reflog)。

git revert 是用一次新的 commit 来回滚之前的 commit 提交,之前的提交记录都会保留

使用 git reset 进行回滚,有个问题就是,如果在回滚前通过 git push 推送到了远程仓库,那远程仓库的版本就比本地仓库的版本要新,回滚后想要再次推送到远程仓库,肯定会报错,提示要先 git pull,但是,如果你 git pull 了,那之前的回滚操作就会白做了。

这个时候聪明的你肯定想到了通过 git push -f -u origin master 强推去覆盖远程仓库,但是如果这样做,多人协作的时候,如果别人正好 pull 了远程仓库最新的代码来开发,下次别人再 pull 的时候,他本地的 git 怎么处理已经被删除的提交?当别人使用 git push 正常推到远程仓库时,也会提示本地仓库落后于远程仓库,会引起更多的问题,所以这个时候就需要使用 git revert 来回滚了。

执行 git revert 时,必须确保工作区是 clean 状态

  • git revert HEAD //撤销最近一次提交
  • git revert HEAD~1 //撤销上上次提交 数字从 0 开始
  • git revert commitId //撤销指定的某一次提交
shell
git log

6869000 git reset --hard id
242f6ab 引入reset.css样式文件
907996a git add后使用git reset HEAD filename撤销修改
2ebc649 撤销工作区的修改,直接使用git checkout -- filename(还没git add)
cdbda2d 修改title为move-tack
13e4cb9 first commit

假如 907996a 这次提交的代码有严重 bug,需要回滚,但是当时没有发现,在这次提交后又进行了 2 次正常的提交,如果使用 git rest 来回滚,那么后面两次提交就没有了,显然不是我们想要的,这个时候就可以使用 revert 来做回滚了。

shell
git revert 907996a

6869000 git reset --hard id
242f6ab 引入reset.css样式文件
907996a git add后使用git reset HEAD filename撤销修改
2ebc649 撤销工作区的修改,直接使用git checkout -- filename(还没git add)
cdbda2d 修改title为move-tack
13e4cb9 first commit

使用 git revert 907996a 后,原来的两次提交记录也存在,这样就不会覆盖别人的提交了,需要注意的时,使用 revert,如果不是撤销最近的一次提交,一定会造成冲突,需要解决完冲突后再提交。

使用远程仓库覆盖本地仓库

有时我们需要直接使用远程仓库来覆盖本地的修改,那么综上所述,就可以直接使用

shell
git reset --hard origin/master //使用远程的master分支直接覆盖本地的master分支