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分支