你可以从远程分支"改变"提交吗?

0 git version-control

我已经分叉了一个存储库,并希望在很长一段时间内对它进行维护和更改.这些更改永远不会合并回原始仓库(OR).但是,我确实希望从OR中获取任何新的更改.将这些提交添加到我的存储库时,我不想要很多合并提交; 如果有冲突,我知道他们是不可避免的.但大多数提交应该是干净的合并.

有没有办法从OR中"修改"这些提交?

我认为这git cherry-pick是一种方法,但OR会有很多变化,我不想每次都挑选.

我已经考虑过检查OR/master,在我的dev分支上重新定位它,然后ff将它合并回我的dev分支.

git checkout -b ORmaster OR/master
git rebase -i dev
git checkout dev
git merge --ff-only ORmaster
Run Code Online (Sandbox Code Playgroud)

但这意味着每次我想从OR/master合并时,我都要检查一个新的分支并重复这个.

有更简单的方法吗?

PS:我也不确定如何说出标题.如果有人能说得更好,请告诉我.

编辑:我添加了我认为我想要发生的事情.

A--B--C                   <-- OR/master, origin/master, master
Run Code Online (Sandbox Code Playgroud)

我添加了一些更改到我的分支

A--B--C                   <-- OR/master
       \
        D--E--F           <-- master
Run Code Online (Sandbox Code Playgroud)

其他人对OR/master进行了更改.

A--B--C--G                <-- OR/master
       \
        D--E--F           <-- master
Run Code Online (Sandbox Code Playgroud)

我想要这些更改,所以我想将它们应用到我的

A--B--C--G                <-- OR/master
       \
        D--E--F--G'       <-- master
Run Code Online (Sandbox Code Playgroud)

我想进行另一次更改,有人会对OR进行更改

A--B--C--G--I             <-- OR/master
       \
        D--E--F--G'-H     <-- master
Run Code Online (Sandbox Code Playgroud)

我想将OR更改应用到我的分支.

A--B--C--G--I             <-- OR/master
       \
        D--E--F--G'-H--I' <-- master
Run Code Online (Sandbox Code Playgroud)

据我了解,这将阻止任何合并提交,同时保持我的repo最新.

tor*_*rek 5

我已根据编辑过的问题对此进行了修订.这当然可以做到这一点,你可以让它更容易自动采摘樱桃,但你会偶尔遇到合并会更好的绊脚石.

首先,让我们看看如何自动完成挑选过程.假设OR存储库只添加提交 - 如更新问题中的图形 - 我们需要的是某种标记,以便我们知道哪个提交是我们之前提到的最后一个提交.

这个标记可以采用任何形式,并且可以提供内置的标记,特别是OR/master自身的reflog .但是为了说明如果没有别的 - 并且为了在存在reflog过期或其他可能导致问题的任何其他情况下更灵活 - 我们可以使用显式分支或标记名称.分支名称是最合适的,因为我们将以Git期望分支名称移动的通常方式移动它.

例如,让我们来看看这个阶段:

A--B--C--G                <-- OR/master
       \
        D--E--F--G'       <-- master
Run Code Online (Sandbox Code Playgroud)

(经过一次樱桃挑选).要记住我们已经专门停止了G,我们应该设置一个分支名称来指向G:

A--B--C--G                <-- marker, OR/master
       \
        D--E--F--G'       <-- master
Run Code Online (Sandbox Code Playgroud)

