您可以从远程分支“重新设置”提交吗?

时间:2019-02-03 01:15:17

标签: git version-control

我已经建立了一个存储库,并希望对其进行长期维护和更改。这些更改将永远不会合并回原始存储库(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

据我了解,这将防止任何合并提交,同时保持我的仓库最新。

1 个答案:

答案 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

可以将他们的提交KL复制到您的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 devgit rebase OR/master,那只会将您的IJ复制到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:您只需查看他们自上次共享提交以来所做的事情。

正是合并提交本身建立了更新的共享提交合并基础。如果没有合并提交,你没有得到更新的合并基础。合并提交很好;拥抱他们。 :-)