我已经分叉了一个存储库,并希望在很长一段时间内对它进行维护和更改.这些更改永远不会合并回原始仓库(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最新.
我已根据编辑过的问题对此进行了修订.这当然可以做到这一点,你可以让它更容易自动采摘樱桃,但你会偶尔遇到合并会更好的绊脚石.
首先,让我们看看如何自动完成挑选过程.假设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)
当这成功时,快速前进marker到OR/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)
您可以复制他们的提交K和L你K'并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 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
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:您只需要查看自上次共享提交以来已完成的事情.它是合并提交本身,它建立了更新的共享提交合并基础.如果没有合并提交,则不会获得更新的合并库.合并提交是好的; 拥抱他们.:-)