Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >head/reset/revert/rebase代码回滚全解:git提交记录的背后原理

head/reset/revert/rebase代码回滚全解:git提交记录的背后原理

原创
作者头像
周陆军博客
发布于 2023-04-09 15:04:12
发布于 2023-04-09 15:04:12
2.9K00
代码可运行
举报
文章被收录于专栏:前端博客前端博客
运行总次数:0
代码可运行

多人合作程序开发的过程中,我们有时会出现错误提交的情况,此时我们希望能撤销提交操作,让程序回到提交前的样子,操作有:

回退(reset):reset是彻底回退到指定的commit版本,该commit后的所有commit都将被清除;reset执行后不会产生记录

反转(revert):revert仅是撤销指定commit的修改,并不影响后续的commit。revert执行后会产生记录。

reset,revert都有撤销、回退的意思,但却各有千秋,区别还是很大的,所以该使用哪种命令一定要结合实际情况来决定。要搞清这些,还是得多学习下git基础知识。

Git 的四个工作区域

  • 工作区:也称工作目录、工作副本,简单来说就是 clone 后我们看到的包含项目文件的目录。我们日常开发操作也是在工作区中进行的。
  • 本地仓库(.git):在工作区中有个隐藏目录.git,这就是 Git 本地仓库的数据库。工作区中的项目文件实际上就是从这里签出(checkout)而得到的,修改后的内容最终提交后记录到本地仓库中。 Tips:不要手动修改 .git 目录的内容
  • 暂存区:也称缓存区,逻辑上处于工作区和本地仓库之间,主要作用是标记修改内容,暂存区里的内容默认将在下一次提交时记录到本地仓库中。
  • 远端仓库:团队协作往往需要指定远端仓库(一般是一个,也可以有多个),团队成员通过跟远端仓库交互来实现团队协作。

一个基本的 Git 工作流程如下:

  1. 在工作区中修改文件
  2. 暂存文件,将文件存放在暂存区
  3. 将改动从暂存区提交到本地仓库
  4. 从本地仓库推送到远端仓库

git的版本管理,及HEAD的理解

使用git的每次提交,Git都会自动把它们串成一条时间线,这条时间线就是一个分支。

如果没有新建分支,那么只有一条时间线,即只有一个分支,在Git里,这个分支叫主分支,即master分支。

有一个HEAD指针指向当前分支(只有一个分支的情况下会指向master,而master是指向最新提交)。

每个版本都会有自己的版本信息,如特有的版本号、版本名等。如下图,假设只有一个分支:

还需了解的术语

  • HEAD:这是当前分支版本顶端的别名,也就是在当前分支你最近的一个提交
  • Index:index也被称为staging area,是指一整套即将被下一个提交的文件集合。他也是将成为HEAD的父亲的那个commit
  • Working Copy:working copy代表你正在工作的那个文件集
  • Flow:git项目管理的流程和规划。比如分支规划:Master/Devlop 分支、Feature 分支、Release 分支、Hotfix 分支

理解 Git 处理分支的方式

  1. commit 操作会为每目录每一个文件计算hash校验,然后在 Git 仓库中将这些校验和保存为树对象
  2. 随后,Git 会创建一个提交对象(commit object)。该提交对象会包含一个指向暂存内容快照的指针。还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。
  3. 然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交。
  4. 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象,

Git 仓库中有五个对象:

三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。

Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照

HEAD是指当前的快照

这个命令主要配合reset的--hard,--mixed和--solf三个参数对对本次的修改进行处理

  • HEAD~1指回退一个快照,可以简写为HEAD~
  • HEAD~2指回退两个快照,
  • HEAD^主要是控制merge之后回退的方向
  • HEAD~才是回退的步数

通过命令行删除远程和本地提交记录

常见的代码回滚场景

回滚场景:仅在工作区修改时

当文件在工作区修改,还没有提交到暂存区和本地仓库时,可以用 git checkout -- 文件名 来回滚这部分修改。

执行以下命令回滚工作区的修改:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git checkout -- build.sh

