前言
一直以来在使用 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。