git rebase -i foo / dev给了noop

时间:2014-11-23 23:39:00

标签: git dvcs

当我按照here所述尝试进入交互式rebase模式时,我所得到的只是 noop ,这很奇怪,但我无法弄清楚原因。

我在我的机器中的临时分支内部,当我尝试查看它们之间的区别时,我得到了这个:

Tugberk@TUGBERKPC /D/Dropbox/AppsPublic/gulp-aspnet-k (temp-a)
$ git log --pretty=oneline  temp-a..ajryan/dev
f0ef4ee40fde4de5360515fd556de9c3ed40431c update readme with new optionsfcba1ae3306ae041a1d82647e4cf65a0c96fe2f7 do not loop for build, restore8bedd238660908f06d698815ef12fce786d716ed fix command concat
e2e3a0d00e3950911c00c0e6e51a671f5f2ac2d3 bump version
d65923ff91eb9d6b9782bc2bf5ab606d19733203 add quiet option
91a1faff0a3aa1ca552df2151190a3ecd87cfc6f allow caller to loop all comma962c55854457314324d81457c42913532875cc85 trailing whitespace, tabs > sp

然而,当我运行以下命令时,我得到了noop:

Tugberk@TUGBERKPC /D/Dropbox/AppsPublic/gulp-aspnet-k (temp-a)
$ git rebase -i ajryan/dev

知道为什么以及我做错了什么?

1 个答案:

答案 0 :(得分:3)

您的git log命令显示的是ajryan/devtemp-a上的提交。您的rebase命令被告知要重新设置temp-a但不在ajryan/dev上的提交,但可能没有这样的提交。图示地:

... - o - o - o                   <-- HEAD=temp-a
                \
                  o - o - o - *   <-- ajryan/dev

因此,没有提交请求并重新绑定到我用星号*标记的提交。所以rebase -i生成一个no-op命令。

如果你执行no-op,那么rebase操作应该通过移动temp-a来指向*之后添加的最后一次提交来结束,这应该使temp-a指向commit {{ 1}}。 (如果这没有发生,那么它是*中的一个小错误。)但是,如果删除no-op,则将终止rebase操作,rebase将不会感动。


请注意,如果您 temp-a上有不同的项目,您可以对它们进行重新绑定,或者重新绑定其他分支。以下是另外两个插图,从几乎相同的基础开始,但temp-a上的一个提交不在temp-a上:

ajryan/dev

在这种情况下,您可以将... - o - o - o - @ <-- HEAD=temp-a \ o - o - o - * <-- ajryan/dev 提交置于其他提交之上:

@

或在底部,在其他提交之下:

... - o - o - o
                \                     (illustration 1)
                  o - o - o - * - @

此处我遗漏了标签(... - o - o - o \ (illustration 2) @ - o - o - o - * temp-a)。这是有目的的:在git中,分支标签很容易移动(并且实际上期望移动,只要它以&#34;前进&#34;方式);所有实际的分支都存储在提交本身中。 ajryan/dev真正做的是复制旧提交到新提交,以便您可以更改其父年龄和/或内容。

在插图#1中,我们重新提供了提交git rebase:它现在已经提交@作为其父级。所有其他提交都没有改变,因此只需要复制提交*

然而,在插图#2中,我们重新确定了最初仅在@上提交的整个提交链。提交ajryan/dev本身未更改,但我们必须复制所有四个原始@提交:我们复制第一个o - o - o - *以将其父级设置为o。这个新提交有一个新的不同的SHA-1 ID,因此我们复制第二个@以使用新提交的ID作为其父ID。第二个副本强制第三个副本,然后强制o提交的最后一个副本。请参阅下一节,了解可能有什么不妥之处。


在git中,要加入两个不同的提交链,通常会使用*

git merge

此处合并提交 A - B / \ ... - o M <-- HEAD=branch \ / C - D 加入从M分出的两个链A - BC - D。如果oA全部存在,并且您创建了新的提交D,则MA没有任何反应:它们仍然与之前相同。

但是,对于简单的开发来说,它通常会更好地降级&#34;工作:让DC坐在最前面&#34; D。但要做到这一点,你必须复制提交,因为git中的提交是永久性的,不变的。您将A - B复制到新的略有不同的C,并将C'复制到新的略有不同的DD'的主要不同之处在于其父级为C',而非B,与o的主要区别在于D'其父级为C',而非C

          A - B - C' - D'   <-- HEAD=branch
        /
... - o
        \
          C - D            [abandoned]

完成rebase副本后,您只需放弃旧的CD提交并开始假装C'D'是原始提交:

          A - B - C - D   <-- HEAD=branch
        /
... - o

现在我们不再需要图表中的小扭结,因为我们已经忘记了原始CD的所有内容,历史就像这样:

... - o - A - B - C - D   <-- HEAD=branch

肮脏的秘密(不是那么秘密,不是那么脏)是原来的CD仍然在那里,它们只是不可见的(给你)。如果其他人拥有原始的两个CD提交,则会使其真正变脏的部分发生。 Git提交ID是其内容的加密校验和,包括父SHA-1 ID,因此原始CD仍然存在且与<{em>不同来自新C 1}}和D以及其他任何人。