不过需要特别留意的是这些改动没有提交到 Git 仓库,Git 无法追踪其历史,一旦回滚就直接丢弃了。

示例: 用 git status 查看,还没提交到暂存区的修改出现在 “Changes not staged for commit:” 部分。

回滚场景:已添加到暂存区时

即执行过 git add 添加到暂存区,但还没 commit,这时可以用 git reset HEAD 文件名 回滚。

执行以下命令回滚暂存区的修改:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git reset HEAD build.sh

回滚后工作区会保留该文件的改动,可重新编辑再提交,或者 git checkout -- 文件名 彻底丢弃修改。

回滚场景:已 commit,但还没有 push 时

即已经提交到本地代码库了,不过还没有 push 到远端。这时候可用 git reset 命令,命令格式为:

git reset <要回滚到的 commit> 或者 git reset --hard <要回滚到的 commit>

需注意的是,提供的是 要回滚到的 commit,该 commit 之后的提交记录会被丢弃

回滚场景:已 push 到远端时

注意!此时不能用 "git reset",需要用 "git revert"!

重要事情说三遍!之所以这样强调,是因为 "git reset" 会抹掉历史,用在已经 push 的记录上会带来各种问题;而 "git revert" 用于回滚某次提交的内容,并生成新的提交,不会抹掉历史。

命令

是否抹掉历史

适用场景

git reset

是,回滚的历史将消失

本地未push的记录

git revert

否,历史记录保留,回滚后重新生成提交记录

回滚已push的内容

git reset回滚某次提交

确保还没其他人提交之前,进行强制回滚——重置HEAD(当前分支的版本顶端)到另外一个commit

git reset --hard HEAD~2

  •  git reset 代码撤回
  • --hard 和 --soft 及默认mixed
    • --hard就是删除提交记录并不保存所删除记录所做的更改——将重置HEAD返回到另外一个commit 重置index以便反映HEAD的变化,并且重置working copy也使得其完全匹配起来。这是一个比较危险的动作,具有破坏性,数据因此可能会丢失!
    • --soft 虽然删除了最近两个提交记录,但是还保存了提交所做的更改——告诉Git重置HEAD到另外一个commit,但也到此为止 index,working copy都不会做任何变化,所有的在original HEAD和你重置到的那个commit之间的所有变更集都放在stage(index)区域中。
    • --mixed是reset的默认参数。它将重置HEAD到另外一个commit,并且重置index以便和HEAD相匹配,但是也到此为止。 working copy不会被更改。所有该branch上从original HEAD(commit)到你重置到的那个commit之间的所有变更将作为local modifications保存在working area中,(被标示为local modification or untracked via git status),但是并未staged的状态,你可以重新检视然后再做修改和commit
  • 数字代表回退几个版本

git push -f ////强制覆盖

记住git reset不会产生commits,它仅仅更新一个branch(branch本身就是一个指向一个commit的指针)指向另外一个commit(Head和branch Tip同时移动保持一致).其他的仅剩对于index和work tree(working directory)有什么影响。git checkout xxxCommit则只影响HEAD,如果xxxCommit和一个branch tip是一致的话,则HEAD和branch相匹配,如果xxxCommit并不和任何branch tip相一致,则git进入detached HEAD 状态

如果别已经提交了代码,怎么删除远程的历史提交记录

删除提交记录中间的提交

git reset --hard 2b93fa8bdc8a1ca8e0c7498bd56460e6d1c408d1 //跟版本号

git push origin HEAD --force

关闭分支的protected权限

但是,你根据上面命令,确无法操作成功,比如报如下提示:

 ! [remote rejected] master -> master (pre-receive hook declined)

这个分支权限被限制了

settings/repository/Protected Branches  ->un protected

git revert放弃某次提交

git revert 之前的提交仍会保留在git log中,而此次撤销会做为一次新的提交。

revert和reset 操作上都差不多,不同的是:

  • git revert 是撤销某次操作,此次操作之前的commit都会被保留
  • git reset 是撤销某次提交,但是此次之后的修改都会被退回到暂存区
  • git reset操作会将版本回退至指定的commit,指定commit后的操作都将被撤销
  • 而git revert则撤销指定commit的修改,同时生成一个新的commit

