Git 撤消操作

1、覆盖提交

  • 有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。此时,可以运行带有 --amend 选项的提交命令尝试重新提交。

    1
    2
    3
    4
    5
    6
    $ git commit --amend



    # git commit --amend -m [提交内容说明]
    $ git commit --amend -m "Amend commit dsc"
    • 这个命令会将暂存区中的文件提交。如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。

    • 文本编辑器启动后,可以看到之前的提交信息。编辑后保存会覆盖原来的提交信息。

  • 例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作。

    1
    2
    3
    4
    5
    $ git commit -m 'initial commit'

    $ git add forgotten_file

    $ git commit --amend
    • 最终你只会有一个提交 - 第二次提交将代替第一次提交的结果。

2、取消暂存的文件

  • 接下来的两个小节演示如何操作暂存区域与工作目录中已修改的文件。这些命令在修改文件状态的同时,也会提示如何撤消操作。

  • 例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交,但是却意外地输入了 git add * 暂存了它们两个。如何只取消暂存两个中的一个呢?git status 命令提示了你。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git add *

    $ git status
    On branch master
    Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    renamed: README.md -> README
    modified: CONTRIBUTING.md
  • 在 “Changes to be committed” 文字正下方,提示使用 git reset HEAD <file>... 来取消暂存。所以,我们可以这样来取消暂存 CONTRIBUTING.md 文件。

    1
    2
    # git reset HEAD [文件名]
    $ git reset HEAD CONTRIBUTING.md
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Unstaged changes after reset:
    M CONTRIBUTING.md
    $ git status
    On branch master
    Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    renamed: README.md -> README

    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: CONTRIBUTING.md
  • 虽然在调用时加上 --hard 选项可以令 git reset 成为一个危险的命令(可能导致工作目录中所有当前进度丢失!),但本例中工作目录内的文件并不会被修改。不加选项地调用 git reset 并不危险 — 它只会修改暂存区域。

3、撤消对文件的修改

  • 如果你并不想保留对 CONTRIBUTING.md 文件的修改怎么办?你该如何方便地撤消修改 - 将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)?幸运的是,git status 也告诉了你应该如何做。在最后一个例子中,未暂存区域是这样。

    1
    2
    3
    4
    5
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: CONTRIBUTING.md
  • 它非常清楚地告诉了你如何撤消之前所做的修改。

    1
    2
    # git checkout -- [文件名]
    $ git checkout -- CONTRIBUTING.md
    1
    2
    3
    4
    5
    6
    $ git status
    On branch master
    Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    renamed: README.md -> README
  • git checkout -- [file] 是一个危险的命令。对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它。除非你确实清楚不想要那个文件了,否则不要使用这个命令。

4、重置或还原已提交的代码

  • 在多人协作时,对代码的管理,难免会出现错误。如果出现错误,我们分析下来是要进行一些回退操作,那么解决办法有如下两种:

    • git reset
    • git revert

4.1 git reset

  • Git 的 “重置” 操作。

  • 在使用 git reset 命令前,需要先了解一个概念:HEAD。HEAD 是当前分支引用的指针,它总是指向该分支上的最后一次提交。这表示 HEAD 将是下一次提交的父结点。通常,理解 HEAD 的最简方式,就是将它看做你的上一次提交的快照。

  • 查看快照的操作如下,下例就显示了 HEAD 快照实际的目录列表,以及其中每个文件的 SHA-1 校验和。

    1
    2
    $ git cat-file -p HEAD
    $ git ls-tree -r HEAD
  • git reset 的作用就是修改 HEAD 的位置,即将 HEAD 指向的位置改变为之前存在的某个版本。

  • 常用命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 回退暂存区里的某个文件,回退到当前版本工作区状态
    $ git reset HEAD --file

    # 可以把版本库上的提交回退到暂存区,修改记录保留
    $ git reset –-soft 目标版本号

    # 可以把版本库上的提交回退到工作区,修改记录保留
    $ git reset –-mixed 目标版本号

    # 可以把版本库上的提交彻底回退,修改的记录全部 revert,即修改记录不保留
    $ git reset –-hard
  • 适用场景

    • 如果我们想直接回到之前的某一版本,但是不想保留该目标版本后面的版本,就可以用这种方法。

    • 分支操作者, 操作如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      # 切换到目标分支上
      $ git checkout <branch_name>

      # 本地目标分支上重置代码到上面指定的 commit_id,
      # 注意:该 commit_id 之后的所有提交都会丢失。
      # 执行完后,HEAD 的位置已经在该 commit_id 的位置
      $ git reset --hard <commit_id>

      # 在上一条命令中,已经在本地分支中 reset 好,接下来让远程分支也有相同的效果,可以直接运行这条命令。
      # 执行后,可以去代码托管网站查看
      $ git push -f 等同于 git push --force

      # 如果目标分支和远程分支没有关联上,可以用这条命令,指出远程分支
      $ git push -f origin <branch_name>
    • 其他分支使用者:

      1
      2
      3
      4
      5
      6
      7
      # 切换到目标分支上
      $ git checkout <branch_name>

      # 这步就是其他同事把自己本地 branch_name 重置到与 origin/branch_name 一致,
      # 注意 --hard 参数会丢弃超过 origin 的所有 commit
      # 如果不想丢弃可以用 --mixed 或 --soft,具体用哪个根据自己情况来
      $ git reset --hard origin/branch_name

4.2 git revert

  • Git 的 “还原” 操作。

  • Git 给你一个生成一个新提交的选项,提交将会撤消一个已存在提交的所有修改。

  • 适用场景

    • 如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,记录下这整个版本变动流程,就可以用这种方法。

      1
      2
      3
      4
      # 本地目标分支撤销指定的 commit_id
      # 注意:做完上面的操作后,可能会出现冲突,需要先解决冲突,在 git add,
      # 然后使用 git commit 提交
      $ git revert -n <commit_id>
      1
      2
      3
      # 在上一条命令中,已经在本地分支中 revert 好,接下来让远程分支也有相同的效果,可以直接运行这条命令。
      # 执行后,可以去代码托管网站查看
      $ git push
  • 注意,git revert 后填的 commit_id 不能是 merge 操作产生的 commit_id.

文章目录
  1. 1. 1、覆盖提交
  2. 2. 2、取消暂存的文件
  3. 3. 3、撤消对文件的修改
  4. 4. 4、重置或还原已提交的代码
    1. 4.1. 4.1 git reset
    2. 4.2. 4.2 git revert
隐藏目录