当你从其他人那里提交提交时,这很重要:如果你将他们的提交重新命名为你的工作,你更改 ID。你制作新的副本,你可能会忘记他们有原件,但他们还不知道你的新副本,他们没有忘记他们的原始身份证。

如果您稍后向他们提交他们的提交的重新复制副本,他们需要做更多的工作来获取他们的提交副本,并可能移动他们已经完成的任何其他工作。

简而言之,除非您事先与他们作出安排(无论他们是谁&#34;可能是谁),否则像插图#2中所示的那样的底板通常不是一个好主意。


&#34;快进&#34;?那么,让我们再看看插图#1。让我们假设o - o - o - @链来自其他人(&#34;拉取请求&#34;),并在其上添加提交*,将您的工作重新定位到他们的工作上。让我们重新绘制图表,再添加一个扭结,并将ajryan/dev标签放回去:

... - o - o - o     [your original '@' commit, before rebasing, was here]
                \
                  o - o - o - *       <-- ajryan/dev
                                \
                                  @   <-- HEAD=(something, maybe "dev")

现在让我们进一步假设他们,无论他们是谁,在他们的o - o - o - *分支上都有dev序列而没有做任何额外的工作,以便他们的东西在提交时结束标记为*。如果您将这个提交序列提供给他们,他们就可以选择它并将提交@添加到他们的dev分支,只需将他们的dev标签向下滑动到点即可到@标签。现在让我们删除我们的ajryan/dev标签,理顺这些图纸中的扭结,并使用标签dev。结果如下:

... - o - o - o - o - o - o - * - @   <-- HEAD=dev

这是他们将拥有的内容,以及将拥有的内容,一旦您同步。这是一个非常简单的历史记录,即使它与实际开发过程略有偏差(您在没有首先看到以@结尾的链的情况下编写了提交*。但这就是&#34; rebase&#34;这使得开发工作变得更加容易,并且通常是人们想要做的事情。

滑动标签&#34;向右&#34; (包括像这样的图纸中的向下和向右,或向上和向右)是一个快速前进的&#34;操作。如果您使用git merge运行--ff-only,它只会执行&#34;合并&#34;如果真的是这种非合并快进。


底线:我认为您希望将@提交内容改为ajryan/dev工作,但您没有拥有 @提交rebase。这就是为什么rebase给你一个noop的原因。在这种情况下,简单的非合并快进git merge就足以使您的标签与其标签相匹配。


还值得考虑这个问题:当你git log X..Y时,你要求git像我在这里一样绘制图形:

... - o - o - o       <-- X
        \
          o - o - o   <-- Y

X..Y概念本质上说:从此图表开始,取出荧光笔并突出显示X指向的提交,以及所有提交左和/或上或下的提交那里。 (这会使o指向的三个Y未标记。)然后,查找Y指向的所有尚未突出显示的提交,并记录这些提交。< / p>

如果你反转XY,就像git log Y..X一样,你要求git去&#34;运行荧光笔&#34;在标记为Y的提交上,仅在o上留下两个X,然后记录X指向的所有尚未突出显示的提交。所以在这里你得到X上的两个o,而没有共享的。{/ p>