B-X
/
A-C
\
D
我希望将X
应用于所有分支B
、C
和D
。虽然cherry-pick
可以实现这个功能,但会产生以下历史记录:
B-X
/
A-C-X
\
D-X
现在提交X
有三个副本,如果我有很多分支,这非常不方便。理想情况下,我希望历史记录如下所示:
B
/
A-X-C
\
D
我只想在出现一次的情况下查找 X
,这样历史记录就会更清晰。我应该使用哪个命令来实现这个目标?
B-X
/
A-C
\
D
我希望将X
应用于所有分支B
、C
和D
。虽然cherry-pick
可以实现这个功能,但会产生以下历史记录:
B-X
/
A-C-X
\
D-X
现在提交X
有三个副本,如果我有很多分支,这非常不方便。理想情况下,我希望历史记录如下所示:
B
/
A-X-C
\
D
我只想在出现一次的情况下查找 X
,这样历史记录就会更清晰。我应该使用哪个命令来实现这个目标?
首要的一点是,你所请求的修复将改写历史记录,这只有在没有其他人使用该分支时才应该这样做。例如,如果您将D
移动到X
之后,那么以前检出D
的任何其他人在拉取时都会感到非常困惑。只有在没有其他人使用它或他们知道并预期更改时才应该这样做。
// Make a new temporary branch starting at A, and move X into it.
git checkout -b tmp A
git cherry-pick X
// For each of B, C and D, rebase them on top of the temporary branch.
git checkout <branch>
git rebase tmp
其他人指出的“拣选”策略非常有效。只想指出,您也可以使用一组带有 --onto 标志的变基来执行此类操作,而不需要临时分支。
git rebase --onto A B X
B-X
/
A--Y
|\
D C
Y
的注释,了解为什么它与X
有不同的名称,以及git如何处理历史中的任何更改。X
应用到了想要的地方,现在你只需要将其他分支rebase一下,这样它们也会在它们的历史记录中拥有它。git checkout C
git rebase Y
git checkout D
git rebase Y
git checkout B
git rebase Y
B
。无论字母代表分支名称还是SHA1提交,上面的顺序都是有意义的。但是,如果B
和X
实际上是一个分支,那么您需要检出该分支并将其倒回到X
创建之前。为了举例说明,我们称该分支为“bee”。git checkout bee
git reset --hard B
git rebase Y
B
/
A--Y-C
\
D
接下来,只需吃蛋糕。
变基、挑选、修订,哦我的天啊!
提交及其SHA1与父提交、执行的更改和其他一些细节是唯一的。因此,当更改提交的父或祖先时,该提交实际上会被克隆并将具有新的SHA1。变基、挑选或任何修改现有提交或提交的父级的操作都将导致修改后的提交获得新的SHA1。而且,由于该提交的SHA1已更改,所有该提交的子代都认为它们有一个新的父级,因此它们也会获得新的SHA1哈希。
旧提交仍然存在,因此上图显示Y作为X的克隆版本,具有新名称和新父级。两者仍然存在,在大多数情况下,旧提交可以轻松检索,在某些情况下(如此例),您实际上需要有意将旧提交移开。这就是为什么在rebase --onto之后,您会看到图表显示X和Y。X提交没有“移动”,更像是克隆。之后,X仍然存在,并且需要通过检出B分支并将其重置为“X”之前的提交来处理。
实际上,B
、C
和D
中的提交也会被克隆,并且它们都会有新的SHA1哈希值。onto
选项!我认为它的工作方式类似于 cherry-pick,这里的 Y 是临时分支吗? - YangY
不是一个临时分支,而是 X
的克隆。 - eddiemoyagit reset -hard ORIG_HEAD
或筛选参考日志来撤消所有操作。如果您已经共享了这些提交,那么这可能非常麻烦,但即使如此,也可以通过在他们的工作分支上使用相同的变基--转移技巧来解决问题。 - eddiemoya看起来对我来说是XY问题,也就是询问你的尝试解决方案而不是你的实际问题。
为什么不从共同祖先开始,在单独的bugfix-X分支上创建bugfix提交“X”,然后将其合并到“A”、“B”和“C”中。例如,Junio C. Hamano在博客文章“早期解决主题分支之间的冲突/依赖关系”中描述了这个想法。
这意味着创建以下历史记录:
B---------b
/ |
A-C-----c |
|\ | /
| D-d / /
\ | / /
\X/--/--/
其中 'b'、'c' 和 'd' 是合并提交。
可以使用以下命令完成:
首先,将提交记录'X'(rebase)移动到分支(提交记录)'B'、'C'和'D'的公共祖先上。
$ git rebase --onto $(git merge-base B C D) B X
这将导致以下情况,其中bugfix提交记录'X'位于单独的bugfix分支上:
B
/
A-C
|\
| D
\
\X'
接下来,将bugfix合并到所有需要它的分支中。例如,将其合并到分支'D'中可以使用以下命令:
$ git checkout D
$ git merge X
这将导致以下结果:
B
/
A-C
|\
| D---d
\ /
\X'/
对于分支'C'和'B'也要执行相同的操作。
一个可能的解决方案是使用多个cherry-pick。检出A并cherry-pick X以创建
B-X
/
A-X'
\
\-C
\
D
现在你应该在X上,这样你就可以挑选B:
B-X
/
A-X'-B'
\
\-C
\
D
检出 X' 并挑选 C。再重复一次:检出 X' 并挑选 D。
这可能不是最有效的解决方案,但应该可以工作。