Git:如何将现有的“merge”转换为“merge --squash”?

2024-02-21

我表演了多次merge承诺但他们应该是merge --squash反而。解决冲突花了一天多的时间,所以我无法手动重新进行合并。

有没有办法转换merge to merge --squash ?


这里值得注意的是git merge and git merge --squash密切相关,但是git merge --squash 不创建合并.

这里的措辞非常重要,特别是“merge”前面的冠词“a”:“a merge”是名词,而“to merge”是动词。两个命令都执行合并操作。区别在于结果如何保存.

还值得以提交图的形式快速提醒一下合并的外观。每轮o这里的节点代表一次提交,较早的提交位于左侧。分支名称是指向一个特定提交(tip分支的提交)。你可以从这个开始,例如:

...--o--*--o--o   <-- main
         \
          o--o--o   <-- feature

然后您决定合并一个特定的feature分支回到main分支,所以你运行:

$ git checkout main && git merge feature

这会执行合并(动词)并进行合并(名词),结果如下所示:

...--o--*--o--o---o   <-- main
         \       /
          o--o--o   <-- feature

Git 添加了一项新提交main,这个新的提交是合并提交:它指向前一个提示main,并且还返回(在这种情况下,也向下)到仍然当前的尖端feature。 (名字feature继续指向与之前相同的提交。)

What git merge --squash所做的就是修改最后一步。它没有进行合并提交,而是完全抑制提交(没有明显的原因)并强制您运行git commit。当你do run git commit,这使得ordinary提交,而不是merge提交,结果如下所示:

...--o--*--o--o---o   <-- main
         \
          o--o--o   <-- feature

这里有两个关键项目:

  • The contents新提交的数量是相同的。两个新提交都是由索引制成 (the index是 Git 的术语,意思是“你所做的下一次提交会发生什么”)。该索引是通过合并动词过程设置的。这first父级是“主线”提交,来自我们进行合并时所在的分支。这second父级是另一个提交,我们刚刚合并的那个。

  • The 父级链接新提交的数量有所不同。真正的合并有both先前的提交作为其父级,但“挤压合并”仅one上一个提交作为其父级——“主线”提交。这意味着它不——它can不 - 记住合并了哪个提交。

在有冲突(但真实)的合并的情况下,git merge无法自行进行新的提交,因此它会停止并迫使您解决冲突。解决完这些冲突后,您必须手动运行git commit,就像您必须始终(没有明显原因)所做的那样git merge --squash及其假合并。您还可以请求任何真正的合并停止并让您检查结果,使用git merge --no-commit.

这导致了简单的方法将真正的合并变成假(挤压)合并,只要真正的合并尚未提交:

  • For git commit要知道进行合并,它依赖于冲突(或--no-commit)合并。该文件名为.git/MERGE_HEAD。 (它还留下了一个名为.git/MERGE_MSG尽管这个额外的文件是无害的。)

  • 因此,您可以简单地remove .git/MERGE_HEAD并运行git commit。 (一旦您使用其消息编写了提交,您可能还想删除 MERGE_MSG 文件。在那之前您可以使用它as消息,或作为其起点。)git commit步骤将不再知道进行合并提交,而是进行普通提交 - 瞧,您已经进行了挤压合并。


如果您已经进行了真正的合并提交,这个过程可能会更困难。特别是,如果您有发表合并,你现在必须让所有获得此合并的人,将其收回。否则真正的合并将会返回(他们很可能会再次合并),或者给他们带来问题,甚至两者兼而有之。如果你能做到这一点,或者如果它有not发布后,您只需“将合并推到一边”,然后放入一个假的合并提交。

让我们重新绘制我们所拥有的,以腾出一些空间。这是与之前相同的图表,只是分散到更多行上:

...--o--*----o----o 
         \         \
          \         o   <-- main
           \       /
            o--o--o   <-- feature

如果我们可以搬家怎么办main回到顶行,然后进行新的提交?好吧,我们会得到下面的图:

...--o--*----o----o--o   <-- main
         \         \
          \         o   [abandoned]
           \       /
            o--o--o   <-- feature

请注意,所有箭头 - 包括提交用于记录历史的内部提交箭头(此处未显示,因为它们很难在文本绘图中生成) - 指向leftward,所以在任何最上面的提交中,都不知道它们下面的任何提交:这些都是“在他们的右边”。只有底线提交,加上我们要放弃的提交,才知道有关顶线提交的任何信息。

此外,如果我们要完全放弃中线提交,那么我们就停止绘制它及其两个合并箭头:

...--o--*----o----o--o   <-- main
         \
          \
           \
            o--o--o   <-- feature

