删除选择提交并合并或变基并添加重要提交

Posted

技术标签:

【中文标题】删除选择提交并合并或变基并添加重要提交【英文标题】:Delete select commits and merge or rebase and add important commits 【发布时间】:2016-11-07 21:26:32 【问题描述】:

所以我正在检查其他 solutions 但它并不完全适合我我也在处理分支合并

git log
commit 6d034e1b1f03241b2c660312660ce29acca23f60
Author: ME <myfakemail@gmail.com>
Date:   Thu Jun 30 13:09:08 2016 +0100

    text so people click the button

commit b9295485e17ccb6662b688b5c0f796656ef5f0de
Author: Me-again <myfakemail@fakeville.com>
Date:   Wed Jun 29 17:22:33 2016 +0100

    Adding the 4th celebration to index.php

commit 01ab5a9cfcefe34e72f06f52974da96ce1c2980a
Author: Me-again <myfakemail@fakeville.com>
Date:   Wed Jun 29 12:40:37 2016 +0100

    do the status check after all stops have been performed

commit 904bfdfbc4b536d052e61a303a17e6e108b7d9fe
Author: ME <myfakemail@gmail.com>
Date:   Thu Jun 23 15:16:39 2016 +0100

    changing music to StarSpangled

commit 5874707b022fb6039df84372a750c8fc57215af1
Author: ME <myfakemail@gmail.com>
Date:   Thu Jun 23 15:15:30 2016 +0100

    Quintessential american music

commit 175d5e53c43c7175b6478070d5660e7426aeade9
Author: Me-again <myfakemail@fakeville.com>
Date:   Wed Jun 22 13:11:48 2016 +0100

    Adding error logging and messaging for stop and start

commit 630c25055044a44be304353d3d18e385fed091a3
Merge: 7019947 35eb826
Author: Not Me <notme@mail.com>
Date:   Fri Jun 17 16:57:17 2016 +0100
    Quintessential american music

commit 175d5e53c43c7175b6478070d5660e7426aeade9
Author: Me-again <myfakemail@fakeville.com>
Date:   Wed Jun 22 13:11:48 2016 +0100

    Adding error logging and messaging for stop and start

commit 630c25055044a44be304353d3d18e385fed091a3
Merge: 7019947 35eb826
Author: Not Me <notme@mail.com>
Date:   Fri Jun 17 16:57:17 2016 +0100

    Merge branch 'master' of https://github.com/ME/MyProject

commit 7019947ceea28bd80d020e062a003433529c2a5a
Author: Not Me <notme@mail.com>
Date:   Fri Jun 17 16:57:00 2016 +0100

    4th of July draft

commit 35eb826c39f8b8e0fafd51a9cebae68dd434c7eb
Merge: f0a144f 6a6937d
Author: Me-again <myfakemail@fakeville.com>
Date:   Fri Jun 17 16:26:18 2016 +0100

    Merge branch 'master' of https://github.com/ME/MyProject

    Entering the new cast iron  options

因此,基本上我们有了这个项目,并决定为我们的美国同胞增加一些风味/乐趣。唯一的事情是,虽然我们已经做好了升级的准备,但对项目做出了一些严肃的承诺。

现在第四个结束了,我想删除主题内容并恢复正常

我在想我的选择是

恢复所有第 4 次相关的提交 rebase 并将两个严重的提交添加回代码中

所以我跑了

git revert --no-commit 6d034e1b1f03241b2c660312660ce29acca23f60 b9295485e17ccb6662b688b5c0f796656ef5f0de    904bfdfbc4b536d052e61a303a17e6e108b7d9fe 5874707b022fb6039df84372a750c8fc57215af1 630c25055044a44be304353d3d18e385fed091a3 7019947ceea28bd80d020e062a003433529c2a5a
error: Commit 630c25055044a44be304353d3d18e385fed091a3 is a merge but no -m option was given.

据我所见,它让我处于半还原状态,仅在暂存区域中删除了那些提交的编辑,但合并中引入的更改仍然存在

我最好只是重新提交到提交 35eb826c39f8b8e0fafd51a9cebae68dd434c7eb 然后添加

01ab5a9cfcefe34e72f06f52974da96ce1c2980a

175d5e53c43c7175b6478070d5660e7426aeade9

抱歉,如果您的 git 大师遇到类似情况,您会采取什么行动?

【问题讨论】:

这就是您要找的? ***.com/questions/7099833/… 为链接干杯,但我想我主要关心的是哪个是最好的使用方法。一般来说,我对 Git 很陌生,所以如果出现这种情况,最好采取哪种行动?恢复或变基我只想以最“正确”的方式做事 如果您想亲自撤消更改,我会使用 revert 来处理这些提交。我强烈建议复制你的回购,这样如果你搞砸了,你总是有一个干净的版本。因此,在您的副本中进行测试,一旦您知道要运行哪些命令,然后在实时存储库中执行它。 也强烈推荐 SourceTree 或某种类型的 Git GUI 【参考方案1】:

了解关于 Git 的信息:

Git 总是添加新东西。还原会添加一个新的提交。变基会添加新的提交。就此而言,合并会添加一个新的提交。

但是git rebase 以一种不寻常的方式添加了新的提交。它复制现有的提交,通过将它们更改为补丁(或基本上等效地,转换为git cherry-pick 操作),然后将补丁应用于不同的——更早的——起点比以前。

