0

在这个分支和屏幕上有一个分支功能/安装新功能,并且有 11 次提交。但是所有提交都合并了提交。计划做一个壁球这些提交。

我在日志历史记录中有合并提交的列表,需要压缩成一个提交。

commit ac174b8dc1dc44e91b56c89c55003942070b9742
Merge: e9048249 e24218ee
Author: sanjay <sanjay@sanjay.com>
Date:   Sun Dec 10 04:48:39 2017 +0000

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit e904824938f2e8517d3ad5a45a11ae4595157cf7
Merge: 41e1d616 a3128511
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 8 12:07:53 2017 +0000

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit e24218eeb60bcbfa92559cf174d3de40b93a6dbe
Merge: 41e1d616 a3128511
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 8 12:07:53 2017 +0000

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit 41e1d61609ea6d3c99d52efb3fb472a18924b2f1
Merge: ddc36e3b bdf8a179
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 8 09:14:59 2017 +0000

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit bdf8a17968543fccc3b02ffc59c2117448f586ff
Merge: d9fe3abd 7b630927
Author: sanjay <sanjay@sanjay.com>
Date:   Tue Dec 12 14:53:19 2017 +0530

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit d9fe3abd0062475cfdff911ce58a967076d5aa08
Merge: 27ee100a 63113ae4
Author: sanjay <sanjay@sanjay.com>
Date:   Tue Dec 12 14:52:34 2017 +0530

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit a3128511b3fd3746d4191794e7dcda52232e9458
Merge: ddc36e3b bdf8a179
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 8 09:14:59 2017 +0000

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit ddc36e3be2dd55b1ba880c307c8be0237ca52bce
Merge: d9fe3abd 7b630927
Author: sanjay <sanjay@sanjay.com>
Date:   Tue Dec 12 14:53:19 2017 +0530

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit 7b630927be19a773414938a43702fe9cd0e7f854
Merge: 27ee100a 63113ae4
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 8 01:52:01 2017 +0000

    Merge branch 'feature/Install New feature on this branch and screens' of https://github.com/service/dosomething.git into feature/Install New feature on this branch and screens

commit 27ee100ad29e8db7fb10ddc04824ccdc8a53d091
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 1 06:25:13 2017 +0000

    Install New feature on this branch and screens

commit 63113ae404be96f113e1c9eb4f79d0de9fc4a90e
Author: sanjay <sanjay@sanjay.com>
Date:   Fri Dec 1 06:25:13 2017 +0000

    Install New feature on this branch

但我做了一个git rebase -i branchname它显示这样的输出。我无法将其压缩为提交。输出是这样的

noop

# Rebase ac174b8..ac174b8 onto ac174b8 (1 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

我如何使用上述提交来处理壁球。

4

1 回答 1

0

TL;DR 答案

您无法通过git rebase. 您可能可以通过 实现您想要的git merge --squash,但除非您知道自己在做什么,否则您通常根本不应该使用git merge --squash。(也就是说,这可能是解决整体问题的错误方法。)

根据经验,在运行git merge --squash了一组提交之后,您应该删除包含这些提交的一个或多个分支,因为它们不再适合开发。(可能有特定的例外。)在这种情况下,这意味着删除您合并的每个分支。

关于变基的事情

正如Evolutionxbox 在评论中所说,当您运行git rebase -i branchname命令时,您选择根本不复制任何提交,将副本放在当前提交之后ac174b8dc1dc44e91b56c89c55003942070b9742

这可能是一件好事,因为当您选择要复制的一组提交时,将副本放在其他一些指定的提交之后,Git 将复制的提交会忽略所有合并提交。这是因为复制合并提交是不可能的,而且通常是无效的。由于上面列表中的 11 个提交中有 9 个合并,因此您无法复制它们。

重要的是要记住,git rebase所做的是复制提交,就像通过使用git cherry-pick命令一样。通常,您将拥有一个 Git 存储库,其中包含一些提交,并且您可以并且应该绘制这些提交的图片(图表),或者至少是那些将参与 rebase 的提交:

       E--F--G   <-- new-desired-base
      /