git rebase 重建提交顺序

git rebase --onto

然后开始删除提交记录2,3[执行 rebase 时会可能遇到冲突,解决冲突不在本文描述范围

git rebase --onto master~3 master~1 master

删除某条commit记录

git rebase -i     d65f0fba23f2113ece6fbb3d104a33a1a8a80406

会进入vim模式,pick改为drop即可,具体操作,查看:https://www.jianshu.com/p/520f8661659c

顺便推荐下:《git中merge还是rebase?git之圣战merge vs rebase 

参考文章:

Git 代码回滚与找回的艺术https://segmentfault.com/a/1190000039320926

git reset soft,hard,mixed之区别深解 https://www.cnblogs.com/kidsitcn/p/4513297.html

git 理解 HEAD^与HEAD~  https://blog.csdn.net/claroja/article/details/78858411

git reset revert rebase 区别 https://blog.csdn.net/lainegates/article/details/72897693

git reset 、rebase和 revert的区别 https://blog.csdn.net/rebeccachong/article/details/39379703

git reset与git revert的区别 https://segmentfault.com/a/1190000019153248

代码回滚:git reset、git checkout和git revert区别和联系 https://www.cnblogs.com/houpeiyong/p/5890748.html

git中reset和revert的区别是什么 https://www.php.cn/tool/git/485052.html

Git恢复之前版本的两种方法reset、revert(图文详解) https://blog.csdn.net/yxlshk/article/details/79944535

转载本站文章《head/reset/revert/rebase代码回滚全解:git提交记录的背后原理》, 请注明出处:https://www.zhoulujun.cn/html/tools/VCS/git/4828.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Git撤销&回滚操作(git reset 和 get revert)
俗话说,老虎也有打盹的时候。我们提交代码,也会有出错的时候。 我今天不小心把不该提交的文件给提交了。
赵云龙龙
2020/02/13
38.3K0
Git撤销&回滚操作(git reset 和 get revert)
代码管理工具的扛把子-Git
但是最近小❤发现很多人(包括我自己)只熟悉日常代码的拉取和提交,连 git revert/rebase 都不知道怎么用,太尴尬了 T.T
xin猿意码
2023/10/18
3340
代码管理工具的扛把子-Git
如何使用 Git Rebase 优雅回退代码?
使用命令 git revert commit_id 能产生一个 与 commit_id 完全相反的提交,即在 log 中会看到一条新的提交 new_commit_id, revert 提交就是删除 commit_id 的提交。
Yorkyu
2022/03/22
4.8K0
如何使用 Git Rebase 优雅回退代码?
Git 的一些事
假设远程分支上有2个提交,然后基于远程develop,再创建一个分支feature。
腾讯工蜂
2018/11/20
11.6K0
Git 教程 -- 基于自己学习记录
由于学校布置了一项熟悉 git 和 svn 操作的实验,所以自己重新温习了下 git,记录过程在这。
希希里之海
2019/04/17
7120
Git 教程 -- 基于自己学习记录
珍藏多年的 Git 问题和操作清单
本文整理自工作多年以来遇到的所有 Git 问题汇总,之前都是遗忘的时候去看一遍操作,这次重新整理了一下,发出来方便大家收藏以及需要的时候查找答案。
猿天地
2019/09/03
1.4K0
珍藏多年的 Git 问题和操作清单
程序员必备基础:Git 命令全方位学习
掌握Git命令是每位程序员必备的基础,之前一直是用smartGit工具,直到看到大佬们都是在用Git命令操作的,回想一下,发现有些Git命令我都忘记了,于是写了这篇博文,复习一下~
捡田螺的小男孩
2020/07/02
7670
【干货】教你打通Git的任督二脉
分布式版本控制系统( Distributed Version Control System,简称 DVCS )。
狼王编程
2021/06/01
4340
【干货】教你打通Git的任督二脉
Git 代码回滚与找回的艺术
Git 是一个灵活和强大的版本管理工具,正确使用能够有效促进团队协作,防止版本丢失。然而实践中,有些开发人员会或有意或无意地误用部分 Git 的功能,给团队带来困扰,甚至造成损失。不恰当的代码回滚操作是其中的主要问题之一。
腾讯云 CODING
2021/03/02
1.6K0
Git 代码回滚与找回的艺术
三年 Git 使用心得 & 常见问题整理
「使用场景:」 当你接到一个修复紧急 bug 的任务时候,一般都是先创建一个新的 bug 分支来修复它,然后合并,最后删除。但是,如果当前你正在开发功能中,短时间还无法完成,无法直接提交到仓库,这时候可以先把当前工作区的内容 git stash 一下,然后去修复 bug,修复后,再 git stash pop,恢复之前的工作内容。
Nealyang
2020/06/19
2.9K0
三年 Git 使用心得 & 常见问题整理
Git 很难么?带你从头到尾捋一遍,不信你学不会!
对于Git,相信大多数程序员并不会感到陌生。但是运用自如可不是一日之功,这可不,上次面阿里,就卡在了对 Git的各种理论理解与实际应用上。
民工哥
2022/04/08
6140
Git 很难么?带你从头到尾捋一遍,不信你学不会!
Git使用规范及命令
rebase没有产生新的节点,使用rebase的git演进路线(提交树)是一直向前的,这样在版本回退时也很容易;用merge的git路线是跳跃的,可以明确的知道是从哪个分支或节点修改的。
用户9645905
2024/06/02
1390
Git使用规范及命令
深入理解 git 一切皆 commit
git 入门教程推荐: 简介 - Git教程 - 廖雪峰的官方网站 Git入门图文教程(1.5W字40图)🔥🔥—深入浅出、图文并茂 - 安木夕 - 博客园
jgrass
2024/12/25
920
深入理解 git 一切皆 commit
Git如何恢复之前版本,reset/revert在命令行和IDEA上的操作步骤
原理: git reset的作用是修改HEAD的位置,即将HEAD指向的位置改变为之前存在的某个版本,如下图所示,假设我们要回退到版本一:
chenchenchen
2021/09/06
8.5K0
【工具箱】GIT的使用场景
无论学习什么技术,都需要了解该技术的本质。若是靠死记硬背该技术提供的方法或者语法,终归是知其然而不知其所以然,当发现错误时,你根本不知道是什么原因导致的。我在使用Git时,就处于这种知其然而不知其所以然的状态。现在,再来补补课。 Git有三个工作区域,分别为:工作目录(Working Directory)、暂存区(Stage或Index)以及资源库(Repository或Git Directory)。 参考Pro Git一书,它给出了Git的几个要点: 直接快照,而非比较差异:Git与其他版本管理系统的主要
张逸
2018/03/07
7300
【工具箱】GIT的使用场景
git初入门(二):文件操作
如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过 "git add" 添加到暂存区,然后执行以下命令:
传说之下的花儿
2023/09/16
4050
git初入门(二):文件操作
使用 Git,10个最需要常备的后悔药
https://segmentfault.com/a/1190000022951517
前端老道
2020/07/07
1K0
使用 Git,10个最需要常备的后悔药
Git入门:从零开始的版本控制之旅
1、虚拟机VMware安装Ubuntu 2、ubuntu安装openssh-server:
Lion Long
2024/08/12
1120
Git入门:从零开始的版本控制之旅
git命令
rebase若有冲突记得要手动解决冲突,然后使用git rebase —continue继续rebase操作
doper
2022/09/26
5140
git命令
Git总结
git在本地分为三个区域,工作区、暂存区和本地仓库,具体情况如下: git的一般操作就是本地代码的修改提交回滚,以及与远程仓库的拉取、合并、提交等。 git fetch   从远程仓库上抓取分支到本机
欠扁的小篮子
2018/04/11
6620
Git总结
相关推荐
Git撤销&回滚操作(git reset 和 get revert)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验