0

假设我在一个分支上工作X。我最近的提交是在20 minutes以前。现在,我想合并来自该组织的官方 repo 的提交,但该提交在大约 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**
4

3 回答 3

0

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

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

于 2013-07-25T02:47:16.890 回答
0

这是可能的,但不是没有创建新的提交。也就是说,如果你的本地提交A4是本地的,你可以变基;但是,由于它们是原产地,因此会引起头痛。

如果我理解正确,这就是您所处的情况,您想在 and之间G插入。BC

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

关键点是提交是由它们的祖先定义的。也就是说,C由作为其父级的事实定义B(对于 也是如此F)。您可以在 之上进行新的提交,但是“在andB之间插入提交”意味着更改的父级,这意味着不再是。BCCCC

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

git rebase --onto G B E
git checkout -B master HEAD   # The '-B' option isn't related to the commit 'B'.

rebase 所做的是B..E在 之上重播范围,即在 之上依次G重新提交CD的补丁。你会处于这种状态:EG

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

C', D',是表示 , ,E'中相同更改的新提交C,但它们与其原始对应项无关。注意 master 和 origin/master 现在是如何分道扬镳的;要整合它们,您必须将它们合并,然后在您的历史记录中将, , , 复制为, , 。DECDEC'D'E'

G在这种情况下进行整合,正确的做法是合并它:

git merge G

这也会引入GF因为它是G: 的不可变部分,提交是由它们的历史定义的。如果你想拉入 justG的补丁,你必须挑选它:

git cherry-pick G

然而,就像 rebase 一样,cherry-picking 一个提交会使用原始补丁创建一个新的提交,因此这也会导致您的历史中的提交重复。有时这没问题:有时您只需要立即进行某个提交(例如,用于生产的修补程序),重复就代表了这一点。但总的来说,这不是你想要的,合并是要走的路。

于 2013-07-25T14:56:03.720 回答
0

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

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

FX您几周前在您的工作分支上编写了修复,以及W1通过W5. 他们(无论谁控制origin/masterorigin/feature或任何你在一个分支上工作)终于开始提交它,也许还有上面的其他提交(C3通过C5)。因为它是不同的提交(即使它做出了相同的更改),所以我将它标记为F2.

可以在上面重新设置你的分支,F2但这必然会让你得到改变,C3至少C4C5如果你也想要的话。如果这是您想要的,只需执行以下操作:

$ git rebase -i master

当你在你的workbranch. 由于您的修复FX已包含(尽管现在称为F2),请从您想要保留的更改列表中删除它(pick启动 rebase 时正在编辑的文件中的一行),然后让交互式 rebase 运行。当然,您还需要确保您的每个提交W1仍然W5可以独立工作,因为它们基于不同的提交(C5上面的 )。如果不是,您可能需要再做一次rebase -i并根据需要修复每个提交。而且,rebase 可能会遇到冲突,您必须手动解决。但假设所有这些都有效,你最终会得到这个:

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

(从数学符号中借用的单引号'表示这些是的提交,它们只是与提交“做同样的事情” W1W2等等。这就是这样rebase做的:它采用现有的提交链,并创建一个新链提交,从其他地方开始,与旧链“做同样的事情”,然后从旧链中删除标签 - <code>workbranch,在这种情况下 - 并将其粘贴到新链上。)

如果幸运的话,没有“额外”提交(C3C4以上):您的工作分支脱离提交 C2,那么远程“主线”上的下一个是您的修复 F2。如果提交W1与修复工作正常,你可以这样做,例如:

$ git rebase -i <sha1-of-F2>

并再次删除pick您提交的行FX,因为它的内容与F2. 在这种情况下,您将获得一个如下所示的提交树:

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

在每种情况下,这里的要点都是相同的:进行新的更改链(您的“工作”),origin/whatever在“他们”将您的错误修复提交FX作为提交时或之后挂起一个点F2。这里的问题也是一样的:你在 C2 分支时测试了你的工作,而新的工作链分支了其他一些提交,所以现在可能你的部分或全部工作被巧妙地破坏了。

注意:当你做 rebase 的东西时,你可以在你的原始作品上粘贴一个标签,这样可以很容易地获得原始的一系列提交(上面的W1, FX, W2, ...),方法是:

git branch original-workbranch workbranch

在你开始任何变基之前。当您对“新”版本中的一切正常感到高兴时,您可以删除额外的标签:

git branch -D original-workbranch

如果您忘记或不关心这个“保存”步骤,并且稍后想要恢复原始工作分支,则可以在事后通过“参考日志”(通常为 90 天左右)完成(请参阅 参考资料git reflog --help),但它是在这一点上做更多的工作。

于 2013-07-25T03:22:26.373 回答