(原创实践+看不懂找我)git回滚代码

240 阅读6分钟

平时多留意、回滚是迫不得已、少用慎用 | 疑则不用、用则不疑

平时多留意、回滚是迫不得已、少用慎用 | 疑则不用、用则不疑

平时多留意、回滚是迫不得已、少用慎用 | 疑则不用、用则不疑

git resetgit revert 是 Git 中用于撤销提交的两个命令,它们的区别在于带给你的工作量和影响范围。

一、先说结论

1. 基本

  • git reset 是截断到某一个commit生效(包含)。
  • git revert 是截断到某一个commit(不包含),解决冲突之后,才生效。

2. 使用场景

  • git reset 适用于 上线之后,发现问题,及时回滚到一个稳定的版本。因为这时候,能确保你操作的时候别人不会合并代码,没有冲突快速高效。任何有权限的人都可以无脑回滚
  • git revert 适用于 要解冲突的文件很少,并且你有自信解决冲突时足够熟悉和自信必须是非常有把握的人才可以回滚,适用于需求开发阶段,少用于线上回滚

二、初始状态

1. 当前文件内容

image.png

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. 当前文件内容

有冲突(因为是改动的同一个文件) image.png

解决冲突(选择新引入的内容),文件内容变为 image.png

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. 当前文件内容

很清晰明了

image.png

执行 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

得到的文件内容如下

image.png

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 中,有三个主要的区域(或者称为状态)用于管理代码的版本控制和变更记录:

  1. 工作区(Working Directory):工作区是指开发者当前正在工作的目录,其中包含项目的实际文件。可以使用 git add 命令将其添加到暂存区
  2. 暂存区(Staging Area 或 Index):通过git commit提交到版本库中生效。
  3. 版本库(Repository 或 Commit History):版本库是存储代码完整历史记录的地方。它包含了所有的提交记录(commit)。后续通过git push就可以让远程的别人看到你的这次提交了。如果是个人本地开发,不使用git push也没问题。

基本的 Git 工作流程如下:

  1. 修改工作区的文件。
  2. 使用 git add 命令将修改的文件添加到暂存区。
  3. 使用 git commit 命令将暂存区的文件提交到版本库,创建一个新的提交记录。

通过这种方式,Git 将代码的版本控制过程分为了三个区域,允许开发者更加灵活地管理和跟踪代码的变化。

六、后续

后续补充 --mixed、--hard、--soft的基本使用