...--*
      \
       A--B--C--D   <-- four-commits

在这里,只能从名称访问的四个提交中的每一个four-commits都是普通(非合并)提交。commit 的父级D是 commit CCis的父级BBis的父级A;并且父级A是我用星号标记的提交*

如果您现在运行git checkout four-commits && git rebase new-desired-base Git 将从提交到哪些four-commits点(即D)开始,选择从提交到哪些点(即. 可访问的提交是, , ,和 commit 之前的每个提交。因此,从列表中减去该列表会留下.new-desired-baseGGGFE**D, C, B, A, *, ...D, C, B, A

Git 现在将切换到G由 标识的 commit ,new-desired-base并以相反的顺序复制四个提交中的每一个,即 的最祖先A的曾祖父母,然后D是祖父母B,然后是父母C,最后是D自身。每个副本都是由完成git cherry-pick1 如果一切顺利,结果如下所示:

       E--F--G   <-- new-desired-base
      /       \
...--*         A'-B'-C'-D'
      \
       A--B--C--D   <-- four-commits

其中'(prime)标记指示哪个提交被复制到具有新哈希 ID 的新提交。

最后,如果一切顺利,Git 会four-commits从原链上取下名称,并将其粘贴到新链的末尾,在此过程中重新附加HEAD

       E--F--G   <-- new-desired-base
      /       \
...--*         A'-B'-C'-D'   <-- four-commits (HEAD)
      \
       A--B--C--D   [abandoned]

现在原始提交没有名称D,它似乎完全消失了。这需要整个链条,因此A-B-C-D 似乎已被替换为A'-B'-C'-D'

       E--F--G   <-- new-desired-base
      /       \
...--*         A'-B'-C'-D'   <-- four-commits (HEAD)

原始提交链仍在您的存储库中,如果您已将其保存在某个地方(以及一些特殊的大部分隐藏名称以防您尚未保存),则可通过其哈希 ID 检索,通常至少 30 天以上,在如果你改变了对变基的想法。

请注意,如果其他在他们的存储库中有这些提交——即,有这些哈希 ID并且有他们自己的名称——这些提交将永远保留在他们的存储库中。您必须让他们删除这些提交名称,然后这些提交最终也会从他们的存储库中消失。


1交互式变基确实会git cherry-pick在每次要复制的提交上运行。一些其他形式的变基不会,但效果通常是相同的。


在继续之前要考虑什么

因为这就是 rebase 的工作方式,所以记住这一点是个好主意。更重要的是要记住它不会复制合并提交,因此如果您要求它复制您的提交链,它将忽略合并。不过,一般来说,要求 Git 对包含合并的内容进行 rebase 是一个坏主意,因为选择要复制的提交往往包括被合并的提交。

考虑下面的简化图:

...--A--B----F   <-- master
      \  \
       \  D   <-- feature-B
        \
         C--E   <-- feature-A

请记住,如果它们是祖先(父母或祖父母),则提交在左侧,如果它们是祖先(孩子),则提交在右侧。所以master已经添加了一个提交,即F,因为feature-B分支。它已经添加了两个提交,即BF,因为它已经feature-A分支了。同时feature-A包含两个提交,CE,不 on master,并且feature-B包含一个提交 ,D,不 on master

如果您的目标是一次合并两个功能master的单个新提交,您可以选择首先合并两个功能分支。您可以使用以下任一方法执行此操作:

git checkout feature-A && git merge feature-B

或者:

git checkout feature-B && git merge feature-A

如果成功,合并的结果将是一个新的提交G。这个新的提交将基于(如合并基础) commit A

  • Git 会将提交快照的内容AD. 实际上,这就是自 commit 以来在 feature-B 中发生的事情A。请注意,这包括中发生的事情,这是可以从(通过查看的父级)B的尖端到达的提交。masterD

  • Git 将分别比较提交快照的内容AE. 实际上,这就是自 commit 以来在 feature-A 中发生的事情A 比较AvsE包括在 中发生的任何事情C,因为在中的快照E包括在中发生的任何事情C(嗯,减去任何返回到中的内容A)。

现在 Git 有两组更改,Git 会将它们组合起来,并将生成的更大更改应用于 commit 中的快照A。这为其提供了生成新快照/提交所需的内容G

...--A--B----F   <-- master
      \  \
       \  D---G
        \    /
         C--E

如果您使用 执行此操作git checkout feature-B && git merge feature-A,则会将新提交G添加到feature-B分支中:

...--A--B----F   <-- master
      \  \
       \  D---G   <-- feature-B (HEAD)
        \    /
         C--E   <-- feature-A

如果使用 执行此操作git checkout feature-A && git merge feature-B,则会将新提交G添加到feature-A分支中,因此我们可能会将其绘制得更像这样:

...--A--B----F   <-- master
      \  \
       \  D   <-- feature-B
        \  `--_
         C--E--G   <-- feature-A

但是,无论哪种方式G都是合并提交,因此不能rebase,不像提交DC--E.

使用git merge --squash

但是,现在可以运行:

git checkout master && git merge --squash <something>

这里<something>是产生新提交的哈希 ID 的任何东西G。您可以输入原始哈希 ID;或者,如果您进行了合并以将提交G添加到feature-B,您可以使用名称feature-B.

git checkout master步骤附加HEADmaster,当然还检查了 的提示提交master,即 commit F。所以假设G是 on feature-B,这看起来像:

...--A--B----F   <-- master (HEAD)
      \  \
       \  D---G   <-- feature-B
        \    /
         C--E   <-- feature-A

git merge --squash步骤执行 的动词部分,即将执行git merge工作git merge:它像以前一样找到合并基础,然后像以前一样运行两个git diff --find-renames命令。

F提交的合并基础G是 commit B。这是因为,粗略地说,合并基础是可以从两个分支提示访问的第一个提交。F,我们退一步到B。从 开始G,我们后退一次 toD和一次 to E,然后第二次从 both DandE到 both Band C。我们现在已经达到了一个共同点——提交——B合并B基础也是如此。

所以,和以前一样,Git 运行git diff --find-renames B Fandgit diff --find-renames B G来查看两个分支中发生了什么。然后 Git 将这些更改组合在一起,将它们应用于快照的内容B,并准备一个新的快照H

这里以两种方式git merge --squash偏离常规:git merge

  1. 它会跳过提交,就像您添加了--no-commit选项一样,或者好像发生了合并冲突。
  2. 当您手动进行提交时,它只会在新提交中记录一个父哈希 ID。

所以当你git commit现在运行时,你会得到:

...--A--B----F--H   <-- master (HEAD)
      \  \
       \  D---G   <-- feature-B
        \    /
         C--E   <-- feature-A

commit的内容H,即快照,与您进行常规合并一样;但常规合并会将结果记录为:

...--A--B----F--H   <-- master (HEAD)
      \  \     /
       \  D---G   <-- feature-B
        \    /
         C--E   <-- feature-A

由于 squash 合并没有记录额外的父级,Git 稍后不会知道,它H已经拥有来自G. (通过真正的合并,Git知道这一点,因为合并基础commit G。)

这对于进行 squash-merge 的人来说意味着,现在对or进行任何 进一步的开发会适得其反,因为它们以后将更难以合并,因为缺少父链接。因此,删除这两个名称可能是合适的此时:feature-A feature-Bmaster feature-A feature-B

...--A--B----F--H   <-- master (HEAD)
      \  \
       \  D---G   [abandoned]
        \    /
         C--E   [abandoned]

C--E与变基一样,即使名称消失,额外的提交D--G也会持续一段时间(可能比变基短),但最终它们确实会消失。但是请记住,如果其他人拥有这些原始提交的名称,并保存在其他存储库中,那么这些提交(以及这些名称)将永远保留在他们的存储库中,除非您说服他们删除它们。如果他们将自己的工作基于这些提交,他们可能会在稍后将他们的工作与您压缩的提交结合起来时遇到麻烦H

于 2017-12-25T01:50:17.557 回答