git - 在 Git 中的根提交之前插入一个提交?

标签 git version-control rebase git-rebase

我之前问过如何squash the first two commits在 git 存储库中。

虽然这些解决方案相当有趣并且不像 git 中的其他一些东西那样真正令人费解,但如果您需要在项目开发过程中多次重复该过程,它们仍然有点像众所周知的伤害包.

所以,我宁愿只经历一次痛苦,然后就可以永远使用标准的交互式 rebase 。

然后,我想做的是有一个空的初始提交,它的存在仅仅是为了成为第一个。没有代码,什么都没有。只是占用空间,所以它可以作为 rebase 的基础。

那么我的问题是,有了一个现有的存储库,我该如何在第一个提交之前插入一个新的空提交,并将其他所有人向前移动?

最佳答案

实现这一目标有 2 个步骤:

  1. 创建一个新的空提交
  2. 重写历史以从这个空提交开始

我们将把新的空提交放在临时分支上 newroot为了方便。

1。创建一个新的空提交

有多种方法可以做到这一点。

仅使用管道

最干净的方法是使用 Git 的管道直接创建一个提交,这样可以避免触及工作副本或索引或哪个分支被 checkout 等。

  1. 为一个空目录创建一个树对象:

    tree=`git hash-object -wt tree --stdin < /dev/null`
    
  2. 围绕它包装一个提交:

    commit=`git commit-tree -m 'root commit' $tree`
    
  3. 创建对它的引用:

    git branch newroot $commit
    

如果您足够了解您的 shell,您当然可以将整个过程重新安排到一行中。

没有管道

使用常规瓷器命令,您不能在不检查 newroot 的情况下创建空提交无缘无故地重复分支和更新索引和工作副本。但有些人可能会觉得这更容易理解:

git checkout --orphan newroot
git rm -rf .
git clean -fd
git commit --allow-empty -m 'root commit'

请注意,在缺少 --orphan 的非常旧版本的 Git 上切换到 checkout ,您必须将第一行替换为:

git symbolic-ref HEAD refs/heads/newroot

2。重写历史以从这个空提交开始

您在这里有两个选择: rebase 或重写干净的历史记录。

rebase

git rebase --onto newroot --root master

这具有简单的优点。但是,它还会更新分支上每次最后一次提交的提交者姓名和日期。

此外,对于一些边缘案例历史,它甚至可能由于 merge 冲突而失败——尽管事实上您正在 rebase 到一个不包含任何内容的提交上。

重写历史

更简洁的方法是重写分支。与 git rebase 不同,您将需要查找您的分支从哪个提交开始:

git replace <currentroot> --graft newroot
git filter-branch master

显然,重写发生在第二步;这是需要解释的第一步。什么git replace它的作用是告诉 Git,每当它看到对要替换的对象的引用时,Git 应该查看该对象的替换。

随着 --graft开关,你告诉它一些与平常略有不同的东西。你说还没有替换对象,但你想替换 <currentroot>提交具有自身精确副本的对象 except 替换的父提交应该是您列出的那个(即 newroot 提交)。那么git replace继续为您创建此提交,然后声明该提交将替换您的原始提交。

现在如果你做 git log , 你会看到事情已经如你所愿:分支从 newroot 开始.

但是,请注意 git replace 实际上不会修改历史记录 – 它也不会传播到您的存储库之外。它只是将本地重定向添加到您的存储库,从一个对象到另一个对象。这意味着没有其他人可以看到此替换的效果 - 只有您。

这就是为什么 filter-branch步骤是必要的。与 git replace您为根提交创建了一个具有调整后父提交的精确副本; git filter-branch然后对所有以下提交也重复此过程。这就是历史实际被重写的地方,以便您可以分享它。

关于git - 在 Git 中的根提交之前插入一个提交?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/645450/

相关文章:

eclipse - svn:将更改从分支合并到工作副本而不更新主干

git - 删除不需要的 merge 提交并使用 Git 改基

git - 将分支 A merge 到 B 但不 merge 已删除的文件

git - `git rebase` 没有更新分支?

Git:使用 git rebase 更改已推送的提交消息

java - 无法启动 kurento 存储库服务器

特定设备的 Android 源代码

git 忽略多个匹配文件

ruby - 如何使用 ruby​​-git 递归克隆远程存储库?

sql-server - 经常使用模式绑定(bind)和更新时如何处理数据库模式更新