当我们下次有更新时,我们将添加到我们自己的`master中的提交数量并不重要,因为我们将拥有:

           I              <-- OR/master
          /
A--B--C--G                <-- marker
       \
        ...
Run Code Online (Sandbox Code Playgroud)

因此,复制提交很简单marker..OR/master,我们可以运行:

git checkout master                 # if needed
git cherry-pick marker..OR/master   # copy the new commits
Run Code Online (Sandbox Code Playgroud)

当这成功时,快速前进markerOR/master我们喜欢的任何方式,包括相当聪明(如果有点可怕):

git push . OR/master:marker
Run Code Online (Sandbox Code Playgroud)

(除非更新为marker快进操作,否则将拒绝执行任何操作).

但这可能会出错

有关何时出错的说明,请考虑如果OR/master获得包含合并的一系列提交会发生什么:

       ...--L
             \
           I--M--N        <-- OR/master
          /
A--B--C--G                <-- marker
       \
        ...
Run Code Online (Sandbox Code Playgroud)

现在提交的范围marker..OR/master包括提交M及其第二父母L以及之前L无法访问的内容G.我们应该复制哪些提交?我们可以实际上挑选M,只要我们单独使用一个-m参数 - 这将永远是-m 1- 并且这可能适用于您的情况.但这是一个问题,你应该知道它(并知道你打算怎么做).如果您使用git merge,如我在下面的原始建议中那样,这不是问题:一切都按照自己应有的方式运行.

(原始答案在分界线下方.)


所有git rebase做的就是复制犯(仿佛git cherry-pick-sometimes 字面上git cherry-pick),然后将一个分支的名字.

您可以随时复制任何提交,因此,您可以重新设置从其他Git存储库获取的提交.但是,这并不能帮助你实现目标.你应该做的是使用git merge.

以这种方式看待它:你的fork只是一个克隆,你的fork的克隆是你的克隆的克隆.除了有一个永远在线的地方存放你自己的克隆(你的分支),你基本上只是克隆原始克隆.因此,我们可以通过这种方式标记本地存储库中的内容:

...--F--G--H   <-- OR/master, origin/master, master
Run Code Online (Sandbox Code Playgroud)

其中每个大写字母表示唯一的提交哈希ID.(我们将在26次提交后用完,所以你可以看到为什么Git的实际哈希ID是如此之大和丑陋 - 它们必须永远是唯一的,每个人都曾在这些存储库,过去或将来做出的每次提交.)

现在,在某些时候,你已经做了自己的提交并将它们推送到origin(你自己的分支),所以现在你有了:

...--F--G--H   <-- OR/master
            \
             I--J   <-- master, origin/master
Run Code Online (Sandbox Code Playgroud)

origin/master总是会以符合您自己master以后你git push origin master,所以我们甚至不需要在这里管它.

同时,虽然,谁拥有,收纳库的乡亲让他们自己提交,这样后git fetch OR,你有这样的:

...--F--G--H--K--L   <-- OR/master
            \
             I--J   <-- master
Run Code Online (Sandbox Code Playgroud)

可以复制他们的提交KLK'L'让你有:

...--F--G--H--K--L   <-- OR/master
            \
             I--J   <-- master
                 \
                  K'-L'  <-- dev
Run Code Online (Sandbox Code Playgroud)

然后你可以快进你的master所以你有:

...--F--G--H--K--L   <-- OR/master
            \
             I--J--K'-L'  <-- dev, master
Run Code Online (Sandbox Code Playgroud)

最终他们会做出更多提交:

...--F--G--H--K--L--N--O   <-- OR/master
            \
             I--J--K'-L'  <-- dev, master
Run Code Online (Sandbox Code Playgroud)

(我已经跳过M保留它)也许你也有:

...--F--G--H--K--L--N--O   <-- OR/master
            \
             I--J--K'-L'  <-- dev
                       \
                        P--Q   <-- master
Run Code Online (Sandbox Code Playgroud)

但如果你现在git checkout devgit rebase OR/master,这只是要复制你IJI'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
Run Code Online (Sandbox Code Playgroud)

这真的不会让你到任何地方.

但是,如果你合并,你得到这个:

...--F--G--H--K--L   <-- OR/master
            \     \
             I--J--M   <-- master
Run Code Online (Sandbox Code Playgroud)

现在他们做出自己的提交而你做出了自己的提交:

...--F--G--H--K--L----N---O   <-- OR/master
            \     \
             I--J--M--P--Q   <-- master
Run Code Online (Sandbox Code Playgroud)

再一次,你只需git merge OR/master将他们的工作融入你的工作中:

...--F--G--H--K--L----N---O   <-- OR/master
            \     \        \
             I--J--M--P--Q--R   <-- master
Run Code Online (Sandbox Code Playgroud)

执行此合并时,必须解决任何合并冲突一次.如果您进行rebase,则必须再次重新解决所有过去的合并冲突.(使用git rerere可以帮助解决这个问题,但这对你的帮助有限.)你只需要解决一次的原因有两个:

  • 您正在进行一次新提交,因此只有一个地方发生冲突.
  • 在您进行合并提交M之后R,下一次合并将从公共合并库开始L,然后是O:您只需要查看自上次共享提交以来已完成的事情.

它是合并提交本身,它建立了更新的共享提交合并基础.如果没有合并提交,则不会获得更新的合并库.合并提交是好的; 拥抱他们.:-)