【git使用】历史commit的分割(git rebase和 git reset的联合使用)

参考

  • [译] 分割一个已存在的 git commit - 掘金
  • Git - 重写历史
  • idea git如何撤回提交 - PingCode
  • git 工作原理与撤销操作图解 | Shall We Code?

分割一个已存在的 git commit

Git 与其他版本控制系统的主要区别之一,在于其允许用户重写历史。实现这一目的的主要途径则是 git reabse,通常还跟随着一句 git push --force 以用本地历史重写远端历史。

这里要谈论的是如何用rebaseresetcommit 来分割既有的提交。

比方说在一次 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-Bgit 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

哈哈哈,我又回来了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/604464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法】和为K的连续子数组

牛客链接&#xff1a;https://www.nowcoder.com/practice/704c8388a82e42e58b7f5751ec943a11?tpId196&&tqId37127&rp1&ru/ta/job-code-total&qru/ta/job-code-total/question-ranking 使用【前缀法】&#xff0c;把所有连续和合索引存进哈希表&#xff0c…

2024阿里云服务器可用区选择方法

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

Dockerfile的EXPOSE

文章目录 环境总结测试使用EXPOSE测试1&#xff1a;不做端口映射测试2&#xff1a;-p 8080:80测试3&#xff1a;-P测试4&#xff1a;--networkhost 不使用EXPOSE 参考 环境 RHEL 9.3Docker Community 24.0.7 总结 如果懒得看测试的详细信息&#xff0c;可以直接看结果&#…

使用is跳转页面的几种方法

1&#xff0c;open() 打开一个新的浏览器窗口 <input type"button" value"去往新窗口按钮" onclick"fun1()">function fun1() {window.open("https://blog.csdn.net/daxiang12092205/article/details/11878477/")} 2&#xff…

二叉树的深度和高度问题(算法村第八关白银挑战)

二叉树的最大深度 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null…

11.perror函数的使用

文章目录 perror函数介绍简介&#xff1a; 测试代码 perror函数介绍 函数原型&#xff1a;void perror(char const *message); 简介&#xff1a; perror函数&#xff0c;以一种简单、统一的方式报告错误。标准库函数在一个外部整型变量errno&#xff08;在errno.h中定义&…

阿里云大数据ACA及ACP复习题(61~80)

61.网络爬虫又称为网络机器人、网络蜘蛛&#xff0c;也可以称它是一种(A)工具 A:从互联网自动提取网页中数据的工具 B:一种病毒软件 C:沉迷于网络有网瘾的人的代称 D:以上都不对 解析&#xff1a;网络爬虫&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社…

JavaWeb——后端案例

五、案例 1. 开发规范—Restful REST&#xff08;Representational State Transfer&#xff09;&#xff0c;表述性状态转换&#xff0c;是一种软件架构风格 注&#xff1a; REST是风格&#xff0c;是约定方式&#xff0c;不是规定&#xff0c;可以打破描述模块的功能通常使…

RA4000CE (RTC模块)适用于汽车,工作温度范围宽,稳定性高

RA4000CE是一个集成了32.768 kHz数字温度补偿晶体振荡器(DTCXO)的RTC模块&#xff0c;适用于汽车&#xff0c;工作温度范围宽&#xff0c;稳定性高。它包括各种功能&#xff0c;如具有闰年校正的秒到年时钟/日历&#xff0c;时间警报&#xff0c;唤醒计时器&#xff0c;时间更新…

ubuntu解决在pycharm上使用jupyter无法导入虚拟环境中的包的问题

ubuntu解决在pycharm上使用jupyter无法导入虚拟环境中的包的问题 根本原因是jupyter 没有和他对应的kernel 需要先使用命令行建立kernel 下载ipykernel pip install ipykernel 首先激活conda conda activate然后添加你的kernel到虚拟环境 python -m ipykernel install -…

P4994 终于结束的起点————C

目录 终于结束的起点题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示样例 1 解释数据范围提示 解题思路Code运行结果 终于结束的起点 题目背景 终于结束的起点 终于写下句点 终于我们告别 终于我们又回到原点 …… 一个个…

stable diffusion 进阶教程-controlnet详解(持续更新中)

说明 插件下载链接:https://pan.baidu.com/s/1-qmJzqcB72nTv_2QLmR-gA?pwd=8888 提取码: 8888 讨论Q群:830970289 个人微信:mindcarver 如果在按着教程尝试的过程中有错误或问题,可以上面询问讨论,或者评论区留言 如果教程有什么问题,请帮忙纠正,持续更新(部分控制插件…

Android WiFi 连接

Android WiFi 连接 1、设置中WiFi显示2、WiFi 连接流程2.1 获取PrimaryClientModeManager2.2 ClientModeImpl状态机ConnectableState2.3 ISupplicantStaNetworkCallback 回调监听 3、 简要时序图4、原生低层驱动5、关键日志 1、设置中WiFi显示 Android WiFi基础概览 packages/a…

【英文时评】太卷了?今年流行“逆向考研”

视频链接&#xff1a;【英文时评】太卷了&#xff1f;今年流行“逆向考研”_哔哩哔哩_bilibili 重要短语or词汇 陌生短语or词汇 Hello and welcome back to YYDS with me Liao. Much has happened since you missed our show. A new phenomenon has occured more undergradu…

关于对象存储的若干事

引言 最近在阅读鸣嵩的一篇文章&#xff0c;数据库的下一场革命&#xff1a;S3 延迟已降至原先的 10%&#xff0c;云数据库架构该进化了 收获很多&#xff0c;过去时间也基于对象存储做过一些功能实现&#xff0c;特记录下。关于鸣嵩&#xff1a; 曹伟&#xff0c;花名鸣嵩&am…

C++-构造与解析

构造函数 构造函数是与同类名的特殊成员函数&#xff0c;主要用来初始化对象的数据成员。 构造函数的特点&#xff1a; 与类同名没有返回类型可以被重载由系统自动调用&#xff0c;不允许在程序中显示调用。 #include <iostream> using namespace std;class student{…

用友NC word.docx 任意文件读取漏洞复现

0x01 产品简介 用友NC是一款企业级ERP软件。作为一种信息化管理工具,用友NC提供了一系列业务管理模块,包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等,帮助企业实现数字化转型和高效管理。 0x02 漏洞概述 用友NC 系统word.docx等接口存在任意文件…

JavaScript 基础二part1.运算符:赋值、一元、比较、逻辑运算符

JavaScript 基础二 1.1 赋值运算符1.2 一元运算符自增运算符的用法&#xff1a;例题 1.3 比较运算符不同类型间的比较严格相等对 null 和 undefined 进行比较 1.4 逻辑运算符例题 1.5 运算符优先级 1.1 赋值运算符 赋值运算符&#xff1a;对变量进行赋值的运算符 已经学过的赋…

光速爱购--靠谱的SpringBoot项目

简介 这是一个靠谱的SpringBoot项目实战&#xff0c;名字叫光速爱购。从零开发项目&#xff0c;视频加文档&#xff0c;十天就能学会开发JavaWeb项目。 教程路线是&#xff1a;搭建环境> 安装软件> 创建项目> 添加依赖和配置> 通过表生成代码> 编写Java代码&g…

2023年12 月电子学会Python等级考试试卷(四级)答案解析

青少年软件编程(Python)等级考试试卷(四级) 分数:100 题数:38 一、单选题(共25题,共50分) 1. 下列有关分治算法思想的描述不正确的是?( ) A. 将问题分解成的子问题具有相同的模式。