看看这个:我们刚刚为那些假挤压“合并”之一绘制了我们想要的提交图。这正是我们想要的,只要我们得到正确的内容在我们的新承诺中。

但是——这是一种练习;在继续之前看看你是否知道答案——新提交的内容从哪里来?答案就在上面的第一个要点中,以粗体显示。 (如果忘记了,请返回检查。)


现在你知道了git commit使用索引来进行新的提交,让我们考虑一下我们现在拥有的真正的合并提交。它有内容。 (所有提交都有内容。)它们来自哪里?它们来自索引!如果我们能以某种方式获取这些内容回到指数,我们是黄金。事实上,我们可以:我们所要做的就是查看承诺,与git checkout, or 已经将其作为当前提交.

由于我们刚刚进行了新的合并提交,因此我们已经将合并提交作为当前提交。索引是干净的——如果我们运行git status,它说没有什么可提交的。所以现在我们使用git reset --soft to reset分支指针main后退一步,得到我们的中间图。这--soft参数告诉 Git:“移动分支指针,但是don't更改索引和工作树。”因此我们仍然拥有原始合并中的索引(和工作树)。现在我们只需运行git commit要进行普通提交,请提供一些适当的提交消息,然后我们就完成了:我们有一个挤压合并。最初的合并现已被放弃,最终(默认情况下 30 天后的某个时间)Git 会注意到它不再使用并将其删除。

(要后退一步,您可以使用HEAD~1 or HEAD^;两者的意思是一样的。因此命令序列就是git reset --soft HEAD^ && git commit,假设当前提交是您希望用假合并替换的真实合并。)


可以使用上面较长的方法even if您进行了多次合并提交。不过,您必须决定是想要多次假合并,还是一次大假合并。例如,假设你有这个:

...--o--o---o--o--o   <-- develop
      \  \    /  /
       \  o--o  /   <-- feature1
        \      /
         o----o   <-- feature2

你希望你的最终图片看起来像:

...--o--o---o--o--o   <-- develop
      \  \
       \  o--o    <-- feature1
        \
         o----o   <-- feature2

最后一个在哪里two致力于develop是两个假(南瓜)合并,还是您只想要一个大假南瓜:

...--o--o---o--o   <-- develop
      \  \
       \  o--o    <-- feature1
        \
         o----o   <-- feature2

最后一次提交是最终结果吗?如果你想twofake-squashes,您将需要保留两个原始合并提交足够长的时间,以便将它们放入索引并从中进行两个普通提交。如果你只想对最终合并进行一次大的假挤压,那么只需要两个 Git 命令:

$ git reset --soft HEAD~2 && git commit

因为我们将保留second合并索引,向后移动two步骤,然后进行新的提交,将其推到一边both merges.

