合并单个提交

时间:2013-07-25 02:43:28

标签: git github git-merge

假设我正在分支X上工作。我最近的承诺是20 minutes前。 现在,我想合并该组织官方回购中的提交,但该提交在大约20天前发生了变化。

我有什么方法可以合并该提交,在我的仓库中保持正确的提交顺序(按时间)。

目前,如果我执行git cherry-pick <sha1>,它会合并提交,但它会成为HEAD

修改

A1--A2--A3--A4--A5--A6--A7--HEAD ----master (official: `upstream`)

A1--A2--A4--A5--A6--A7--A8--A9--A10 ----mybranch (github repo : `origin`)

A1--A2--A4--A5--A6--A7--A8--A9--A10 ----mybranch (local repo on system)

My aim: Merge the upstream's `A3` commit **in its own place**:

A1--A2--**A3**--A4--A5--A6--A7--A8--A9--A10 ----mybranch (github repo : `origin`)

A1--A2--**A3**--A4--A5--A6--A7--A8--A9--A10 ----mybranch (local repo on system)

(NOT THIS):

A1--A2--A4--A5--A6--A7--A8--A9--A10--**A3**

3 个答案:

答案 0 :(得分:0)

可以使用rebase或更多樱桃采摘,但我不会在这里详细说明,因为你可能正在尝试一些你不应该做的事情。你为什么要对你的历史撒谎,并假装那个提交是你的分支的一部分,而不是它?

您可以简单地合并,git log --date-order将以正确的日期顺序提供您的提交:)。

答案 1 :(得分:0)

根据你对另一个答案的评论,你说开发看起来像这样:

C2 --- C3 --- C4 --- F2 --- C5       <-- master, origin/master (or similar)
   \
    W1 --- FX --- W2 --- W3 --- W4 --- W5  <-- workbranch

您几周前在工作分支上写过修复FX,以及W1W5的提交。他们(无论是谁控制origin/masterorigin/feature,还是你在分支上工作的任何人)终于可以提交它,也许还有其他提交(C3C5 ) 以上。因为它是一个不同的提交(即使它做出相同的更改),我已将其标记为F2

可以F2之上重新分支你的分支,但这必将至少从C3C4获得更改,{{ 1}}如果你也想要它。如果这就是你想要的,那就做:

C5

当你在$ git rebase -i master 时。由于已经包含了您的修补程序workbranch(现在称为FX),因此请从更改列表中删除它(在您启动rebase时正在编辑的文件中为F2行)你想继续,然后让交互式rebase运行。当然,您还需要确保每个提交pickW1仍然可以自行运行,因为它们基于不同的提交(W5,以上)。如果不是,您可能需要执行另一个C5并根据需要修复每个提交。并且,rebase可能会遇到冲突,您必须手动解决。但假设所有这些都有效,你最终会得到这个:

rebase -i

(借用数学符号表示的单引号C2 --- C3 --- C4 --- F2 --- C5 <-- master, origin/master (or similar) \ W1' --- W2' ... --- W5' <-- workbranch 标记表示这些提交只是与提交' {做同样的事情',{这是W1所做的:它需要一个现有的提交链,并从其他地方开始创建一个新的提交链,与旧链“做同样的事情”,然后删除标签 - W2,在这种情况下 - 来自旧链并粘贴在新链上。)

如果你很幸运,没有“额外”提交(上面是rebaseworkbranch):你的工作分支是提交C2,然后是下一个远程“主线”上的一个是你的修复F2。如果提交C3可以正常使用,您可以这样做,例如:

C4

并再次删除提交W1的{​​{1}}行,因为其内容与$ git rebase -i <sha1-of-F2> 相同。在这种情况下,您将获得一个如下所示的提交树:

pick

在每种情况下,这里的要点都是相同的:创建一个新的变更链(你的“W”ork),挂起FX中的一个点,在“他们”放置你的bug修复提交时或之后提交F2中的C2 --- F2 --- C5 <-- master, origin/master (or similar) \ W1' --- W2' --- W3' --- W4' --- W5' <-- workbranch 。这里的问题也是一样的:你在分支C2时测试了你的工作,而新的工作链分支了其他一些提交,所以你的部分或全部工作现在可能会被巧妙地破坏。

注意:当您执行rebase东西时,您可以在原始作品上粘贴标签,这样可以轻松获得原始系列的提交(origin/whateverFX,{{ 1}},...在上面),通过做类似的事情:

F2
在开始任何变基之前

。当您对“新”版本中的所有内容都很满意时,您可以删除额外的标签:

W1

如果您忘记或不打扰这个“保存”步骤,以后想恢复原始工作分支,可以在事后(通常约90天)通过“ref log”完成(参见{ {1}}),但在那一点上工作更多。

答案 2 :(得分:0)

这是可能的,但不是没有创建新的提交。也就是说,如果您从A4开始的本地提交仅限本地提交,则可以进行更改;然而,看到它们起源于它们会引起头痛。

如果我理解正确,那就是您所处的情况,并且您希望在GB之间插入C

* H (upstream/master)
* G
* F
| * E (master, origin/master)
| * D
| * C
|/
* B
* A

关键是,提交是由他们的祖先定义。也就是说,C定义的,因为B是其父级(F也是如此)。您可以在B之上进行新的提交,但是“在BC之间插入提交”意味着更改C的父级,这意味着{{1 }}不再是C

您所追求的历史当然是可能的(但这会导致问题):

C

rebase的作用是在git rebase --onto G B E git checkout -B master HEAD # The '-B' option isn't related to the commit 'B'. 之上重播范围B..E,即重新提交GCD的补丁。转到E的顶部。你将处于这种状态:

G

* H (upstream/master) | * E' (master) | * D' | * C' |/ * G * F | * E (origin/master) | * D | * C |/ * B * A C'D'是代表E'CD中相同更改的新提交,但它们是与原来的同行无关。注意master和origin / master现在如何分歧;要集成它们,您必须合并它们,然后您将ECD,重复为EC',{ {1}}在你的历史中。

要在这种情况下整合D',正确的做法是合并它:

E'

这也将引入Ggit merge G ,因为它是G的不可变部分:提交由其历史定义。如果你想只提取F的补丁,你必须选择它:

G

然而,就像一个rebase一样,使用原始的补丁创建一个新的提交,因此这也会导致你的历史记录中的提交重复。这有时是好的:偶尔你只需要一个特定的提交(例如,生产的修补程序),并且复制表示这一点。但总的来说,这不是你想要的,合并是要走的路。