Git新手教程-撤销更改(七)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Git新手教程-撤销更改(七)相关的知识,希望对你有一定的参考价值。

参考技术A 在前面的文章中,我们学习了标签、分支、和合并。现在我们将学习Git中另外的三个命令 git commit --amend , git revert , git reset 。下面简单的介绍中几个命令的功能:

在平时的项目开发中,有时候我们可能提交完相应文件后,才发现漏掉了几个文件没有添加,或者我们 commit 消息并没有书写完整或有错别字。那这个时候我们该整么办呢?或许我们会执行一个新的提交来添加我们遗漏的内容,但是这样一点都不优雅!!在Git中为我们提供了带有 --amend 选项的提交来修改我们 最近 的提交:

这里大家可能还是不是很明白,我们看下面这个简单的例子:

在上述例仓库中我们创建了一个 commit ,该 commit 消息并没有书写完整。这个时候我们想修改它,那么我们就可以使用命令 git commit --amend ,当输入该命令后,我们能得到如下弹窗:

这个时候,我们就可以完善该 commit 信息,然后保存并离开。这里我改成了 删除了多余的语句 ,这时我们再使用 git log 命令,我们会发现我们的 commit 消息已经被更改了。如下所示:

当然在上述例子中,我们只是简单的修改了 commit 信息,并没有修改或添加一些新的文件,如果你修改或添加了新的文件,并想将这些修改的文件添加到最近的 commit 中去的话,那么你可能要经历以下步骤:

在实际的项目中,如果你想修改最近的 commit ,那么你需要使用 git commit --amend 来更新最近的 commit ,而不是创建新的 commit 。

在上述例子中,我们知道了如何修改最近的 commit ,但是如果我们想还原这个 commit 。那这个时候,我们又该怎么办呢?我们可以使用 git revert 命令来告诉 Git 还原之前创建的commit,该命令使用的方式如下:

还是以上述例子来进行讲解,比如我们想还原下图中红色框中的 commit :

我们可以使用 git revert b71b40 ,需要注意的是使用该命令,默认会创建一个新的提交。如下图所示:

一般情况下,我们可以使用Git系统默认的 revert 信息。当我们保存并退出后,再使用 git log 命令查看我们的日志提交记录,我们能得到下图:

在上述例子中,我们学会了如何还原一个提交,但是如果我们本是这个提交就是错误的,我们并不想要这个提交,也不想仓库记录中包含 revert 的提交记录。这个时候我们又该怎么办呢?我们可以使用 git reset 命令来告诉 Git 重置 commit 。

重置(reset) 似乎和 还原(revert) 相似,但它们实际上差别很大。还原会创建一个新的 commit,并还原或撤消之前的 commit。但是重置会清除 commit!

git reset 命令相比其他 Git 命令功能要多一点,可以用来:

git reset 并不直接使用 commit 的 SHA ,而是使用特殊的 "祖先引用" 来告诉 Git 将 HEAD 指针移动到哪个commit。我们来看看这些特殊的符号。

我们可以通过以下方式引用之前的 commit:

^ 和 ~ 的区别主要体现在通过合并而创建的 commit 中。合并 commit 具有两个父级。对于合并 commit, ^ 引用用来表示第一个父 commit,而 ^2 表示第二个父 commit。第一个父 commit 是当你运行 git merge 时所处的分支,而第二个父 commit 是被合并的分支。

我们看下面的例子,来一起来理解:

因为 HEAD 指向 b71b405 commmit。

了解了祖先引用,现在我们来了解 git reset 命令的使用:

一般情况下,使用该命令,我们会添加如下选项:

直接理解这些选项比较困难,下面我们将结合图片与实际例子来进行讲解。

在下图中,假如我们的仓库中已经有了如下提交 D、E、F、G、H ,其中 master 指向最近的提交 H , HEAD 指向 master 。

这个时候我们如果使用 git reset --mixed HEAD~1 那么会将 master 与 HEAD 将会指向前一个提交 G 。同时 G 提交会移动到工作目录中。如下图所示:

当 H 提交修改的文件被移动到到工作目录后,文件的状态都为 modifed ,也就是我们需要重新添加到暂存区,然后进行 commit 。我们继续看下面的例子:

在上述仓库中有3个提交,其中 HEAD 指向 bb780f9 上的 master , 这个时候如果我们运行 git reset HEAD~ 命令,会将 commit bb780f9 中的文件移动到工作目录中,如下所示:

调用 git status 来查看我们的仓库状态,我们会发现使用 --mixed 选项,是不会暂存我们的更改的,也就是不会将相应提交的文件放入暂存区中。

当使用 --soft 选项时,不仅会移动 master 与 HEAD 指针,还会将相应修改添加到暂存区中,如下所示:

我们继续查看下面的例子:

最后我们再来看看 --hard 选项:

使用 --hard 将清除对应 commit 所作的更改,继续查看下面的👇的例子:

当使用了 --hard 选项后,发现仓库中对应的提交消失了。

当我们直接使用 git reset 或 git reset HEAD 时,表示清除暂存区中的 commit 。下面我们来看这个例子:

那么如果我们只想将 B.java 文件从暂存区中移除,那我们又该怎么办呢?我们可以使用如下命令:

当然在Git中支持多个文件的取消暂存,具体命令如下:

在上述命令中 <file>... 代表一个或多个文件。

最后还是回到我们熟悉的图形化界面的使用流程中。我们来看看IDEA为我们提供了哪些便利吧。

在创建相应 commmit 时,我们可以勾选下图中的
Amend commit 选项。如下所示:

上述操作与使用 git commit --amend 命令的效果一样。

