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
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 //撤销指定的某一次提交
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 来做回滚了。
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,如果不是撤销最近的一次提交,一定会造成冲突,需要解决完冲突后再提交。
使用远程仓库覆盖本地仓库
有时我们需要直接使用远程仓库来覆盖本地的修改,那么综上所述,就可以直接使用
git reset --hard origin/master //使用远程的master分支直接覆盖本地的master分支