平时多留意、回滚是迫不得已、少用慎用 | 疑则不用、用则不疑
平时多留意、回滚是迫不得已、少用慎用 | 疑则不用、用则不疑
平时多留意、回滚是迫不得已、少用慎用 | 疑则不用、用则不疑
git reset 和 git revert 是 Git 中用于撤销提交的两个命令,它们的区别在于带给你的工作量和影响范围。
一、先说结论
1. 基本
- git reset 是截断到某一个commit生效(包含)。
- git revert 是截断到某一个commit(不包含),解决冲突之后,才生效。
2. 使用场景
git reset 适用于 上线之后,发现问题,及时回滚到一个稳定的版本。因为这时候,能确保你操作的时候别人不会合并代码,没有冲突快速高效。任何有权限的人都可以无脑回滚git revert 适用于 要解冲突的文件很少,并且你有自信解决冲突时足够熟悉和自信。必须是非常有把握的人才可以回滚,适用于需求开发阶段,少用于线上回滚
二、初始状态
1. 当前文件内容
2. commit记录
git log --oneline
951a94f (HEAD -> branchA) 我是第六次commit
c537cb8 我是第五次commit
663f532 我是第四次commit
fb26cf1 我是第三次commit
a95e2ee 我是第二次commit
086b010 我是第一次提交
三、git revert
目标:撤销第四次提交(意思是保留第四次之前的,不含第四次)
1. 命令
git revert 663f532
2. 当前文件内容
有冲突(因为是改动的同一个文件)
解决冲突(选择新引入的内容),文件内容变为
3. commit记录
可以看出,是多了一条最新的提交记录
e382b3c (HEAD -> branchA) Revert "我是第四次commit"
951a94f 我是第六次commit
c537cb8 我是第五次commit
663f532 我是第四次commit
fb26cf1 我是第三次commit
a95e2ee 我是第二次commit
086b010 我是第一次提交
插入知识
<<<<<<< HEAD
表示当前分支的内容
=======
表示你要新引入的内容
>>>>>>>
4. 补充知识
- 你会发现,git revert是会引入冲突的,然后解决冲突的时候具体保留了哪些,只有自己清楚。所以
可能会存在因为粗心保留少了或者保留多了的问题。(因为某次提交都是新增文件的时候很少见,所以多数情况下,引入冲突是在所难免的)如果要去解冲突的文件比较多时,那么挺费时间的,而且解决完冲突还要再测一下。所以适用于改动文件较少的情况。 - revert的时候,不包含对应commit的记录,所以
真正保留的需要再往前数一次提交。 - 如果以后又想要"我是第四次commit", 可以再针对性的 git revert e382b3c,即
revert revert - revert命令
会产生一次最新的提交记录,不会删除之前的任何一条提交记录。
四、git reset
目标:会滚到某一版本(包含对应commit)
1. 命令
git reset --hard 663f532
2. 当前文件内容
很清晰明了
执行 git reset之后,如果你之前跟踪过远程,那么会提示你需要pull很多更新(这些其实就是你刚删除的),所以你需要强制 git push
git push --force
3. commit记录
可以看出,最近一个区间的记录消失了(实则只是head头的移动,所有的commit记录依旧还有)
663f532 (HEAD -> branchA) 我是第四次commit
fb26cf1 我是第三次commit
a95e2ee 我是第二次commit
086b010 我是第一次提交
4. 撤销reset
使用 git reflog 查看所有的历史提交记录,你会发现经过reset丢失的历史记录还存在
git reflog
663f532 (HEAD -> branchA) HEAD@{0}: reset: moving to 663f532
951a94f HEAD@{1}: reset: moving to 951a94f6ae81b9677c775b7168c4263c66c1e878
ceebb00 HEAD@{2}: commit: Revert "我是第四次commit"
951a94f HEAD@{3}: commit: 我是第六次commit
c537cb8 HEAD@{4}: commit: 我是第五次commit
663f532 (HEAD -> branchA)HEAD@{5}: commit: 我是第四次commit
fb26cf1 HEAD@{6}: commit: 我是第三次commit
a95e2ee HEAD@{7}: commit: 我是第二次commit
086b010 HEAD@{8}: commit (initial): 我是第一次提交
恢复到第六次记录
git reset --hard 951a94f
得到的文件内容如下
5. 补充知识
- 你会发现,
git reset 不会引入冲突,这点非常有优势。 - reset之后,仅仅是移动了HEAD头的位置,原始的commit信息并没有删除。只不过
git log 返回的是当前生效的HEAD对应的记录,你本地push之后,其他人也是在该HEAD位置生效(只要在push之前别人不改);但git reflog 返回的是全部的commit记录,包含所有的操作历史。这一点,很赞 - reset命令不会产生新的提交记录,只是移动头、但是
生效的代码确实被删除了一个区间段(但是也可以恢复) 即 可以用 reflog命令之后, 再reset到任意一次commit即可。 - 执行git reset的时候,要确保你的分支是最新的,别人不会改动。如果不是最新的,然后你重置到某一次提交,会导致你还没拉下来的别人的改动被你删除了。(如果出现这种情况,就需要再次手动的将别人的git记录 chery-pick到你的分支上)。
最保险的策略是告知其他人不要动这个分支了、或者你重新拉一个分支
五、git的3个区
在 Git 中,有三个主要的区域(或者称为状态)用于管理代码的版本控制和变更记录:
- 工作区(Working Directory):工作区是指开发者当前正在工作的目录,其中包含项目的实际文件。可以使用
git add命令将其添加到暂存区。 - 暂存区(Staging Area 或 Index):通过
git commit提交到版本库中生效。 - 版本库(Repository 或 Commit History):版本库是存储代码完整历史记录的地方。它包含了所有的提交记录(commit)。后续通过git push就可以让远程的别人看到你的这次提交了。如果是个人本地开发,不使用git push也没问题。
基本的 Git 工作流程如下:
- 修改工作区的文件。
- 使用
git add命令将修改的文件添加到暂存区。 - 使用
git commit命令将暂存区的文件提交到版本库,创建一个新的提交记录。
通过这种方式,Git 将代码的版本控制过程分为了三个区域,允许开发者更加灵活地管理和跟踪代码的变化。
六、后续
后续补充 --mixed、--hard、--soft的基本使用