Git 撤销操作实践之 Reset Revert Rebase

2,223 阅读3分钟

前言

一直以来在使用 git 的时候经常对 reset revert rebase 这三个命令很是困惑。每次使用的时候也都是小心翼翼的,对着文档一步步操作。今天就总结一下这三个命令的使用场景以及使用方式。

正文

reset revert rebase 三个命令都可以修改 git 的提交历史(或者说撤销提交)。但是功能上却又有很大的区别。

数据准备

# 新建 git 环境
mkdir demo; cd demo ; git init

# 新建 reset 分支
git checkout -b dev

echo AAAAA > reset.txt
git add reset.txt
git commit -m "AAAAA"

echo BBBBB >> reset.txt
git add reset.txt
git commit -m "BBBBB"

echo CCCCC >> reset.txt
git add reset.txt
git commit -m "CCCCC"

echo DDDDD >> reset.txt
git add reset.txt
git commit -m "DDDDD"


# 此时的 git log 如下
$ git log --pretty=format:"%h %s" --graph

* d6212d8 DDDDD
* e807553 CCCCC
* 3609018 BBBBB
* a9fb808 AAAAA

# 此时的文件如下
$ cat reset.txt
AAAAA
BBBBB
CCCCC
DDDDD

git reset

该命令用于回退版本,可以指定退回某一次提交的版本,常见模式如下:

  • --mixed 默认参数回退版本并将修改放入工作区
  • --soft 回退版本并将修改放入暂存区
  • --hard 回退版本并将修改丢弃
# 回退到上一版本
$ git reset HEAD^ 
# 指定文件回退到上一版本
$ git reset HEAD^ hello.php 
# 回退到指定版本
$ git  reset  3609018 

比如上面的 demo 仓库现在需要回到 BBBBB 的提交:

$ git reset --hard f64fbe6
HEAD is now at f64fbe6 BBBBB

$ cat reset.txt
AAAAA
BBBBB

$ git log --pretty=format:"%h %s" --graph
* f64fbe6 BBBBB
* 17a6e45 AAAAA

git revert

该命令与 reset 功能基本一致。需要注意的是此次操作之前和之后的commit和history 都会保留,并且把这次撤销作为一次最新的提交。比如实现 demo 仓库现在需要回到 BBBBB 的提交对应的操作为:

# 1. 执行撤销到的 commit
$ git revert f64fbe6
error: could not revert f64fbe6... BBBBB

# 2. 解决冲突

# 3. 提交修改
$ git commit -am "revert commit"

# 验证结果
$ cat reset.txt
AAAAA
BBBBB

$ git log --pretty=format:"%h %s" --graph
* a6fa241 revert commit
* 7dedf32 DDDDD
* a513f6c CCCCC
* f64fbe6 BBBBB
* 17a6e45 AAAAA

对比 git reset 来看 git revert保留了完整的提交历史,不会改变项目历史,对那些已经发布到共享仓库的提交来说这是一个安全的操作。

当然 revert 还可以指定回退的提交记录, 比如回退 BBBBB、CCCCC 两次提交:

注意 git diff 17a6e45..a513f6c 左开右闭的区间。

# 先 diff 查看对应的差异
git diff 17a6e45..a513f6c
# 回退revert
$ git reset --hard HEAD^

#  解决冲突

# 查看日志
$ git log --pretty=format:"%h %s" --graph
* 81a5d64 revert BC
* 7dedf32 DDDDD
* a513f6c CCCCC
* f64fbe6 BBBBB
* 17a6e45 AAAAA

git rebase

该命令是一个非常强大的命令,功能有很多。主要的功能是修改 git 的提交历史,常见的场景为合并提交记录、修改commit message等。

下面依旧是 git revert 中的例子撤销 BBBBB、CCCCC 两次提交:

# 先 diff 查看对应的差异
git diff 17a6e45..a513f6c
# rebase 前三次提交
$ git rebase -i HEAD~3

# 修改 commit 
d 515cfeb BBBBB
d 879218f CCCCC
pick 6a664ef DDDDD

# 解决冲突并存入暂存区间(git add reset.txt)

# 继续 rebase (弹出后默认保存既可,如需修改commit log 直接编辑)
git rebase --continue 

# 查看commit log
$ git log --pretty=format:"%h %s" --graph
* 989618e DDDDD
* 17a6e45 AAAAA

总结

  • git reset 最佳场景本地commit,一般是回退到指定版本。

  • git rebase 可以新增、修改、删除 commit log,一般适用于展示完美的 commit log,方便于代码的 review。

  • git revert 可以删除一次或多次 commit,并新增 commit log 的方式完成。适用于远程仓库的提交记录。记录所有的修改历史,方便 review commit log。