当前位置:   article > 正文

一文搞懂本地和远程分支代码回退git reset_git reset 远程

git reset 远程

最近痴迷于git flow,打算对之前大部分人一提起就害怕的代码回退——git reset来进行一个实践,也算是一篇操作总结,想直接看结论的可以拉到文末,如有纰漏,欢迎大佬们指正补充。

一、本地git reset

在代码还没push到代码仓时,我们的代码都是本地操作,这时的git reset都在本地进行。那一般会有几种情况需要reset呢?总结了一下,大概有以下三种:

  • 不该add的文件被add;
  • 某些代码commit后想回退;
  • 某些已经commit的代码完全不想要了

下面就让我们来模拟一下,这三种情况下,代码要怎么进行reset。

在开始之前,给大家送上一些福利图,这对于接下来的场景理解一定会有所帮助。

文件状态转化
在这里插入图片描述
文件存储流程
在这里插入图片描述
git提交文件流程
在这里插入图片描述
git-reset图
在这里插入图片描述

1.1 把不该add的文件add了

我们在码云上新建一个代码仓,pull之后,在本地添加.gitignore文件,然后我们push到remote。这时本地和远程上的提交信息只有一个:
远程
本地
然后,我们在本地新添加一个Java文件:GitDemo.java,如下图:
在这里插入图片描述
然后再添加并add一个新文件:GitRollback.java:
在这里插入图片描述
然后我们commit这两个文件:
在这里插入图片描述
这时,我们发现GitRollback这个类是不需要提交的,那怎么办呢?

我们根据一些网友说的checkout来试试:

git checkout --  GitRollback.java
  • 1

结果如下图,根本不起作用,:
在这里插入图片描述

git push 时还是默认选择两个文件:
要push的代码根据网友的说法,是因为此时的代码已经被add了,但是checkout这个命令究竟什么时候可以用?我们下文再谈。

继续第一种场景,从开头的git-reset图,我们可以知道,这时我们要回到没有被add的场景,那我们应该选择的是git reset – soft,我们来执行一下:

git reset --soft --GitRollback.java
  • 1

在这里插入图片描述
没有任何作用,说明该命令不能只回退一个文件,那我们就只能进行版本回退了,在版本回退的同时,我们直接用idea工具来回退。

步骤如下:

1、选择版本:
在这里插入图片描述
2、在idea的工具栏上面,点击git—reset head ,出现如下:
在这里插入图片描述
填入版本号之后,我们发现本地的两个文件都已经恢复到没被add的状态,并且commit记录消失:

在这里插入图片描述

要是我们选择的是soft回退会怎么样?我们重新刚才的场景:

在这里插入图片描述
这次我们选择soft,点击reset后,再次commit时,发现文件还是add状态:
在这里插入图片描述
可以得知:

如果要让文件回退到未被add的状态,只能选择用git reset --mixed

1.2 某些代码commit后想回退;

在第一种情境的基础上,我们先commit&push代码,然后我们在GitRollback.java 上添加一些代码,并commit:
在这里插入图片描述
这时,我们只是想保存代码,而不是回退到未add的状态,那我们执行git reset soft即可:
在这里插入图片描述
那如果选择 mixed,代码会变成没有add的状态吗?我们复现一下:
在这里插入图片描述
发现没有区别,因为我们并没有在上一次commit中去新增文件,所以只是回退代码到未commit的状态,而不是回到没有被add的状态,所以这种场景下,选择soft或者mixed都可以

1.3 某些已经commit的代码完全不想要了

让我们模拟第三种场景,我们在GitRollback.java中,添加了一下代码,并新增了一个类,同时commit:

在这里插入图片描述
但是,如果我们不想要这段代码而且要保存这个类,也就是部分回退,那应该怎么操作呢?

打开命令窗口,输入以下命令:

git reset 1144a121 GitRollback.java
  • 1

命令中的1144a121是上个版本的版本号。命令格式如下:

git reset 版本号  filename
  • 1

结果如图:

在这里插入图片描述
我们需要再次在命令窗口执行commit代码,随便输入一个commit message,例如;

git commit -m "just reset local second commit on GitRollback.java"
  • 1

在这里插入图片描述
这时我们的工作区还没有任何变化,我们在控制台输入:

git checkout GitRollback.java
  • 1

再看我们的工作区:
在这里插入图片描述
代码已经回退,并且新增的类依旧在。查看git log:

在这里插入图片描述
多了一个commit信息。如果我们不想要commit,又该怎么样操作?我们复现一下。

将代码回退到上一个版本之后,我们使用hard命令来回退试试:

git reset --hard  1144a121 GitRollback.java
  • 1

在这里插入图片描述
结果如下,并不能回退:

在这里插入图片描述
这时,我们上文提到的checkout命令就派上用场了。我们在命令窗口输入:

git checkout 1144a121 -- GitRollback.java
  • 1

结果如下:
在这里插入图片描述
本地新增文件没有回退,并且指定文件代码回退到上一个版本,查看git log:
在这里插入图片描述
可以发现,并没有多余的commit信息,所以,对于这种情况,我们推荐使用checkout命令

可能会有读者好奇,每次我都是怎么复现场景的,其实,我是用了git reset hard 来快速复现的,这个命令的应用场景又是怎么样的呢?

1.4 将本地近期commit的版本的代码完全放弃,直接用远程的代码

git reset hard这个命令,就是用于这种场景的。当我们本地修改的代码不多,或者是不小心改动了多次之后,如果不想再从remote clone code,这应该是最好的实现方式。

我们来看看本地和 第一次commit之间的区别:

在这里插入图片描述
第一次commit的时候,本地只有两个Java类,而现在,我们有四个类,那如果我们想不保留这两个类,而且不留下commit信息,如何做呢?

复制第一次commit的版本号,打开idea最上方的git工具栏,git —— reset head,选择hard并输入版本号:

在这里插入图片描述
结果如下:
在这里插入图片描述
本地代码文件变成两个,没有额外添加新的commit记录,但是本地旧的commit记录仍然保持。

再看远程的commmit记录:
在这里插入图片描述

说明本地的git commit 记录没有实时更新。

1.5 本地代码回退多次

我们在远程新建一个文件:helloword.java,然后进行commit:
在这里插入图片描述
之后,我们在本地进行3次commit:
在这里插入图片描述
然后,我们update本地代码,发现本地最近的两次修改都有问题,这时就面临一个git reset的问题。
在这里插入图片描述
其实,git reset 除了指定版本号进行回退外,默认还有一个参数head,代表当前版本,我们只需要在head后加上要回退的次数,即可:

git reset head~2
  • 1

操作如下:
在这里插入图片描述
我们validate一下,看看内容:
在这里插入图片描述
发现是第二次提交的内容,不是第一次commit的内容,回退后查看工作区:
在这里插入图片描述
发现我们第二次commit的内容还在,这是因为我们在本地commit之后还进行了update,update默认也算一次提交。

我们再次进行update,这次,我们选择rebase,看看git reset head 是否会回退到本地只提交一次时的代码:
在这里插入图片描述
git rebase之后,可以发现本地没有多余的commit信息,我们再执行一次:

git reset head~2
  • 1

在这里插入图片描述
validate一下:
在这里插入图片描述
发现是第一次commit的内容,reset之后查看工作区:
在这里插入图片描述
代码成功回退到第一次commit的场景。

总结
1、要回退本地的多次commit,用git reset head~num 命令,其中num代表你要回退几次commit;
2、update project时,建议使用git rebase命令,这样update时不会生成多余的commit信息,而且会将本地的commit放到最前面,回退时就可以精准回退。

二、远程git reset

