我已经建立了一个存储库,并希望对其进行长期维护和更改。这些更改将永远不会合并回原始存储库(OR)中。但是,我确实想从OR中引入任何新更改。将这些提交添加到我的存储库时,我不需要很多合并提交。如果有冲突,我知道它们是不可避免的。但是大多数提交应该干净合并。
是否有一种方法可以从OR中“重新设置”这些提交?
我认为git cherry-pick
是做到这一点的一种方法,但是OR会对其进行很多更改,因此我不想每次都选择。
我已经考虑过签出OR / master,将其重新部署到我的dev分支之上,然后将其合并回我的dev分支。
git checkout -b ORmaster OR/master
git rebase -i dev
git checkout dev
git merge --ff-only ORmaster
但这意味着每次我想从OR / master合并时,我都必须签出一个新分支并重复此操作。
有没有更简单的方法?
PS:我也不知道标题的字眼。如果有人能说得更好,请告诉我。
编辑: 我添加了我想发生的事情。
A--B--C <-- OR/master, origin/master, master
我添加了一些对分支的更改
A--B--C <-- OR/master
\
D--E--F <-- master
其他人对OR / master进行了更改。
A--B--C--G <-- OR/master
\
D--E--F <-- master
我想要这些更改,所以我想将其应用于我的
A--B--C--G <-- OR/master
\
D--E--F--G' <-- master
我想进行其他更改,有人对OR进行更改
A--B--C--G--I <-- OR/master
\
D--E--F--G'-H <-- master
我要将OR更改应用于我的分支。
A--B--C--G--I <-- OR/master
\
D--E--F--G'-H--I' <-- master
据我了解,这将防止任何合并提交,同时保持我的仓库最新。
答案 0 :(得分:5)
我基于所述编辑的问题已经修订本。当然可以这样做,您可以使自动进行摘樱桃变得容易一些,但是偶尔会遇到绊脚石,合并会更好。
首先,让我们看一下如何自动执行摘樱桃的过程。假设OR
存储库仅添加个提交(如更新问题中的附图所示),我们需要的是某种标记,以便我们知道哪个提交是我们最后选择的最后一个。
此标记可以采用任何形式,并且可以使用内置标记,尤其是OR/master
本身的引用日志。但是,为了说明如果不出意外,并在引用日志到期或其他任何可能导致问题的,我们可以用一个明确的分支或标记名称的存在更多的灵活性。一个分支的名字是最合适的,因为我们将在所有Git分支预期名字移动通常的方式将其移动。
让我们以这个阶段为例:
A--B--C--G <-- OR/master
\
D--E--F--G' <-- master
(摘樱桃后)。要记住我们已经专门从G
离开,我们应该设置分支名称以指向G
:
A--B--C--G <-- marker, OR/master
\
D--E--F--G' <-- master
当我们到了下一次有一些更新,它不会不管我们有多少提交加入到我们自己的'主,因为我们将有:
I <-- OR/master
/
A--B--C--G <-- marker
\
...
因此,复制的提交只是marker..OR/master
,我们可以运行:
git checkout master # if needed
git cherry-pick marker..OR/master # copy the new commits
成功后,将marker
前进到OR/master
任意方式,包括比较聪明的(如果有点吓人的话):
git push . OR/master:marker
(除非对marker
进行更新是一项快进操作,否则它将拒绝执行任何操作)。
举例说明何时出错,请考虑如果OR/master
获得一系列包含合并的提交会发生什么情况:
...--L
\
I--M--N <-- OR/master
/
A--B--C--G <-- marker
\
...
现在,提交范围marker..OR/master
包括提交M
及其第二父级L
以及L
之前无法通过G
访问的所有内容。其提交的 的我们应该复制?只要我们使用M
参数(实际上始终为-m
)单独进行操作,我们就可以 从字面上挑选-m 1
,而这个可能适合您的情况。但这是一个令人担忧的问题,您应该意识到这一点(并知道您打算对此做些什么)。如果您使用git merge
(如我在下面的原始建议中所述),则 并不是问题:一切都会按照应有的方式自动进行。
(原来的答复是分割线以下。)
所有git rebase
所做的都是复制提交(就像git cherry-pick
一样-有时是git cherry-pick
上是 ),然后移动分支名称。
您始终可以复制所拥有的任何提交,因此,可以对从其他Git存储库中获得的提交进行基准化。这不会帮助你与你的实际目标,虽然。你应该做的是使用git merge
看它是这样的:你的叉子只是一个克隆,和您的前叉的克隆是你的副本的副本。除了有一个始终保持上线的地方藏匿自己的clone(刀叉),你基本上只克隆原来的克隆。因此,我们可以标记的东西,在你的本地库是这样的:
...--F--G--H <-- OR/master, origin/master, master
其中每个大写字母代表唯一的提交哈希ID。 (我们将在26次提交后用完,因此您可以了解为什么Git的实际哈希ID如此之大又丑陋-在过去这些存储库中每个人所做的每个提交中,它们必须永远是唯一的 或未来。)
现在,在某些时候,你做出自己的承诺(S)和推他们origin
(你自己的叉),所以现在你有:
...--F--G--H <-- OR/master
\
I--J <-- master, origin/master
在您origin/master
之后,您的master
总是会与您自己的git push origin master
相匹配,因此我们在这里甚至不需要理会它。
但是,与此同时,拥有OR存储库的人将自己的提交提交给自己,因此在git fetch OR
之后,您将拥有以下内容:
...--F--G--H--K--L <-- OR/master
\
I--J <-- master
您可以将他们的提交K
和L
复制到您的K'
和L'
中,以便:
...--F--G--H--K--L <-- OR/master
\
I--J <-- master
\
K'-L' <-- dev
然后您可以快进master
,以便:
...--F--G--H--K--L <-- OR/master
\
I--J--K'-L' <-- dev, master
最终他们会做出更多提交:
...--F--G--H--K--L--N--O <-- OR/master
\
I--J--K'-L' <-- dev, master
(我已跳过M
来保留它),也许您也有:
...--F--G--H--K--L--N--O <-- OR/master
\
I--J--K'-L' <-- dev
\
P--Q <-- master
但是如果您现在使用git checkout dev
和git rebase OR/master
,那只会将您的I
和J
复制到I'
和J'
并复制您的K'
是他们的K
到新K"
的副本,依此类推:
I'-J'-K"-L" <-- dev
/
...--F--G--H--K--L--N--O <-- OR/master
\
I--J--K'-L'
\
P--Q <-- master
这真的没带你去任何地方。
但是,如果您合并,则会得到以下信息:
...--F--G--H--K--L <-- OR/master
\ \
I--J--M <-- master
现在,他们使自己的提交和你做你的:
...--F--G--H--K--L----N---O <-- OR/master
\ \
I--J--M--P--Q <-- master
再次,您只需git merge OR/master
即可将他们的工作并入您的工作中:
...--F--G--H--K--L----N---O <-- OR/master
\ \ \
I--J--M--P--Q--R <-- master
进行合并时,必须一次解决所有合并冲突。如果您重新设定基准,则必须重新解决所有以前的合并冲突。 (使用git rerere
可以与帮助,但如何有帮助的,这是一个限制。)你只需要一次解决这些问题的原因有两方面:
M
和之后的R
之后, next 合并以公共合并基础L
开始,然后O
:您只需查看他们自上次共享提交以来所做的事情。正是合并提交本身建立了更新的共享提交合并基础。如果没有合并提交,你没有得到更新的合并基础。合并提交很好;拥抱他们。 :-)