【git使用】历史commit的分割(git rebase和 git reset的联合使用)
参考
- [译] 分割一个已存在的 git commit - 掘金
- Git - 重写历史
- idea git如何撤回提交 - PingCode
- git 工作原理与撤销操作图解 | Shall We Code?
分割一个已存在的 git commit
Git 与其他版本控制系统的主要区别之一,在于其允许用户重写历史。实现这一目的的主要途径则是 git reabse,通常还跟随着一句 git push --force 以用本地历史重写远端历史。
这里要谈论的是如何用rebase、reset 和 commit 来分割既有的提交。
比方说在一次 commit 中,包含了两个编辑过的文件(A 和 B);但你只想把其中的 A 引入当前分支,B 则不需要。
使用 git cherry-pick <commit-hash> 并不可行,因为它会把 A 和 B 的改变都拉过来。
解决方法是将那次 commit 分成两个,然后只 cherry-pick 包含了 A 的那个。
做法如下:
- 运行
git rebase -i <commit-hash>~(注意~),或者git rebase -i <hash-of-previous-commit>- 就是你想更改的 commit 的上一个 commit
- 在编辑窗口中找到要更改的那次 commit,将其前面的
pick改成edit- vim 形式改动
- 保存并退出 VIM
git reset HEAD~以重置阶段性的改变git add [files-to-add]所有本次需要用到的文件 (此处就是 A)- 正常的
git commit -m <message> - 一次或多次的将剩余的文件分别提交
- `git add [other-files-to-add]``
git commit
git rebase --continue以指示分割过程完成并退出变基操作
最后,就可以用 git cherry-pick <new-commit-hash> 将所需的新提交引入我们的分支中了。
# 1. git rebase 指定想要更改 commit 的前一个 commit,可以理解为 指定父节点,然后开始改动
git rebase -i <commit-hash>~ #(注意 `~`),
git rebase -i <hash-of-previous-commit>
# 2. 在编辑窗口中找到要更改的那次 commit,将其前面的 `pick` 改成 `edit`,退出后,git 会自动进行重演,停止到改为 edit 的 commit 处
# 3. 丢弃当前 commit,将此次 commit 变更文件放到工作区。
# 注意!执行该命令前,最好确认工作区和暂存区为空,否则会有些冲突
git reset HEAD~
# 4. 之后就和正常提交一样,执行 git add,git commit
# 5. 最后重演之后所有的 commit
git rebase --continue# 原理简单讲解
# 1. git rebase -i commit-id
# 就是对 commit-id 后面的所有 commit 进行重演,就是相当于你自己执行 git add、git commit 逐个提交 commit
# - pick 标志: 就是对 commit 进行不做改动的重演,直到遇到非 pick 标志的 commit 才会停止
# 注意若删除了某条 commit,该 commit 就不会重演了
# - edit 标志: 就是指定重演时,停止的位置,可以理解为该 edit 标志 commit 提交后停了下来,等待你的编辑;
# 编辑完成后,执行 git rebase --continue 继续重演后续的 commit
# - squash 标志: 可以将多个历史 commit 进行合并。未使用过,理解为就是将多个相邻的 squash 标志的commit 合并为一个 commit # 2. git reset HEAD~
# reset 就是重置 HEAD 指针的指向
# HEAD 可以理解为指针,指向最新的 commit
# HEAD~ 就是 HEAD 前1次的commit,即次新的 commit, HEAD~2 就是 HEAD 的前2次 commit
# 所以 git reset HEAD~ 就相当于,将 HEAD 指针向前移动 1 次,那么就会丢失最新的 commit
# 同理 git reset HEAD~2 就相当于,将 HEAD 指针向前移动 2 次,那么就会丢失最新的 2 个 commit
# 那么丢失的 commit 中的文件改动会哪去呢? —— 这就对应了 reset 的三种模式
# --mixed 模式: 也就是默认模式,会将所有丢失 commit 的文件改动等放到【工作区】
# --soft 模式: 也就是默认模式,会将所有丢失 commit 的文件改动等放到【暂存区】
# --hard 模式: 也就是默认模式,会将所有丢失 commit 的文件改动【丢弃】
# 所以,再执行 reset 前,最好将工作区和暂存区清空,否则可能有未注意到的合并,从而产生bug
# 另外执行 hard 模式要慎重,会造成文件的丢失
# 若不慎造成 commit 丢失,可以通过 reflog 进行恢复,但是无法恢复【工作区】和【暂存区】的文件丢失
解释样例
| +---------------+
+------------>| commit-D | HEAD
| +---------------+
| +---------------+
+------------>| commit-C | HEAD^ 或 HEAD~
| +---------------+
| +---------------+
+------------>| commit-B | HEAD^^ 或 HEAD~2
| +---------------+
| +---------------+
+------------>| commit-A | HEAD~3
| +---------------+
|
v
git rebase
-
Git - 重写历史
-
该命令主要用于修改历史 commit,如历史 commit 的拆分,合并等
-
注意使用方式
- 指定想要改动的 commit 的前一个 commit
- 如想要改动 commit-C,那就执行
git rebase -i commit-B或git rebase -i HEAD~2(或HEAD^^)
-
执行
git rebase -i commit-B后,会列出 commit-B 之后的所有 commit,之后 vim 形式操作- 在需要更改的 commit 前面,就将其前面的 pick 改为 edit,其他不变,保存 esc :q
- 若想将多个 commit 压缩为一个,就将其前面的 pick 改为 squash,其他不变,保存 esc :q
- 还有其他功能请自行百度
git reset
- idea git如何撤回提交 - PingCode
- git 工作原理与撤销操作图解 | Shall We Code?
- 可以理解为 调整 Head 指针的位置,将其后的 commit 释放( 默认模式会将历史 commit 的改动放回到工作区, hard 模式会丢弃)
- 如
git reset commit-B含义就是将 commit-B 之后的所有 commit 的更改恢复到工作区- 该命令等同于
git reset HEAD~2(或HEAD^^)
- 该命令等同于
- 若发现更改错误,可以通过 git reflog 查看历史记录,进行恢复
- 如
- git reset 有三种模式
| git reset | ||
|---|---|---|
| git reset --soft | 保留工作区,并把重置HEAD所带来的新的差异放进暂存区 | 注意可能会影响当前工作取的更改可能会覆盖历史的commit 的改动 (若当前工作区和历史 commit 对相同文件有改动) |
| git reset --mixed (等同于 git reset) | 保留工作区,并清空暂存区 | 注意可能会影响当前工作区的更改可能会覆盖历史的commit 的改动 (若当前工作区和历史 commit 对相同文件有改动) |
| git reset --hard | 重置工作区和暂存区 | 注意当前工作区的改动可能会丢失 (若当前工作区和历史 commit 对相同文件有改动) |
| 总结 | 最好在执行 reset 之前,清理干净工作区和暂存区,防止产生一些意外的变动无法评估 默认模式(mixed)会将历史 commit 的改动放回到工作区 hard 模式会丢弃 |
# 最好在执行 reset 之前,清理干净工作区和暂存区,防止一些意外的变动导致 bug
# hard 模式 慎用,可能会产生文件变动丢失
# 改动失误,造成丢失时,可尝试用 git reflog 查看历史记录,然后采用 git reset 进行恢复
版本回滚
如何指定回滚到哪里
HEAD 表示当前版本
HEAD^ 上一个版本
HEAD^^ 上上一个版本
HEAD~100 上100个版本,通用的
版本号 指定版本
可以配合不同的模式(–mixed, --soft, --hard)达到不同的效果。
首先查看commit日志
$ git log --pretty=oneline
1341074157aeb92de8caf982507d3f6c9280d5eb (HEAD -> master) commit 03
86b5d83fe42a1a9da8e96612a6c2c91f8e3e2001 commit 02
23dddd7b12606de10ed759cb72793d072ef2e48a commit 01
faa4214bc342ade5693a7efc8a64e869965c039e fix conflict
818c5faf28d0a0e5c8133dbd77dd24e6e70db9bf aaaaaaa
6f43203cf463dc5320916f96abef0f1ad63428fd (b1) xx
adda355046920ae91118cf42ec2f45190b0ec89c test
2e1b4bced0f0ce2c20362789be2878b36c6910f7 add t4
8262ea4e39ea80dc56056a667e9dbdcd235efc08 add t3
f2b85bf7f7516a6a6a0768e44266d09414b03a2e 2
01d308a7ef190b881969ea9b9112424819ab346a first commit
commit 01, commit 02, commit 03 为最近的三次提交,是提交时的备注信息。
HEAD -> master表示当前HEAD处于 master分支的1341074157aeb92de8caf982507d3f6c9280d5eb
我们回到上一个版本 commit 02 去,也就是 86b5d83fe42a1a9da8e96612a6c2c91f8e3e2001
$ git reset --hard HEAD^
HEAD is now at 86b5d83 commit 02或者 git reset --hard HEAD~1 或者 git reset --hard 86b5d83fe42a1a9da8e96612a6c2c91f8e3e2001
发现代码发生了变化,和预期一直。
再使用 git log 查看一下
$ git log --pretty=oneline
86b5d83fe42a1a9da8e96612a6c2c91f8e3e2001 (HEAD -> master) commit 02
23dddd7b12606de10ed759cb72793d072ef2e48a commit 01
faa4214bc342ade5693a7efc8a64e869965c039e fix conflict
818c5faf28d0a0e5c8133dbd77dd24e6e70db9bf aaaaaaa
6f43203cf463dc5320916f96abef0f1ad63428fd (b1) xx
adda355046920ae91118cf42ec2f45190b0ec89c test
2e1b4bced0f0ce2c20362789be2878b36c6910f7 add t4
8262ea4e39ea80dc56056a667e9dbdcd235efc08 add t3
f2b85bf7f7516a6a6a0768e44266d09414b03a2e 2
01d308a7ef190b881969ea9b9112424819ab346a first commit
发现 commit 03 已经看不到了,为什么呢?因为每一个commit只会保存它的parent节点,并不知道它的下一个节点时什么。那么问题来了,我又想回到 commit 03 该怎么办呢?
Git提供了一个命令git reflog用来记录你的每一次命令
$ git reflog
86b5d83 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
1341074 HEAD@{1}: reset: moving to 1341074157aeb92de8caf982507d3f6c9280d5eb
86b5d83 (HEAD -> master) HEAD@{2}: reset: moving to HEAD
86b5d83 (HEAD -> master) HEAD@{3}: reset: moving to HEAD^
1341074 HEAD@{4}: commit: commit 03
86b5d83 (HEAD -> master) HEAD@{5}: commit: commit 02
23dddd7 HEAD@{6}: commit: commit 01
找到 commit 03 这一条,1341074 就是第一个版本号。
$ git reset --hard 1341074
HEAD is now at 1341074 commit 03
哈哈哈,我又回来了。
相关文章:
【git使用】历史commit的分割(git rebase和 git reset的联合使用)
参考 [译] 分割一个已存在的 git commit - 掘金Git - 重写历史idea git如何撤回提交 - PingCodegit 工作原理与撤销操作图解 | Shall We Code? 分割一个已存在的 git commit Git 与其他版本控制系统的主要区别之一,在于其允许用户重写历史。实现这一目的的主要途…...
栈和队列oj题——225. 用队列实现栈
** 个人主页:晓风飞 专栏: 数据结构| Linux|| C语言 路漫漫其修远兮,吾将上下而求索 文章目录 题目要求:实现 MyStack 类:注意:示例:解释:提示: 解题核心数据结构的定义初…...
集合的三种遍历方式
迭代器(Iterator) 概述:Iterator 是个接口,迭代器是集合的专用遍历方式 使用方法,我们想要使用迭代器,必须首先得到集合对象,通过集合对象生成迭代器对象,才能进行集合的遍历 常用…...
Mysql 中的常用命令
在数字化世界中,数据库已经成为数据存储和处理的核心。而MySQL,作为最受欢迎的关系型数据库管理系统之一,其强大的功能和易用性使它成为开发者和企业的首选。掌握MySQL中的常用命令,是每一位数据库管理员和开发者的基本要求。本篇…...
【Java】CompletableFuture使用方法
背景 CompletableFuture是Java 8中引入的一个类,它实现了Future和CompletionStage接口,用于表示异步计算的结果。使用CompletableFuture可以方便地编写异步编程的代码,并且可以链式地组合多个异步操作。 接口 CompletableFuture实现了Future…...
摆烂式学习ssh
摆烂式学习ssh ssh工作原理ssh基本使用sshd配置文件密钥登录1.客户端2.服务器3.注意事项4.使用密钥登录测试 ssh高级使用技巧1.在非正规端口启动2.rsync 命令3.透过 ssh 通道加密原本无加密的服务4.以ssh信道配合x server 传递图形接口5.ssh配合virtualbox虚拟机使用技巧 ssh工…...
用 Python 抓取 bilibili 弹幕并分析!
01 实现思路 首先,利用哔哩哔哩的弹幕接口,把数据保存到本地。接着,对数据进行分词。最后,做了评论的可视化。 02 弹幕数据 平常我们在看视频时,弹幕是出现在视频上的。实际上在网页中,弹幕是被隐藏在源代码…...
目标检测YOLO实战应用案例100讲-基于红外图像处理的无人机光伏组件故障检测(续)
目录 3.2 自适应温度阈值故障检测算法设计 3.3 基于拟合灰度曲线的故障检测方案设计...
go mod 命令详解
文章目录 1.关于模块2.关于 go mod3.格式4.示例参考文献 1.关于模块 模块(Modules)是 Go 1.11 版本引入的一依赖管理机制。 一个模块是 Go packages 的集合,定义在项目根目录下的 go.mod 文件。go.mod 文件定义了模块的路径,这也…...
花了一小时,拿python手搓了一个考研背单词软件
听说没有好用的电脑端背单词软件?只好麻烦一下,花了一小时,拿python手搓了一个考研背单词软件。 代码已经开源在我的github上,欢迎大家STAR! 其中,数据是存放在sqlite中,形近词跳转是根据jaro …...
一篇文章学会Vim
一篇文章学会Vim 声明:以下内容均为我个人的理解,如果发现错误或者疑问可以联系我共同探讨 简介 Vim是一个高度可定制的终端文本编辑器,它可以很方便的创建和修改任何类型的文本。作为vi的升级版,有许多新的特性(以下列出的特性…...
面试算法91:粉刷房子
题目 一排n幢房子要粉刷成红色、绿色和蓝色,不同房子被粉刷成不同颜色的成本不同。用一个n3的数组表示n幢房子分别用3种颜色粉刷的成本。要求任意相邻的两幢房子的颜色都不一样,请计算粉刷这n幢房子的最少成本。例如,粉刷3幢房子的成本分别为…...
js逆向第11例:猿人学第4题雪碧图、样式干扰
任务4:采集这5页的全部数字,计算加和并提交结果 打开控制台查看请求地址https://match.yuanrenxue.cn/api/match/4,返回的是一段html网页代码 复制出来格式化后,查看具体内容如下: <td><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAA…...
OpenEular23.09(欧拉)操作系统为企业搭建独立的K8S集群环境,详细流程+截图
一.环境; win10,vmware16 pro,openeular23.09,linux内核 6.4.0-10.1.0.20.oe2309.x86_64, docker-engine 2:18.09.0-328,kubernetes 1.25.3,containerd 1.6.22,calico v3.25 集群…...
学生成绩管理系统半成品
C语言的老师在给我们讲指针的时候,讲的并不深入,她用了一个学生成绩管理系统来引入指针这个东西并给我们讲解,但我觉得她的管理系统功能有一些不足,并且不是很美观,所以说心血来潮,自己也动手写了一个学生成…...
国家信息安全水平等级考试NISP二级题目卷⑤(包含答案)
国家信息安全水平等级考试NISP二级题目卷(五) 国家信息安全水平等级考试NISP二级题目卷(五)需要报考咨询可以私信博主! 前言: 国家信息安全水平考试(NISP)二级,被称为校园版”CISP”,由中国信息…...
4.快速实现增删改查,模糊查询功能
打开springboot项目,在com.example下建包common,在common下新建Result.java 4.1封装统一的返回数据结构 1.在Result.java中编写如下代码: private static final String *SUCCESS*"0"; private static final String *ERROR*"-1"; p…...
【Redux】自己动手实现redux和react-redux
1. React提供context的作用 在class组件的世界里,如果后代组件共享某些状态,比如主题色、语言键,则需要将这些状态提升到根组件,以props的方式从根组件向后代组件一层一层传递,这样则需要在每层写props.someData&#…...
代码随想录算法训练营day6|242.有效的字母异位词、349.两个数组的交集、202.快乐数
哈希表理论基础 建议:大家要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。 什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时…...
2024.1.4每日一题
LeetCode每日一题 2397.被列覆盖的最多行数 2397. 被列覆盖的最多行数 - 力扣(LeetCode) 题目描述 给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix ;另给你一个整数 numSelect,表示你必须从 matrix 中选择的 不同 …...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