一般情况下,我们不会去回退远程版本到指定版本,因为远程代码在多人协作的情况下,可能更新速度比较快,一旦回退会影响团队其他人的代码,为了演示,这里我们看看这两种场景。

1、因为码云默认分支的设置缘故,不能force push,所以我们新建dev分支并push到remote之后,我们在dev分支上去push一些代码,发现最新一次的push代码有问题,回退到上一个版本

在这里插入图片描述

如上图,我们决定把代码回退到the second commit这个版本。

我们复制码云上的版本号,然后用idea自带的git reset 功能选择mixed,填入版本号,执行:

在这里插入图片描述

结果如图:
在这里插入图片描述

第三次commit的代码已经重新变成未commit状态,查看git log,commit信息还在:
在这里插入图片描述

那远程要怎么和本地保持一致呢?

git 有个不常用的force push 这时就派上用场了,如下图:

在这里插入图片描述
点击后,本地commit信息消失:
在这里插入图片描述
查看远程代码:

在这里插入图片描述
commit信息同步一致,说明版本已经回退。

2、发现某次push的代码里有问题,该如何回退到指定版本

在本地和远程同时commit&push几次代码,现在我们的版本到了v5,相对于the second commit而言,我们多了一个文件和一行代码。

在这里插入图片描述

同样,我们要reset to the second commit,那我们同样复制该版本号。然后,本地回退:

在这里插入图片描述
回退完成后,我们再次选择commit时,会把remote的新建文件也默认勾选了,这会造成一定的困扰:这个文件究竟是我之前修改的,还是其他人修改的呢

在这里插入图片描述

那我们暂时不看commit,直接force push,代码强推上仓库了。
在这里插入图片描述

所以这时说明版本也回退了,本地代码没有被覆盖的问题。

三、如何避免git reset

虽然上面说了种种关于git reset的技巧和方法,但我希望各位读者永远都用不上。作为一个coder,我们应该尽量避免这种可能会造成代码覆盖的高风险事情的发生。

改掉一个bug,最好的方式是重写代码后commit,而不是在本地搞一堆reset之后,还担心把别人的代码给覆盖掉,有时还会分不清哪些代码是自己改的,哪些是别人改的。

这是我一直持有的观点。那我们如何避免呢?我认为有以下两种方式。

1、设立保护分支

现在类似码云、GitHub上都有设置保护分支的功能,本地的代码只能被提交到自己的分支上,如果要合并到保护分支,那就必须先经过commiter的审视,这样子,即使本地代码再怎么玩,只要最后一关没被合入保护分支,那就不会造成代码仓的代码问题。

2、idea自带的rollback和local history功能

作为一个高级开发工具,idea在git上的功能还是比较强大的,当我们本地的代码要commit之前,可以点击下图的rollback功能,看看我们改了哪些东西,哪些需要回退:
在这里插入图片描述
也可以打开local history:
在这里插入图片描述
查看各个文件的history,避免修改有误。

四、总结

  1. 如果要将本地已经add的文件回退到工作区(untracked ),请使用git reset --mixed 功能;

  2. 已经commit的文件代码如果想回退,不管用git reset --mixed还是git reset --soft,都只是将代码回退到add状态,并不会将其回退到untracked ;

  3. 回退commit中的某个文件到某个指定版本,可以用

git checkout 版本号 -- filename
  • 1
  1. 回退到某个版本并不保留commit记录和代码时,用git reset hard。
  2. 所有的git reset命令都会改写commit log,只是有时local和remote不一致。
  3. git reset remote 只能 force push到非保护分支,会造成remote repository的commit log和代码消失问题。
  4. 避免git reset,最好是设置保护分支,然后合理利用好idea自带的rollback和local history功能。

参考链接

git 让单个文件回退到指定版本

Git语法之Checkout使用

What’s the difference between git reset --mixed, --soft, and --hard?

ocal-branching-on-the-cheap

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/794672
推荐阅读
相关标签
  

闽ICP备14008679号