假设我正在分支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**
答案 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
,以及W1
到W5
的提交。他们(无论是谁控制origin/master
或origin/feature
,还是你在分支上工作的任何人)终于可以提交它,也许还有其他提交(C3
到C5
) 以上。因为它是一个不同的提交(即使它做出相同的更改),我已将其标记为F2
。
你可以在F2
之上重新分支你的分支,但这必将至少从C3
和C4
获得更改,{{ 1}}如果你也想要它。如果这就是你想要的,那就做:
C5
当你在$ git rebase -i master
时。由于已经包含了您的修补程序workbranch
(现在称为FX
),因此请从更改列表中删除它(在您启动rebase时正在编辑的文件中为F2
行)你想继续,然后让交互式rebase运行。当然,您还需要确保每个提交pick
到W1
仍然可以自行运行,因为它们基于不同的提交(W5
,以上)。如果不是,您可能需要执行另一个C5
并根据需要修复每个提交。并且,rebase可能会遇到冲突,您必须手动解决。但假设所有这些都有效,你最终会得到这个:
rebase -i
(借用数学符号表示的单引号C2 --- C3 --- C4 --- F2 --- C5 <-- master, origin/master (or similar)
\
W1' --- W2' ... --- W5' <-- workbranch
标记表示这些新提交只是与提交'
{做同样的事情',{这是W1
所做的:它需要一个现有的提交链,并从其他地方开始创建一个新的提交链,与旧链“做同样的事情”,然后删除标签 - W2
,在这种情况下 - 来自旧链并粘贴在新链上。)
如果你很幸运,是没有“额外”提交(上面是rebase
和workbranch
):你的工作分支是提交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/whatever
,FX
,{{ 1}},...在上面),通过做类似的事情:
F2
在开始任何变基之前。当您对“新”版本中的所有内容都很满意时,您可以删除额外的标签:
W1
如果您忘记或不打扰这个“保存”步骤,以后想恢复原始工作分支,可以在事后(通常约90天)通过“ref log”完成(参见{ {1}}),但在那一点上工作更多。
答案 2 :(得分:0)
这是可能的,但不是没有创建新的提交。也就是说,如果您从A4
开始的本地提交仅限本地提交,则可以进行更改;然而,看到它们起源于它们会引起头痛。
如果我理解正确,那就是您所处的情况,并且您希望在G
和B
之间插入C
。
* H (upstream/master)
* G
* F
| * E (master, origin/master)
| * D
| * C
|/
* B
* A
关键是,提交是由他们的祖先定义。也就是说,C
是定义的,因为B
是其父级(F
也是如此)。您可以在B
之上进行新的提交,但是“在B
和C
之间插入提交”意味着更改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
,即重新提交G
,C
,D
的补丁。转到E
的顶部。你将处于这种状态:
G
* H (upstream/master)
| * E' (master)
| * D'
| * C'
|/
* G
* F
| * E (origin/master)
| * D
| * C
|/
* B
* A
,C'
,D'
是代表E'
,C
,D
中相同更改的新提交,但它们是与原来的同行无关。注意master和origin / master现在如何分歧;要集成它们,您必须合并它们,然后您将E
,C
,D
,重复为E
,C'
,{ {1}}在你的历史中。
要在这种情况下整合D'
,正确的做法是合并它:
E'
这也将引入G
和git merge G
,因为它是G
的不可变部分:提交由其历史定义。如果你想只提取F
的补丁,你必须选择它:
G
然而,就像一个rebase一样,使用原始的补丁创建一个新的提交,因此这也会导致你的历史记录中的提交重复。这有时是好的:偶尔你只需要一个特定的提交(例如,生产的修补程序),并且复制表示这一点。但总的来说,这不是你想要的,合并是要走的路。