通过依次点击编译器底部的 Version Control -> Log ,然后选择想要 revert 的 commit ,点击鼠标 右键 ,选择 Revert Commit 就可以啦~

通过依次点击编译器底部的 Version Control -> Log ,然后选择想要 reset 的 commit ,点击鼠标 右键 ,选择 Reset Current Branch to Here.. 就完成第一步啦~

当然在第二步中,我们需要选择 git reset 中的选项,在 IDEA 中提供了四种选项 Soft、Mixed、Hard、Keep ,如下所示:

在上图中,我们不熟悉的只有 --keep 选项,因为该选项在平时中的项目并不常用,所以这里就不做更多介绍了,有兴趣的小伙伴,可以查看官方文档中 git reset 中对其的介绍。

站在巨人的肩膀上,才能看的更远~

git 撤销更改

git 撤销更改

总结一下希望以后不再记混淆, 也希望看到这里的同学不犯同样的错, 这里主要介绍一下几种错误的解决方案:

  1. 修改暂存内容的撤销
  2. 暂存提交内容的撤销
  3. 提交推送内容的撤销
  4. 推送服务器内容的撤销

以上几种情况几乎覆盖到工作中常用的所有情况, 当然你要是有更复杂的情况, 那就只能再想想别的办法, 因为我这边只有两个人同时开发, 所以遇到的情况就这些, 下面说一下解决方案:

  1. 修改暂存内容的撤销. 这种情况一般是自己修改了很多东西, 但是突然领导说这些东西都不用了, 并且未来也不用了, 那么你很多修改过的文件想一下子撤回, 只需要用下面的一个命令即可,

    //--hard 表示强制回到某个版本, head是指当前版本的原始状态, 这行完之后就完全回到了最后一次pull之后的状态
    git reset --hard head   

    当然执行这个代码之前一定要先看看自己修改了那些内容, 在这中状态下执行下面的命令即可

    git diff 
    执行结果如下
    
    wangjunlingdeMacBook:MyDemo wangjunling$ git diff
    diff --git a/MyDemo/MyDemo/ViewController.m b/MyDemo/MyDemo/ViewController.m
    index 2c4d434..844ebbf 100644
    --- a/MyDemo/MyDemo/ViewController.m
    +++ b/MyDemo/MyDemo/ViewController.m
    @@ -79,6 +79,9 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
    
        NSLog(@"测试");
    
    +    NSLog(@"测试");
    +    
    +    
    
    

    在终端中可以清晰看得出这次进行的增删改查的具体信息

  2. 暂存提交内容的撤销. 这种情况很少有但是如果发生了要有方法解决, 如果采取第1中情况的解决方案也是可以的, 但是有时候有些更改我们并不想全部放弃, 对于这种情况执行以下操作 :

    //1. 可以先看看更改了什么, 这时候再执行 git diff 就什么都看不到了, 因为git diff 不带参数的时候对比的是当前版本的变化, 而通过 git add . 之后则需要对比的是 暂存区和当前分支的变化, 所以需要加一个head参数即:
    git diff head
    //2. 执行下面的命令可以撤销暂存, 保留当前的修改状态, 等调整之后再暂存提交即可
    git reset head
    //执行上面的命令后, 再执行 git diff 如果有更改说明修改的内容已经从暂存区挪出来了
  3. 提交推送内容的撤销, 已经commit的更改, 突然发现某个地方修改错了, 想撤销, 但是又不能全部撤销, 所以我们可以通过下面的命令撤销commit

    //同样的我们先去执行git diff 没内容, 再执行 git diff head 仍然没有信息, 为什么呢, 因为我们现在要对比的是 commit和head之间的不同, 所以我们需要加入两个要对比的版本的参数, 如下
    
    git diff head^ head
    
    执行完就能看到当前提交内容的修改, 然后执行 撤销操作
    
    git reset head^
    
    这样代码就会回到上此来回来的状态, 并且新修改的代码都还在
    如果执行 git reset --hard head^ 这样直接把修改的东西全都抛弃了, 并回到未修改前的状态
    
  4. 推送服务器内容的撤销. 这种情况虽然比较危险但是如果抢救及时还是没问题的, 首先还是查看变化

    //下面这条命令是查看你刚提交到远程端的代码和本地上个版本的不同, 也即是你提交的那部分代码的变化
    git diff  origin/head head^
    
    //解决问题的思路是将本地的内容回退的上个版本, 修改之后再提交到远程端, 命令和第三种情况一样, 如果需要保留修改的代码, 那就不要加--hard, 如果不需要保留则需要加 --hard, 这里我们暂定需要保留
    git reset head^ 
    
    执行完之后你的文件全部变成了未提交的状态, 这时候实际上你的版本已经落后服务器一个版本了, 所以当你修改完之后, git  push 会被服务器拒绝, 信息如下
    To github.com:wangjunling888/MyDemo.git
    ! [rejected]        master -> master (non-fast-forward)
    error: failed to push some refs to 'git@github.com:wangjunling888/MyDemo.git'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    
    解决方案 就是 用-f参数(force)强制执行覆盖操作, 当然这个操作之前一定要确定你的同事没有提交其他的代码, 要不然你把被人的代码都覆盖掉了就麻烦了, 命令如下
    
    git push -f
    
    

    好了, 就总结到这里, 技术有限, 如有疏漏或错误,欢迎留言区留言交流.

以上是关于Git新手教程-撤销更改(七)的主要内容,如果未能解决你的问题,请参考以下文章

git 新手使用教程

新手学Python之学习官网教程(七: Input and Output)

新手安装配置git简洁教程

30分钟新手git教程

GitHub 新手详细教程

GitHub 新手教程 三,Git Bash