【五一创作】【笔记】Git|如何将仓库中所有的 commit 合成一个?又名,如何清除所有 git 提交记录?(附 git rebase 机制的简要分析)
在对代码进行开源时,我们往往并不希望代码开发过程中的提交记录被其他人看到,因为提交的过程中往往会涵盖一些敏感信息。因此会存在 将仓库中所有 commit 合成一个
的需求。
直觉上,往往会用 rebase 和 squash 或 reset,不过我尝试了一下存在问题,会出现最后仍然剩两个 commit 的情况。
接下来分享三种可用的方式,并简单介绍一下为什么不用 rebase
。
文章目录
- 方式一:git commit --amend(官方建议)
- 方式二:新建本地的 git 仓库
- 方式三:新建空白的子分支
- 为什么不建议用 rebase 进行该合并操作?
方式一:git commit --amend(官方建议)
这一种方式意思就是追加提交,最符合 git 的使用原则,也最轻量。我建议使用这种方式,这也是 git 官方建议的方式。
首先在 github 网页上或者使用 git log
查看第一个 commit 的 id,然后运行:
git reset --soft <第一个 commit 的 id>
git commit --amend
这两行指令的含义是:
- 将当前分支的状态切换到第一个提交中,并保留本地的修改以及暂存区的设置;
- 将现在的暂存区的内容直接 amend 到前一个提交(在这里指的就是第一个 commit)。
运行这两行指令之后,将会弹出一个新的编辑框,要求填写 commit message。默认的 commit message 就是你的第一个提交的 commit 信息,如果你需要修改,就修改一下。
注意,如果你不希望保留第一个 commit 的作者信息,你可以再加个参数--reset-author
,抹杀干净:
git commit --amend --reset-author
方式二:新建本地的 git 仓库
这种方式是最直观直接的,新建了当然什么都没有了咯。
不过操作起来比较麻烦,需要删除文件夹、调整当前的目录。
# 1. 删除当前目录的 .git/ 文件夹
# 2. 新建 git 仓库
git init
# 3. 建立当前 git 目录与远端仓库的关系
git remote add origin git@github.com:user/repo
# 4. 重新添加所有文件并提交
git add .
git commit -m 'message'
# 5. 对远端仓库强制更新
git push -f origin master
方式三:新建空白的子分支
这种方式也很直观,就是新建空白子分支,再将子分支直接命名为原来的主分支,李代桃僵。
不过在推送时有点邪门,弄不好也容易出错,不建议使用,不过可以用来了解一下 orphan
参数。
# 1. 新建一个空白分支
git checkout --orphan <分支名> # orphan 代表这个分支是一个初始提交
# 2. 重新添加所有文件并提交
git add .
git commit -m "new"
# 3. 删除原来的主分支
git branch -D master
# 4. 将新建的空白分支的名称改成master
git branch -m master
# 5. 对远端仓库强制更新
git push -f origin master --set-upstream
注意,主分支有可能叫做 main
,也有可能叫做 master
。
为什么不建议用 rebase 进行该合并操作?
rebase 用于压缩 commit 的时候,往往是这样的过程:
git rebase -i HEAD~n
,其中n
是需要合并的 commit 数量;- 弹出新的编辑窗口,选择(pick)一个分支,压缩(squash)其他分支:
pick commitid s commitid1 s commitid2
- 保存并退出。
rebase 这个 git 指令仅看名字,意思大概是重新设置一下 base commit。因此它在使用时,是需要有一个 base commit 的,它的 pick、squash 等操作,都是基于这个 base 去做的。
就拿上述所说的过程中的第二步解释,在这一步中,其 base commit 其实是 commitid
的 parent commit
,它实际上做的操作,是先切换到 parent commit,然后再在 parent commit 里去进行 cherry-pick
、squash
操作。然后再重新提交。
而你无法使用 rebase 去合并仓库中的所有 commit 的原因,也仅仅是因为它的机制:
- 最初的那个 commit,它没有它的 base commit。所以你无法使用 rebase 去 pick 第一个 commit。
- 当你每个 commit 都不 pick 的时候,压缩完了的 commit 将会不知道存给哪个 commit。
所以如果要使用 rebase 里提供的 squash(压缩)对所有分支进行压缩,压缩成唯一的一个 commit,那 rebase 操作时,要么无法找到 base commit 从而指令直接运行出错,要么你压缩完成之后 commit 不知道存给谁就报错。
而这些报错在处理起来,对于一个只想简单交个代码的人来说是比较难懂的。
如果你不相信,我这边提供一个例子。
假如现在总共有 3 个 commit,其中第一个 commit 的 id 是 d2d48778
,如下所示:
用 rebase 进行合并的时候,只能对最后两个 commit 进行操作。
如果你强行操作 3 个,运行的是如下指令:
git rebase -i HEAD~3
那你将会得到报错的结果fatal: invalid upstream 'HEAD~3'
:
如果你运行 git rebase -i HEAD~2
,那么将一切正常。
而如果你发觉不对劲,因此干脆直接去 rebase 第一个 commit,运行了如下指令:
git rebase -i d2d48778
那你将不会得到报错,但会得到如下编辑框,没有第一个 commit 的 id:
此时,直观上讲,我们肯定会不管不顾地将 pick 直接全改成 squash,期望出现奇迹。可是当我们保存并退出时,会发现出现的是报错error: cannot 'squash' without a previous commit
,要求必须选择一个此前的 commit 去作为压缩的结果存储的 commit:
既然如此,干脆手动新增一行 pick
行不行呢?强行指定第一个 commit 作为存储 squash 结果的 commit,如下所示:
实际上,这也不行。原因就在于第一个 commit 没有前一个 commit,根本不能被 cherry-pick。如果你真的这样做了,那么你会得到一个报错The previous cherry-pick is now empty, possibly due to conflict resolution.
,与我的描述一致,如下图所示:
你或许还注意到了 git 官方给出了一个解决办法,就是 git commit --allow-empty
,那么,它解决的结果是什么呢?当运行了这行指令之后,弹出新的编辑框要求输入 commit message,然后查看当前 git 日志,如下两图所示:
你会惊讶地发现,居然还是有两个提交。
更可怕的是,当你终于想起来去看看自己的 git 状态时,你会发现操作日志也没有了,rebase 也没执行,本地的修改也不见了。如下图所示:
虽然实际上,本地的修改其实还在 本地的 commit 文件里,但由于你也不知道到底怎么 rebase,在百般 rebase 失败之后,你或许已经忘记了最新代码的 commitid、或者已经失手推送更新了远端仓库、或者已经忘记了自己到底要改什么东西,最后的结果可能是让人崩溃的。
其实在 git status
时,git 命令行就已经显示了这个问题的所有解决方案:
- 你可以修改你的 rebase 操作,使用
git rebase --edit-todo
,让它 pick 第二个 commit、基于第一个 commit,这样起码能够保留你的代码文件,只是第一个 commit 会多余。 - 你可以使用
git commit --amend
操作,只是做简单的追加操作,而不是像现在这样使用 rebase 乱来。具体可以参考本文的方式一。 - 你可以重新执行 rebase 操作,使用
git rebase --continue
,如果你坚持觉得自己是正确的话。(当然,这样做只会导致继续报错罢了)
综上所述,我为了讲清楚为什么不在合并所有 commit 的时候使用 rebase,简单地思考并描述了一下 rebase 的原理和机制,希望对遇到这个问题的人有所帮助。
另外,大部分机制是直接通过操作看或猜出来的,仅结合 git 输出信息,并未结合官方的描述文档,若有错误,还请在评论区留言指正。
本账号所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_46106285/article/details/130459829。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。
相关文章:
【五一创作】【笔记】Git|如何将仓库中所有的 commit 合成一个?又名,如何清除所有 git 提交记录?(附 git rebase 机制的简要分析)
在对代码进行开源时,我们往往并不希望代码开发过程中的提交记录被其他人看到,因为提交的过程中往往会涵盖一些敏感信息。因此会存在 将仓库中所有 commit 合成一个 的需求。 直觉上,往往会用 rebase 和 squash 或 reset,不过我尝…...
如何写出高质量代码?
作为一名资深开发人员,写出高质量的代码是我们必须要追求的目标。然而,在实际开发中,我们常常会遇到各种问题。比如,代码的可读性、可维护性、健壮性和灵活性等,这些都会影响代码的质量。那么,究竟如何才能…...
外卖项目优化-01-redis缓存短信验证码、菜品数据、Spring Cache(注解开发缓存)、(注解开发)缓存套餐数据
文章目录 外卖项目优化-01课程内容前言1. 环境搭建1.1 版本控制解决branch和tag命名冲突 1.2 环境准备 2. 缓存短信验证码2.1 思路分析2.2 代码改造2.3 功能测试 3. 缓存菜品信息3.1 实现思路3.2 代码改造3.2.1 查询菜品缓存3.2.2 清理菜品缓存 3.3 功能测试3.4 提交并推送代码…...
Chapter1:控制系统数学模型(下)
第一章:控制系统数学模型 Exercise1.13 已知控制系统结构图如下图所示,求系统的输出 C 1 ( s ) C_1(s) C...
排序算法总结
常见排序算法的时间复杂度、空间复杂度及稳定性分析: 时间复杂度空间复杂度是否有稳定性基于比较的排序算法选择排序 O(N^2)O(1)否 冒泡排序O(N^2)O(1)是插入排序O(N^2)O(1)是归并排序O(N*logN)O(N),每次需要额外一个数组用于拷贝是快排O(N*log…...
java+jsp企业物流货运快递管理系统servlet
功能需求具体描述: (1)用户功能模块包括用户登录注册,用户信息的修改,用户发布货物信息,给客服人员留言,对运输公司进行评价。 (2)企业功能模块包括企业注册登录,企业信息的修改,受理用户发布的…...
【ROS仿真实战】获取机器人在gazebo位置真值的三种方法(三)
文章目录 前言一. 使用ROS tf库二、 使用Gazebo Model Plugin三、 使用libgazebo_ros_p3d插件四、总结 前言 在ROS和Gazebo中,获取机器人的位置信息通常通过ROS消息传递进行。在这篇文章中,我们将介绍三种获取机器人在Gazebo中位置真值的方法࿱…...
Winform从入门到精通(35)——FontDialog(史上最全)
文章目录 前言一、属性1、Name2、AllowScriptChange3、AllowSimulations4、AllowVectorFonts5、AllowVerticalFonts6、Color7、FixedPitchOnly8、Font9、FontMustExist10、MaxSize11、MinSize12、 ScriptsOnly13、ShowApply14、ShowColor15、ShowEffects16、ShowHelp...
AcWing 854. Floyd求最短路Floyd模板
Floyd算法: 标准弗洛伊德算法,三重循环,基于动态规划。 循环结束之后 d[i][j]存储的就是点 i 到点 j 的最短距离。 需要注意循环顺序不能变:第一层枚举中间点,第二层和第三层枚举起点和终点。 特点: 1.复杂…...
Graph Theory(图论)
一、图的定义 图是通过一组边相互连接的顶点的集合。 In this graph, V { A , B , C , D , E } E { AB , AC , BD , CD , DE } 二、图的类型 2.1 Finite Graph A graph consisting of finite number of vertices and edges is called as a finite graph. Null Graph Tri…...
[Python]生成 txt 文件
前段时间有位客户问: 你们的程序能不能给我们生成个 txt 文件,把新增的员工都放进来,字段也不需要太多,就要 员工姓名/卡号/员工编号/员工职位/公司 这些字段就行了,然后我们的程序会去读取这个 txt 文件,拿里面的内容,读完之后会这个文件删掉 我: 可以接受延迟吗?可能没办法实…...
GeoTools实战指南: 自定义矢量样式并生成截图
GeoTools实战指南: 自定义矢量样式并生成截图 介绍 本段代码的主要功能是将矢量数据(Shapefile)渲染成一张图片。 准备环境 首先,您需要将GeoTools库添加到您的项目中。使用Maven或Gradle添加依赖项,或者直接下载GeoTools的jar文件并添加到您的类路径中。 Maven <…...
深度学习超参数调整介绍
文章目录 深度学习超参数调整介绍1. 学习率2. 批大小3. 迭代次数4. 正则化5. 网络结构总结 深度学习超参数调整介绍 深度学习模型的性能很大程度上取决于超参数的选择。超参数是指在训练过程中需要手动设置的参数,例如学习率、批大小、迭代次数、网络结构等等。选择…...
Bootloader
本篇不作太过的技术了解,仅可作为初学者的参考。用嘴简单的语言讲清楚一件事。 项目中遇到Bootloader升级MCU,我很好这是什么软件,逻辑是什么,怎么升级的。 术语及定义 指纹信息fingerprint诊断仪用于标识特定的下载尝试的信息 …...
安卓开发_广播机制_广播的最佳实践:实现强制下线功能
安卓开发_广播机制_广播的最佳实践:实现强制下线功能 ActivityCollector类用于管理所有的ActivityBaseActivity类作为所有Activity的父类创建一个LoginActivity来作为登录界面布局LoginActivity 在MainActivity中加入强制下线功能布局MainActivity在BaseActivity中注…...
国民技术N32G430开发笔记(10)- IAP升级 Application 的制作
IAP升级 Application 的制作 1、App程序跟Bootloader程序最大的区别就是, 程序的执行地址变成了之前flash设定的0x08006000处, 大小限制为20KB 所以修改Application工程的ld文件 origin 改成 0x08006000 length 改成0x5000 烧录是起始地址也要改为x0x…...
[计算机图形学]材质与外观(前瞻预习/复习回顾)
一、图形学中的材质 不同的物体表面有着不同的材质,而不同的材质意味着它们与光线的作用不同。那么我们之前在介绍辐射度量学和渲染方程提到过其中一个函数,叫做BRDF,而在实际上,也就是BRDF定义了不同的材质。BRDF决定了光如何被反…...
Java 的简要介绍及开发环境的搭建(超级详细)
图片来源于互联网 目录 | CONTENT Java 简介 一、什么是 Java 二、认识 Java 版本 三、选择哪个版本比较好 搭建 Java 开发环境 一、下载 Java 软件开发工具包 JDK 二、配置环境变量 自动配置 手动配置 三、下载合适的 IDE IntelliJ IDEA Visual Studio Code Eclip…...
每天一道算法练习题--Day15 第一章 --算法专题 --- -----------二叉树的遍历
概述 二叉树作为一个基础的数据结构,遍历算法作为一个基础的算法,两者结合当然是经典的组合了。很多题目都会有 ta 的身影,有直接问二叉树的遍历的,有间接问的。比如要你找到树中满足条件的节点,就是间接考察树的遍历…...
golang - 函数的使用
核心化编程 为什么需要函数? 代码冗余问题不利于代码维护函数可以解决这个问题 函数 函数:为完成某一功能的程序指令(语句)的集合,称为函数 在 Go 中,函数分为:自定义函数(自己写…...
真题详解(极限编程)-软件设计(六十一)
真题详解(二分查找平均值)-软件设计(六十)https://blog.csdn.net/ke1ying/article/details/130417464 VLANtag属于 数据链路层实现。 数据链路层:网桥交换机。 网络层:路由器。 物理层:中继器。 Telent…...
计算机网络笔记:TCP粘包
默认情况下, TCP 连接会启⽤延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们. 如果短时间有多个数据发送, 会缓冲到⼀起作⼀次发送 , 这样可以减少 IO 消耗提⾼性能。 如果是传输⽂件的话, 那么根本不⽤处理粘包的问题, 来⼀个包拼⼀个包就好了。但是如果是多条消息, 或者…...
Vue(标签属性:ref、配置项:props、混入mixin、插件、样式属性:scroped)
一、ref(打标识) 前面提及到了标签属性:keys 这里将了解ref:打标识 正常布置脚手架并创建入口文件main.js,引入组件 1. 可以给元素注册引用信息(获取真实DOM) 给一个按钮获取上方的dom的方法,方…...
数仓建设规划核心问题!
小A进入一家网约车出现服务公司,负责公司数仓建设,试用期主要一项 OKR是制定数据仓库建设规划;因此小 A 本着从问题出发为原点,先对公司数仓现状进行一轮深入了解,理清存在问题,然后在以不忘初心原则提出解…...
容器镜像的导入导出
容器镜像的导入导出 第1关:导入导出容器 任务描述 本关任务是学习导入导出容器,要求学习者参照示例完成将busyboxContainer容器的文件系统保存为一个tar包,通过该tar包导入一个busybox:v1.0镜像。 相关知识 将 "容器的文件系统&…...
Java每日一练(20230502)
目录 1. 二叉搜索树的最近公共祖先 🌟🌟 2. 随机分组问题 🌟 3. K 个一组翻转链表 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练…...
JVM学习(九):堆
一、堆(Heap)的概述 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。 Java堆区在JVM启动的时候即被创建,其空间大小也就确定了。是JVM管理的最大一块内存空间。同时,堆内存的大小是可以调节的。《Java虚拟…...
golang - switch
switch 的使用 switch 语句用于基于不同条件执行不同操作,,直每一个 case 分支都是唯一的,从上到下逐一测试到匹配为止匹配项后面也不需要再加 break switch 表达式 {case 表达式1, 表达式2, ... :语句块1case 表达式2, 表达式3, ... :语句块…...
浙大数据结构与算法一些有意思的理论基础题
堆栈 有人给出了堆栈用数组实现的另一种方式,即直接在函数参数中传递数组和top变量(而不是两者组成的结构指针),其中Push操作函数设计如下。这个Push函数正确吗?为什么? #define MaxSize 100 ElementTyp…...
【热门框架】Mybatis-Plus怎样进行映射匹配兼容?Mybatis-Plus的ID有哪些生成策略
Mybatis-Plus提供了两种映射匹配兼容的方式:驼峰转下划线和全局配置。 驼峰转下划线 默认情况下,Mybatis-Plus会将Java类中的驼峰命名方式自动映射到数据库表中的下划线命名方式。例如,Java类中的userName属性会自动映射到表中的user_name字…...
网站建设有哪些基本流程/百度平台我的订单
TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的。 常规的用法大家都知道,现在来讨论它的一些高级的用法。 1、CommaText 2、Delimiter &DelimitedText 3、Names &Values &ValueFromIn…...
网站建设技术公司/百度seo网站优化服务
在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数。该函数的主要功能就是进行topology的任务分配(task assignment)。mk-assignments函数定义如下: ;; get existing a…...
goz建站/免费搭建自己的网站
Q1:怎么在html文件中调用js文件在html中调用js代码的方法主要有两种:一、将javascript直接写在html文件中,然后在html中调用js函数等;二、将js代码写一个文件中,然后在html中引用该文件,在使用js文件中定义…...
wordpress 取消评论/免费seo教程
首先生成两张数据表,一般要实现两张数据表之间的联系要建立第三张表,如下 数据表生成之后,生成一些测试数据,接下来就对表article_tag表进行操作 在模型文件中声明两张表之间的关系: 测试数据: 转载于:https://www.cnb…...
洛阳自助建站/网络优化器下载
1.首先是覆盖网络的概念 •覆盖网络 –在一个含有N个节点的网络中,将整个网络看做一个圆环,节点按标识符从小到大顺时针组成一个环。对象分配在节点n上,n是从节点标识符大于等于对象标识的节点开始顺时针方向遇到的第一个活着的节点。 •Cho…...
备案网站需要多久/bt搜索引擎最好用的
SOC常见问题解答 1.SOC FPGA中的ARM是软核还是硬核?ARM核的外设是软核还是硬核? SOC FPGA 中的ARM核是硬核。所以简称HPS,Hardware Processor System 2.ARM处理器核是包含于FPGA逻辑单元内部的吗? 如下图所示。刚开始接触SOC FPGA…...