此外,git rebase 通常跳过 合并提交。以这种方式复制合并提交是不可能的,因此如果您使用 --preserve 选项(它试图保留合并),git rebase 重新执行合并,而不是尝试复制它们. (它的效果如何,如果它确实有效,通常取决于合并最初的简单程度以及您将新提交链“移动”到的位置。)

交互式 rebase 允许您选择要复制的提交,以及是否停止和调整副本。这意味着,如果你复制一个提交链,去掉一个“坏”的提交,你会得到一个永远不会做出“坏”更改的新链。它还允许您将多个提交“压缩”为单个提交,方法是应用除最后一个提交之外的所有提交的更改而不进行新提交尚未,然后使用最终工作进行新提交 -树,以及所有提交的提交文本(并让您将该文本编辑成一条消息)。

一旦 rebase 完成复制提交,它会移动分支名称,因此它现在指向最尖端的 已复制 提交,而不是指向分支的上一个尖端。旧的提交仍在您的存储库中,但效果是就好像它们已被删除,并且分支倒回,然后将新副本添加到您将它们复制到的新位置。 p>

这意味着使用原始提交的任何其他人(假设您已经发布(通常是git push-ed)它们并且其他人拥有原始提交)现在必须采取一些特殊措施来说明您的“复制和倒带并指向副本”效果。

最后,由于 Git 是围绕这种“添加新内容”模型构建的,如果您总是以最简单的方式添加新内容(包括普通的还原),那么 Git 周围的每个人和一切都可以正常工作,无需额外的摆弄。

结论:还原更容易

因此,您可能确实想恢复,就像您尝试过的那样。

在我看来,您在git revert 序列中所做的几乎所有事情都是正确的。你做了一件完全可选的事情——你选择了--no-commit,这样所有的还原都可以组合成一个大的“撤消一堆东西”提交——然后你遇到了一个问题,即还原一个合并比还原一个“常规”(非合并)提交。

还原的工作原理

还原合并提交更难的原因与操作机制有关。为了进行还原,Git 本质上是一个“向后差异”:而不是比较“之前”和“之后”,为了了解如何将旧版本更改为新版本,Git 比较“之后”和“之前”,看看如何改回来。

为了实现任一比较,Git 需要两个提交 ID:“之前”版本和“之后”版本。对于普通(非合并)提交,这很容易。提交本身是“之后”,其父级是“之前”。运行git log --oneline --graph --decorate 以直观地查看父/子关系。注意现在普通的非合并提交有一个父级。然而,合并提交有两个(或更多)父级,这意味着 git revert 不知道将哪个视为“之前”版本。

这就是您收到 is a merge but no -m option was given 错误的原因:提交是一个合并,git revert 需要知道哪些更改要撤消,即要与哪个父级进行比较。 (你几乎肯定想要-m 1。)

因为您使用了--no-commit,Git 会按照命令行中指定的方式一次还原一个,而无需提交。然后它遇到错误并停止,因此它没有恢复该合并,也没有在命令行上列出任何后续提交。

如果没有--no-commit,Git 会执行每次还原然后提交还原,当它失败并抱怨-m 时,您会处于更明显的状态。

不幸的是,您必须指定 -m 选项来恢复合并提交,而您不得指定 -m 选项来恢复非合并提交.这意味着您必须使用多个git revert 命令。

好消息是您可以继续使用现有的git revert --no-commit:只需git revert -n -m 1 &lt;the merge&gt;,然后是git revert -n 每个额外的提交(只需再做一个)。全部完成后,git commit 将在一个巨大的还原中撤消所有内容。

或者,如果您希望一次还原一件事 - 这可以让您在一年后回顾这件事时更容易看到您在做什么,但也会让您更嘈杂(因此更难)看看你在做什么——你可以使用git reset --hard 回到最近提交的索引/暂存区和工作树状态:

$ git reset --hard HEAD

当然,这假定当您开始整个git revert 序列时,所有内容(索引和工作树)都是干净的。现在您可以:

$ git revert ...

每次提交,这次没有-n。 (这假设您已经改变了想要大逆转的想法。)

我该怎么做

请注意,您可以一次执行一个还原,然后使用git rebase -i 将它们全部压缩成一个大还原。这最终的工作方式与使用 git revert -n 完全相同:首先创建一个包含六个单独还原的链,然后将(未发布的)链折叠成一个大还原,然后发布(git push)最终结果。

我自己可能会这样做,这样我就可以验证每个还原是否正常工作,查看具有六个单独提交的版本,思考一下,然后决定 future-me 是更喜欢这个还是一个大的-revert,然后 rebase-and-push,或者只是 push,基于此。

【讨论】:

感谢您提供非常详细的回答,确实学到了很多,但我确实遇到了这个问题 git revert -n -m 1 630c25055044a44be304353d3d18e385fed091a3 错误:无法恢复 630c250... 合并分支 'master' github.com/ME/MyProject 如果即使使用-m,恢复本身也会失败,您将需要解决一些合并冲突。这是在没有-n 的情况下一次还原一个最有帮助的时候,因为您的工作树将只有一个中间状态,而不是 4+ 要弄清楚。

以上是关于删除选择提交并合并或变基并添加重要提交的主要内容,如果未能解决你的问题,请参考以下文章

合并/其他提交交错后的交互式变基

删除坏变基后引入的重复提交

在没有变基的情况下恢复合并

Git中分支变基的原理

rebase(变基)

Git 常用命令手册