git reset revert rebase 区别

xiaoxiao2021-02-28  102

最近合并他人代码,因为代码是从git代码库之外来的,于是出了各种问题。于是又翻看了git教程。这里推荐两篇: Git教程 - 廖雪峰的官方网站 非常通俗易懂,教了最基本的,十分实用。 ###Git 基础图解、分支图解、全面教程、常用命令### 把git的命令以图解的形式给了出来,让人更理解git背后的处理原则。 但我读完后,仍然不理解git reset/revert,于是自己实践,终于得出了结果。 首先,说下Git的处理基准:

一、Git 基础原理

每个文件都有各自的记录,称之为树也可(这是git reset让人迷糊的地方);Git库中有commit/index/working directory 3个状态之分,如下图: History,所有提交过的commit保存的位置,也就是说只要commit过,都是历史,可以回到过去~ Stage(index),也就是当前git add过的但尚未commit的文件 Work directory,就是当前正在改的代码了 Git之中并无分支,但4个指针(很像C/C++语言的指针): (1)我们常用的branch(像master/dev/…) (2)动态的HEAD,也就是当前用户在Git树中的位置,这个名称是固定的,三个命令的工作就是让这个HEAD来回走; (3)index指针; (4)work directory指针。git commit 的本质是让index/work directory/HEAD指向同一个commit。 Git 不会主动删除 任何一个commit,无论这个commit是否在某个分支的路径中,或者HEAD是否指向它,所以理论上无论任何时候,只要知道commit-id就可以到达这个commit。

二、命令比较

2.1 Git 测试树

现在说完基础知识,在建一个测试环境,Git树如下:

$ git log --all --graph --oneline # 查看Git树信息

master下有dev和other两个分支,我们的测试主要在dev分支下,不用考虑other分支。dev分支下有个log.txt文件,文件内容和当前的commit内容相同

2.2 git revert 命令

现在先来说revert

$ git reset 2e5e386 # 也就是取消dev2这个commit 重置后取消暂存的变更: M log.txt $ cat log.txt <<<<<<< HEAD dev4 ======= dev >>>>>>> parent of 2e5e386... dev2 $ echo "revert dev2" > log.txt $ git add . $ git revert --continue # revert的话,最好用这个来提交

完成后,Git树状态如下: 也就是说,git revert “commit-id”后,git 会比较”commit-id”与当前(也就是HEAD)内容的区别,由用户修改完成后,再提交为新的commit。这个命令最好让人理解。

2.3 git reset 命令

这个命令是这三个命令中最让人迷糊的,有3个参数soft/mixed(默认)/hard。只要把这3个命令和Git的3个工作区对比就可以了。 先用图说明下: soft 参数 mixed 参数 hard 参数 配合第一节说的Git基础原理,基本就可以明白git reset 在做什么了。

但还有一个问题,如果reset当前分支好几步的commit节点,如何处理? 答:Git取变化的文件树中最新的内容。

有点迷糊啊,那来个例子: 继续之前的Git log。 先测试 soft 模式

$ git reset --soft 2e5e386 $ git status 位于分支 dev 要提交的变更: # !!! 这是add 过的状态 !!! (使用 "git reset HEAD <文件>..." 以取消暂存) 修改: log.txt $ git checkout -- log.txt $ cat log.txt revert dev4 # 这是log.txt文件树中最新的内容,HEAD指向了"dev2"

再测试 mixed 模式

$ git reset --hard 8785cbf # 回到revert的位置 $ git reset 2e5e386 # 使用mixed模式到"dev2" $ git status 位于分支 dev 尚未暂存以备提交的变更: # !!! 这是需要 add 过的状态 !!! (使用 "git add <文件>..." 更新要提交的内容) (使用 "git checkout -- <文件>..." 丢弃工作区的改动) 修改: log.txt $ cat log.txt revert dev4 # 这是log.txt文件树中最新的内容,HEAD指向了"dev2"

最后测试 hard 模式 (很危险,会清除work directory未保存的内容,最好commit后再使用这个模式)

$ git reset --hard 8785cbf # 回到revert的位置 $ git reset --hard 2e5e386 $ git status 位于分支 dev 无文件要提交,干净的工作区

需要说明的是,git reset后,再commit时,新的commit并不在当前分支中,因为它确实不是一个有名字的分支,这时状态是detached HEAD,如下图。 想要保存,就在这时

$ git checkout -b new-branch-name

2.4 git rebase 命令

这个命令很好理解,就是不想合并分支时,把某个分支的commit自动添加到另一个分支之后,用下图可以比较清楚地解释这个命令。

转载请注明原文地址: https://www.6miu.com/read-38420.html

最新回复(0)