再次强调,重要的是,没有一个real合并已发布,或者,如果它们已发布,您说服所有其他已选择它们的人停止使用它们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Git:如何将现有的“merge”转换为“merge --squash”? 的相关文章

  • 在 git repo 中查找超过 x MB 且 HEAD 中不存在的文件

    我有一个 Git 存储库 用于存储随机的内容 主要是随机脚本 文本文件 我设计的网站等 随着时间的推移 我删除了一些大型二进制文件 通常为 1 5MB 这些文件会增加存储库的大小 而我在修订历史记录中不需要这些文件 基本上我希望能够做到 m
  • DVCS命令的统一

    当处理多个 开源 项目时 多个版本控制系统开始出现问题 虽然它们共享共同的操作 但我经常在输入时犯错误hg add反而git add 我记得前段时间看到过一个项目 通过提供基本命令以统一的方式访问不同的源代码控制软件提交 ci add等在外
  • 运行“git apply”时出错

    当我尝试时 您能否告诉我如何解决 补丁不适用 错误 git 应用补丁 git apply 0001 my patch error patch failed test xml 114 error text xml patch does not
  • git diff 在尖括号中显示 unicode 符号

    我有一个带有 unicode 符号 俄语文本 的文件 当我修复一些拼写错误时 我使用git diff color words 看看我所做的改变 如果是 unicode 西里尔文 符号 尖括号会造成一些混乱 如下所示 cat p1 cat p
  • 分支明显不同,但提交历史是相同的

    git status告诉我我的分支和我在另一个存储库上开始的分支已经分歧 On branch master Your branch and origin master have diverged and have 13 and 13 dif
  • IntelliJ:查看本地和 git 提交/分支之间所有已更改文件的差异

    使用 IntelliJ 的 diff 查看器是检查代码的一种非常好的方法 因为您可以使用 IntelliJ 代码编辑器的所有功能 重构 完成等 在本地版本中进行更改 不幸的是 我还没有弄清楚当你在 IntelliJ 中进行代码审查时如何做最
  • 如何使用交互式变基将提交编辑为未提交?

    我想使用交互式变基来编辑以前的提交 但是当我进入该提交的编辑模式时 所有文件都已提交 我知道我可以进行更改并修改提交 但我希望所有更改最初都未提交 暂存或以其他方式 这样我就可以对其进行编辑 就像在最初提交之前一样 这可能吗 Imagine
  • git pull,忽略深度,如何不拉取整个历史记录?

    我们有一个巨大的多 GB git 存储库 主要是二进制对象 克隆需要几天时间 实际的主分支 没有历史记录 只有大约 20MB 所以我想 深度为 1 的 git 克隆就是解决办法 然而 现在我需要将某人的更新拉到主服务器 我们没有分支 当我拉
  • git Push over sshfs 失败,并显示“关闭 sha1 文件时出错:错误的文件描述符”

    我们使用 sshfs 通过 SSH 安装文件系统 并将其用作 git 存储库协作的远程存储 Mac OSX 10 6 6 到 RHEL 3 服务器 SSHFS 版本 2 2 MacFUSE SSHFS 2 2 0 MacFUSE 库版本 F
  • 丢失了我在 GIT 中的提交。你会不小心删除提交吗?

    我正在使用 git gui 但看不到我的分支 我知道我今天检查了一些东西 在完成提交并使用分支查看器验证后 我更改为较早的分支 我对之前的分支进行了更改 然后想返回到当前的分支 但我再也看不到它了 任何帮助都会很棒 回答你的问题 在大多数情
  • 我可以直接从我的谷歌云端硬盘在线推送/拉取吗?

    有一些方法可以通过谷歌驱动器同步 Windows 应用程序将我的本地 git 存储库同步到我的谷歌驱动器 但我想知道我是否可以完全绕过它的需要 Fro eg git remote add origin https drive google
  • 无法从 Sourcetree 拉取 Git 远程存储库

    我生成了 ssh 密钥并配置了我的 git 和 SourceTree 我可以 git pull 并从 Git bash 执行其他操作 注意 我在 bashrc 中添加了以下内容以使其正常工作 eval ssh agent ssh add 然
  • 在 Azure DevOps 项目之间移动存储库时保留拉取请求

    我在同一帐户内有两个 Azure DevOps 项目 我想将存储库从一个项目移动到另一个项目 这一页探索如何在具有完全保真历史记录的团队项目之间移动 git 存储库 https learn microsoft com en us azure
  • Netbeans 和 Git,.obj 文件被忽略

    我正在开发一个涉及 obj 文件的小型 git 项目 当我查看 项目选项卡 时 我发现它们被忽略了 但如果我查看我的 gitignore 我无法理解为什么 DepthPeeling nbproject private DepthPeelin
  • apt-get 无法在 ubuntu dockerfile 中工作

    我对 docker 相当陌生 正在尝试通过编写自己的镜像来学习 并且目前正在阅读 Docker 的实际操作 ISBN 1633430235 在我自己的代码和书中的示例 第 146 页 中 我想通过 dockerfile 安装 git My
  • Rails/Ruby 合并两个具有相同键、不同值的哈希值

    我有两个想要合并的哈希值 它们看起来像这样 Hello gt 3 Hi gt 43 Hola gt 43 第二个哈希看起来像 Hello gt 4 Hi gt 2 Bonjour gt 2 我想合并这两个哈希数组 使结果看起来像 Hello
  • 如何在 macOS 上将 Git 升级到最新版本?

    我刚刚购买了一台装有 OS X Lion 的新 Mac 我在终端中检查了默认安装的 git 版本 我得到了答案 git version gt git version 1 7 5 4 我想将 git 升级到最新版本 1 7 8 3 因此我下载
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 如何在 R 中合并同名列表中的数据框?

    我有一个包含很多数据框的列表 如果它们具有相同的名称 我想合并它们 即合并所有具有相同名称 a 和 b 的数据框 像这样 a lt aaaaa b lt bbbbb c lt ccccc g lt list df1 lt data fram
  • 当 .gitattributes 中的 EOL 设置为 CRLF 时,Git diff 认为行结尾为 LF

    当我恢复对带有 Windows 行结尾的文件的更改并且 gitattributes 将 EOL 定义为 CRLF 时 git 认为行结尾已更改为 LR 即使十六进制编辑器显示 CRLF 仅当 gitattributes 定义 EOL 字符时

随机推荐