0


【笔记】Git|将git仓库中所有的 commit 合成一个,清空所有 git 提交记录

在对代码进行开源时,我们往往并不希望代码开发过程中的提交记录被其他人看到,因为提交的过程中往往会涵盖一些敏感信息。因此会存在

将仓库中所有 commit 合成一个

的需求。

直觉上,往往会用 rebase 和 squash 或 reset,不过我尝试了一下存在问题,会出现最后仍然剩两个 commit 的情况。

接下来分享三种可用的方式,并简单介绍一下为什么不用

rebase

文章目录

方式一:git commit --amend(官方建议)

这一种方式意思就是追加提交,最符合 git 的使用原则,也最轻量。我建议使用这种方式,这也是 git 官方建议的方式。

首先在 github 网页上或者使用

git log

查看第一个 commit 的 id,然后运行:

git reset --soft<第一个 commit 的 id>git commit --amend

这两行指令的含义是:

  1. 将当前分支的状态切换到第一个提交中,并保留本地的修改以及暂存区的设置;
  2. 将现在的暂存区的内容直接 amend 到前一个提交(在这里指的就是第一个 commit)。

运行这两行指令之后,将会弹出一个新的编辑框,要求填写 commit message。默认的 commit message 就是你的第一个提交的 commit 信息,如果你需要修改,就修改一下。

在这里插入图片描述

更多配置

  1. 如果不希望保留第一个 commit 的作者信息,可以加参数--reset-authorgit commit --amend --reset-author
  2. 如果希望不要修改作者和日期,可以加参数--no-editgit commit --amend --no-edit
  3. 如果希望修改日期,可以加参数--date,例如:git commit --amend--date"Mon Aug 1 12:23:11 2022 +0800"

以上配置均可以组合使用。

方式二:新建本地的 git 仓库

这种方式是最直观直接的,新建了当然什么都没有了咯。
不过操作起来比较麻烦,需要删除文件夹、调整当前的目录。

# 1. 删除当前目录的 .git/ 文件夹# 2. 新建 git 仓库git init
# 3. 建立当前 git 目录与远端仓库的关系git remote add origin [email protected]:user/repo
# 4. 重新添加所有文件并提交gitadd.git commit -m'message'# 5. 对远端仓库强制更新git push -f origin master

方式三:新建空白的子分支

这种方式也很直观,就是新建空白子分支,再将子分支直接命名为原来的主分支,李代桃僵。
不过在推送时有点邪门,弄不好也容易出错,不建议使用,不过可以用来了解一下

orphan

参数。

# 1. 新建一个空白分支git checkout --orphan<分支名># orphan 代表这个分支是一个初始提交# 2. 重新添加所有文件并提交gitadd.git commit -m"new"# 3. 删除原来的主分支git branch -D master
# 4. 将新建的空白分支的名称改成mastergit branch -m master
# 5. 对远端仓库强制更新git push -f origin master --set-upstream

注意,主分支有可能叫做

main

,也有可能叫做

master

为什么不建议用 rebase 进行该合并操作?

rebase 用于压缩 commit 的时候,往往是这样的过程:

  1. git rebase -i HEAD~n,其中 n 是需要合并的 commit 数量;
  2. 弹出新的编辑窗口,选择(pick)一个分支,压缩(squash)其他分支:pick commitids commitid1s commitid2
  3. 保存并退出。

rebase 这个 git 指令仅看名字,意思大概是重新设置一下 base commit。因此它在使用时,是需要有一个 base commit 的,它的 pick、squash 等操作,都是基于这个 base 去做的。

就拿上述所说的过程中的第二步解释,在这一步中,其 base commit 其实是

commitid

parent commit

,它实际上做的操作,是先切换到 parent commit,然后再在 parent commit 里去进行

cherry-pick

squash

操作。然后再重新提交。

而你无法使用 rebase 去合并仓库中的所有 commit 的原因,也仅仅是因为它的机制:

  1. 最初的那个 commit,它没有它的 base commit。所以你无法使用 rebase 去 pick 第一个 commit。
  2. 当你每个 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 命令行就已经显示了这个问题的所有解决方案:

  1. 你可以修改你的 rebase 操作,使用 git rebase --edit-todo,让它 pick 第二个 commit、基于第一个 commit,这样起码能够保留你的代码文件,只是第一个 commit 会多余。
  2. 你可以使用git commit --amend操作,只是做简单的追加操作,而不是像现在这样使用 rebase 乱来。具体可以参考本文的方式一
  3. 你可以重新执行 rebase 操作,使用 git rebase --continue,如果你坚持觉得自己是正确的话。(当然,这样做只会导致继续报错罢了)

综上所述,我为了讲清楚为什么不在合并所有 commit 的时候使用 rebase,简单地思考并描述了一下 rebase 的原理和机制,希望对遇到这个问题的人有所帮助。

另外,大部分机制是直接通过操作看或猜出来的,仅结合 git 输出信息,并未结合官方的描述文档,若有错误,还请在评论区留言指正。

本账号所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_46106285/article/details/130459829。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

标签: git github

本文转载自: https://blog.csdn.net/qq_46106285/article/details/130459829
版权归原作者 shandianchengzi 所有, 如有侵权,请联系我们删除。

“【笔记】Git|将git仓库中所有的 commit 合成一个,清空所有 git 提交记录”的评论:

还没有评论