zoukankan      html  css  js  c++  java
  • 没想到,Git居然有3种“后悔药”!

    没想到,Git居然有后悔药!

    你知道Git版本控制系统中都有哪些“后悔药”吗?

    本文通过案例讲解git reset 、 git revert 、 git checkout在版本控制中的作用;

    场景

    小明同学作为新人加入到一个新的项目组中做开发,在项目的迭代开发中,小明勤勤恳恳的写代码,直到有一次...

    小明:完了,完蛋了

    洋仔:怎么了,一惊一乍的

    小明:我把错误代码用git commit后还push到线上代码库了! 这可怎么办!

    洋仔:莫慌,git有“后悔药”!

    洋仔:容我给你慢慢道来。 但是我们要先知道一些git的基础知识,你才能更好的理解git命令的作用

    预备知识

    git将项目的存储分为4部分,每部分有自己作用,

    见下图:

    • Workspace:工作区(当前用户操作修改的区域)
    • Index / Stage:暂存区 (add后的区域)
    • Repository:仓库区或本地仓库(commit后的区域)
    • Remote:远程仓库(push后的区域)

    整体过程可以简述为:

    • 工作区–>add–>暂存区–>commit–>本地仓库区–>push–>远程仓库区
    • 远程仓库区–>fetch–>使用refs emotes下对应分支文件记录远程分支末端commit_id 和 本地仓库区 -->merge–>工作区
    • 远程仓库区–>pull–>使用refs emotes下对应分支文件记录远程分支末端commit_id and 本地仓库区 and 工作区

    具体的git的组成部分和概念命令,请移步下述两个博客:

    Git技术干货!工作中Git的使用实践和常用命令合集!

    Git - 使用git不知道内部实现机制怎么行

    假设项目存在这么一个提交记录:

    $ git log
    commit commit_id4 (HEAD -> master)
    Author: test
    Date:   Thu Aug 20 16:28:45 2020 +0800
        第三次修改README文件
    
    commit commit_id3 (HEAD -> master)
    Author: test
    Date:   Thu Aug 20 16:28:45 2020 +0800
        第二次修改README文件
    
    commit commit_id2
    Author: test
    Date:   Thu Aug 20 16:28:19 2020 +0800
        第一次修改README文件
    
    commit commit_id1
    Author: test
    Date:   Thu Aug 20 16:26:59 2020 +080
        初始化项目
    

    提交顺序为:commit_id1 --> commit_id2 --> commit_id3 --> commit_id4

    注意:在git中每次的commit都有一个commit id唯一标识当前的提交!

    下面,我们先来解决小明的这个问题,使用git reset即可完美解决~

    问题解决

    洋仔:小明,你的这个就可以用git reset 这个命令来完美的搞定,下面我们看一下如何解决

    1、获取当前提交的commit id

    命令:git log

    获取到当前项目分支下的所有commit记录;

    假设上述小明提交错误的commit id为commit id:commit_id4这一次提交;

    他的上一次提交就是commit id:commit_id3 ,我们要将修改回滚到commit_id3的时刻!

    小明:我想要把我刚才 commit的修改保留下来,我修改的代码不能给我删除掉呀!

    洋仔:没问题

    2、将某个commit id前的commit清除,并保留修改的代码

    命令:git reset <commit_id> 当前场景下就是:git reset commit_id3

    将指定commit_id后的所有提交,都去除,并保留修改的代码在本地的区域,也就是Workspace

    小明:啊哈,这样的话我就可以把错误代码修改后再提交了; 但是我已经push到线上仓库的数据怎么办呢?

    洋仔:别急,有办法~

    3、修改代码完成后,将修改好的代码add到暂存区,并提交到本地仓库中

    命令:git add <file_name> and git commit 当前场景下:git add . and git commit

    将最新修改后的代码commit

    则提交后的提交记录假设如下: 可以看到,我们错误提交的commit_id4提交记录消失,取而代之的是我们更新代码后提交的记录commit_id5; 这样就完成了本地的代码修改和更新

    $ git log
    commit commit_id5 (HEAD -> master)
    Author: test
    Date:   Thu Aug 20 16:28:45 2020 +0800
        第三次修改README文件-更新错误后提交
    
    commit commit_id3 (HEAD -> master)
    Author: test
    Date:   Thu Aug 20 16:28:45 2020 +0800
        第二次修改README文件
    
    commit commit_id2
    Author: test
    Date:   Thu Aug 20 16:28:19 2020 +0800
        第一次修改README文件
    
    commit commit_id1
    Author: test
    Date:   Thu Aug 20 16:26:59 2020 +080
        初始化项目
    

    4、将本地修改同步到远程仓库

    命令:git push origin HEAD --force

    将本地修改强行同步到远程仓库,使得远程仓库和本地仓库保持一致!

    整体流程如下:

    git log
    git reset commit_id3
    修改代码
    git add .
    git commit -m '第三次修改README文件-更新错误后提交'
    git push origin HEAD --force
    

    洋仔:好了,小明,你的问题完美解决了

    小明:哦吼,但是我还有一个问题: 如果我想要不保留回滚commit的修改,直接删除掉修改!该怎么处理呢?

    洋仔:简单~ 我们整体看一下 git reset 命令

    后悔药-git reset

    在进行下面的讲解是,还是先假设有这么一个提交链:

    commit_id1 --> commit_id2 --> commit_id3 --> commit_id4

    git reset commit_id2:

    reset是将HEAD重新定位到commit_id2上,对于commit_id3 和 commit_id4 和本地当前的修改,对于不同的参数param,会有不同的处理;

    reset命令有三种处理模式:

    • --soft:保留commit修改,将修改存储到index中;也就是说git add后的区域
    • --mixed:保留commit修改,将修改存储到本地工作区域中;也就是说git add前的区域
    • --hard:删除commit修改,慎用!

    git reset --soft

    回滚commit_id前的所有提交,不删除修改:

    git reset --soft commit_id

    重设head,不动index,所以效果是commit_id之后的commit修改全部在index中
    将id3 和 id4的修改放到index区(暂存区),也就是add后文件存放的区域,本地当前的修改保留

    git reset --mixed

    回滚commit_id前的所有提交,不删除修改:
    git reset commit_id 等同于 git reset --mixed commit_id

    与 下述的 git reset --hard commit_id效果不同

    重设head 和 index,不重设work tree,效果就是commit_id之前的修改,全部在work tree中,为还未add的状态
    将id3 和 id4 的所有修改放到本地工作区中,本地当前的修改保留

    git reset --hard

    回滚commit_id前的所有提交,将修改全部删除:
    git reset --hard commit_id

    重设head、index、work tree,也就是说将当前项目的状态恢复到commit_id的状态,其余的全部删除(包含commit_id后的提交和本地还未提交的修改)
    慎用!!

    后悔药-git revert

    小明:原来git reset这么强大呀! 但是我这还有个问题:

    如果想要只操作修改中间的一个commit,不对其他的commit产生影响; 也就是类似于我们只修改commit_id2,而对commit_id3 和 commit_id4无影响,该怎么处理呢?

    洋仔:(这么多问题,幸亏我懂,要不这次就丢大了。。) 简单! git revert 命令!

    装b

    适用场景: 在项目开发中,突然发现在前几次的提交中,有一次提交中包含一个bug; 当然我们可以进行一个新的修改,然后再提交一次; 但是,不优雅哈哈; 我们可以直接重做有bug的commit~

    为什么不直接去再添加一个commit呢? git revert是用于“反做”某一个版本,以达到撤销该版本的修改的目的。

    比如,我们commit了三个版本(版本一、版本二、 版本三),突然发现版本二不行(如:有bug),想要撤销版本二,但又不想影响撤销版本三的提交,就可以用 git revert 命令来反做版本二,生成新的版本四,这个版本四里会保留版本三的东西,但撤销了版本二的东西;

    在revert命令中常用的就两个:

    • git revert -e <commit_id>:重做指定commit的提交信息
    • git revert -n <commit_id>:重做执行commit的代码修改

    git revert -e

    重做commit_id的提交信息,生成为一个新的new_commit_id
    git revert -e commit_id

    git revert -n

    重做commit_id的提交
    git revert -n commit_id
    将commit_id中修改,放到index区,我们可以对他重新做修改并重新提交

    revert vs reset

    • git revert是用一次新的commit来回滚之前的commit,此次提交之前的commit都会被保留不动;
    • git reset是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除或放回工作区等待下一次提交;

    小明:还有这种操作,可以直接单独操作提交过程中的某一个commit! 太棒了!

    后悔药-git checkout

    小明:还有最后一个问题:

    如果我在一次开发中,发现某个文件修改错误了,想要将文件恢复到刚pull代码时的状态怎么办呢?

    洋仔:简单! 看git checkout解决这个问题!

    我们知道使用git checkout可以

    • git checkout <branch_name>切换分支

    • git checkout -b <branch_bame>创建分支等操作

    它还有回滚指定文件的修改的功能

    命令:git checkout -- <file_name>

    上述语句的作用,就是将file_name的本地工作区的修改全部撤销,有两种情况:

    • 如果file_name在commit后没有add过这个文件,则撤销到版本库中的状态

    • 如果file_name在commit后add过这个文件,则撤销到暂存区的状态,也就是add后的状态

    总之,就是让指定的文件回滚到最近的一次git add 或者 git commit时的状态!

    小明:太棒了,以后再也不怕提错代码了!

    总结

    上述,我们介绍了git reset git revert git checkout 在版本回滚、重做、撤销修改方面的作用;

    可以应用到工作中对 误操作、不满足要求、不满足意愿的commit记录的重做和修改;

  • 相关阅读:
    JavaScript之图片操作7
    JavaScript之图片操作6
    【数据结构】树
    【数据结构】查找
    【数据结构】排序
    【HTML】常用标签及属性
    【数据结构】堆栈
    【计算机网络】五层体系结构
    【Linux】相关英文缩写含义
    【Java】连接数据库MySQL
  • 原文地址:https://www.cnblogs.com/lyycoder/p/13539665.html
Copyright © 2011-2022 走看看