Squashing Merged提交Rebase

时间:2017-12-24 20:14:05

标签: git rebase git-squash

我在此分支和屏幕上有功能/安装新功能并有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

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

1 个答案:

答案 0 :(得分:0)

TL; DR回答

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

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

关于rebase

的事情

作为evolutionxbox said in a comment,当您运行git rebase -i branchname命令时,您选择根本不复制任何提交,将副本放在当前提交ac174b8dc1dc44e91b56c89c55003942070b9742之后。

这可能是件好事,因为当你选择要复制的一些提交时,将副本放在其他一些指定的提交之后,Git将复制的提交省略所有合并提交。这是因为复制合并提交既不可能,也常常是非生产性的。由于上面列表中的11个提交中有9个是合并,因此无法复制它们。

记住git rebase copy 提交的做法非常重要,就像使用git cherry-pick命令一样。一般来说,你将拥有一个Git存储库,其中包含一些提交,你可以而且应该绘制一张图片 - 这些提交的图表,或者至少是那些参与rebase的图片:

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

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

如果您现在运行git checkout four-commits && git rebase new-desired-base,Git将从four-commits点(即D)的提交开始,选择不是的提交可以从new-desired-base点的提交开始,即G。从G可到达的提交为GFE*,以及提交前*的每次提交。因此,从列表D, C, B, A, *, ...中减去该列表会留下D, C, B, A

Git现在将切换到由G标识的提交new-desired-base,并以相反的顺序复制四个提交中的每一个,即最祖先的A伟大的-parent为D,然后是祖父母B,然后是父C,最后是D本身。每个副本都由{{1>} 完成 1 如果一切顺利,结果如下:

git cherry-pick

其中 E--F--G <-- new-desired-base / \ ...--* A'-B'-C'-D' \ A--B--C--D <-- four-commits (prime)标记表示哪个提交被复制到具有新哈希ID的新提交。

最后,如果一切顺利,Git将从原始链中取名',并将其粘贴到新链的末尾,在此过程中重新附加four-commits:< / p>

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'

原始提交链仍在您的存储库中,如果您已将其保存在某处(以及某些特殊隐藏名称,以防您未保存),则可通过其哈希ID进行检索,通常用于至少再过30天,以防你改变主意对于篮板。

请注意,如果任何 else 在其存储库中都有这些提交 - 即,具有这些哈希ID 并且具有自己的名称 - 这些提交将永远保留在<他们的存储库。你必须得到他们来删除那些提交的他们的名称,然后这些提交最终会离开他们的存储库。

1 交互式rebase确实在每个要复制的提交上运行 E--F--G <-- new-desired-base / \ ...--* A'-B'-C'-D' <-- four-commits (HEAD) 。其他一些形式的rebase不是,但效果通常是相同的。

在继续之前需要考虑的事项

由于这就是rebase如何运作,所以记住它是个好主意。更重要的是要记住它没有复制合并提交,因此如果您要求它复制您的提交链,它将省略合并。但是,一般来说,要求Git重新定义包含合并的内容是个坏主意,因为选择要复制的提交往往包括要合并的提交。

考虑以下简化图:

git cherry-pick

请记住,如果他们是更为祖先(父母或祖父母),则提交在左侧,如果他们不是祖先(儿童),则提交到右侧。所以...--A--B----F <-- master \ \ \ D <-- feature-B \ C--E <-- feature-A 添加了一个提交,即master,因为F已分支。它已添加两个提交,即feature-BB,因为F已分支。同时feature-A包含两个提交,feature-AC,不在Emaster包含一个提交,feature-B,即不在D

如果您的目标是在master上同时合并两个功能,则可以选择合并两个功能分支。您可以使用以下任一方式执行此操作:

master

或:

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

如果成功,合并的结果将是新的提交git checkout feature-B && git merge feature-A 。这个新提交将基于(在合并库中)commit G

  • Git会将提交A的快照内容与A中的快照内容进行比较。实际上,这是自提交D 以来在功能B中发生的事情。请注意,此包含 A中发生的事件,这是一个可以从B的提示访问的提交(通过查看master&#39}亲本)。

  • Git将分别将提交D的快照内容与A中的快照内容进行比较。实际上,这是自提交E以来在功能A中发生的事情。比较AA包括E中发生的任何事情,因为C中的快照包括E中发生的任何事件(嗯,减去C中所有的反转。

现在Git有两组更改,Git将组合它们,并将更大的更改应用于提交A中的快照。这为它提供了生成新快照/提交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或{{1}不同}。

使用D

然而,现在可以运行:

C--E

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

feature-B步骤将feature-B附加到git checkout master,当然还会检查HEAD的提示提交,即提交master。因此,假设master位于F,这看起来像是:

G

feature-B步骤执行...--A--B----F <-- master (HEAD) \ \ \ D---G <-- feature-B \ / C--E <-- feature-A 动词部分,即git merge --squash将执行的工作:它找到与以前一样,合并基础,然后像以前一样运行两个git merge命令。

提交git mergegit diff --find-renames的合并基础是提交F。这是因为粗略地说,合并基础是从两个分支提示可以到达的第一个提交。从G开始,我们退一步到B。从F开始,我们退一次到B,一次退到G,然后再退一次DEDE。我们现在已达到共同点提交B - 因此C是合并基础。

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

此处B以两种方式偏离常规H

  1. 它会跳过提交,就像您添加了git merge --squash选项一样,或者好像发生了合并冲突。
  2. 当您自己手动进行提交时,它会在新提交中仅记录一个父哈希ID。
  3. 所以当你现在运行git merge时,你得到:

    --no-commit

    提交git commit内容,即快照,与您进行常规合并的情况相同;但是定期合并会将结果记录为:

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

    由于壁球合并记录额外的父母,Git稍后不知道H已经拥有...--A--B----F--H <-- master (HEAD) \ \ / \ D---G <-- feature-B \ / C--E <-- feature-A 的所有作品。 (通过真正的合并,Git 知道,因为合并基础将 提交H。)

    对于进行压缩合并的人来说,这意味着现在对 G {{1}进行任何进一步开发会产生相反的效果因为缺少父链接,它们将更难以合并到G中。因此,此时删除两个名称 feature-A feature-B 可能是合适的:

    master

    与重新定位一样,额外提交feature-Afeature-B将会在短时间内(可能比rebase更短),即使名称消失,但最终它们会消失。但请记住,如果其他人拥有这些原始提交的名称,并保存在某些其他存储库中,那些提交 - 以及这些名称 - 将永远保留在他们的存储库中,除非您说服他们删除它们。如果他们将自己的工作建立在这些提交的基础上,他们可能会遇到麻烦,以后将他们的工作与你压扁的提交...--A--B----F--H <-- master (HEAD) \ \ \ D---G [abandoned] \ / C--E [abandoned] 结合起来。