目录
在学习和工作中,使用git进行多人协助时经常会出现提交错误、合并错误的情况,经常会有人提交错了合并错了怎么办,今天这里说明一下。
revert
和 reset
是两种用于撤销更改的方法,但它们的作用和使用场景有所不同。
一、revert
git revert
用于撤销指定的提交,并生成一个新的提交。这个新提交将会反转前一个提交的更改,但保持整个提交历史的完整。它适用于已经推送到共享仓库的更改,因为它不会修改已有的提交历史。
使用场景:
- 希望撤销某一次指定的提交,但不影响之后的其他提交。
- 需要保留提交历史的完整性。
基本用法:
git revert <commit> # commit为需要撤销的hash值
举个栗子:
首先准备了两次提交记录
我们发现第二次提交有问题,需要回退掉,于是执行下面
根据上面的实际操作发现 revert的回退实际上是对“需要回退的节点”上的所有提交进行了删除,重新生成了新的提交记录。
这是个坑:
revert对于分支合并来说存在一个坑,用一个栗子就可以说明白,当前文件夹master分支创建一个A和B文件,并创建A和B分支,如下图:
准备数据,A和B分支分别对应A和B文件时间交错提交两次,如下图:
将B合并到A后会发现AB的提交交错在日志里面,如下图
此时发现不应该把B合并到A里面,于是使用revert操作,
问题来了——产生了一个新的提交记录,B的内容是没了但是提交记录还在,
如果此时B分支提交了第三次记录后需要合并到A分支会产生什么问题呢,此时我们新增一个C文件进行B3的提交,如下图
此时向A分支再次合并发现B分支中的B1和B2两次提交内容没有了(原因是A1执行了一次revert merge B的操作,这一次操作删除了B的内容算是一个新的提交,新的提交时间大于B1和B2因此保留了新的文件节点)
如果想要恢复B文件内容,则需要将“”“revert merge B”这条记录revert掉,如图
二、reset
git reset
用于将当前分支的 HEAD 移动到另一个提交点,可以用来"删除"某些提交。git reset
会修改提交历史,通常只在本地开发的时候使用,不建议在已经推送到共享仓库的分支上使用。
使用场景:
- 撤销本地未推送的提交。
- 回溯到某个点并可能丢弃某些更改。
基本用法:
git reset [--soft | --mixed | --hard] <commit>
--soft
: 仅移动 HEAD,保留工作目录和暂存区的修改。--mixed
: 移动 HEAD 和暂存区,保留工作目录的修改(默认)。--hard
: 移动 HEAD、暂存区和工作目录,清除所有修改
举个栗子:
A - B - C - D (HEAD)
你想要回到提交 B
。
-
保留所有更改,但在暂存区中撤销提交:
git reset --soft B
结果:
A - B (HEAD)
这将保留提交
C
和D
的更改在暂存区中。 -
保留工作目录的改动,并在暂存区中撤销提交:
git reset --mixed B
结果:
A - B (HEAD)
这将保留提交
C
和D
的更改在工作目录中,但清除暂存区。 -
丢弃所有更改:
git reset --hard B
结果:
A - B (HEAD)
这将丢弃
C
和D
的所有更改,包括工作目录中的修改。
这不是坑:
按照上面revert坑中的栗子来说,初始文件如下图
此时将B合并到A分支中,提交记录还是交替
此时发现B不该合并的,需要reset掉,于是执行,但是要注意commit应该为A的最后一次提交节点,实例中为965c3b4272ecd7a51da3f942e771d21da505db63
执行后发现A把合并的B内容删除了,并没有留下任何痕迹,真是来取无痕啊~
git reset --hard <commit>
然后再次合并B发现依然正常
三、附赠git命令简写
-bash-4.2$ cat ~/.gitconfig
[alias]
st = status
ci = commit
co = checkout
br = branch
sub = submodule
cp = cherry-pick
[credential]
helper = store
[user]
email = XXXXXXXX
name = XXXXX
[push]
default = simple
-bash-4.2$
-bash-4.2$
-bash-4.2$