简短版本:只有在执行本地提交后明确合并时,是否需要保留合并?究竟会发生什么?它是否将您提交的代码重新应用于合并的分支?
请解释什么时候git pull --rebase --preserve-merges对常规有用git pull --rebase?我git pull --rebase在这里阅读了一个问题:http:
//notes.envato.com/developers/rebasing-merge-commits-in-git/
这可能会导致代码更改重复.
我在这里读到:什么时候`git pull --rebase`让我陷入困境?
只有在你提交了一些提交后才基本上进行了修改,才会发生这种情况.
所以我不确定我什么时候需要git pull --rebase --preserve-merges,如果使用它就不好了 git pull --rebase.
tor*_*rek 47
从技术上讲 - 我声称这有点愚蠢的git,pull脚本(它是一个shell脚本)应该只为你做这个 - 你必须运行git pull --rebase=preserve而不是试图使用git pull --rebase --preserve-merges.(或者,正如我在Vlad Nikitin的回答评论中指出的那样,你可以设置为自动获得相同的效果.)branch.name.rebasepreserve
换句话说,你应该永远不会运行git pull --rebase --preserve-merges,因为它(错误地)传递--preserve-merges给fetch代替步骤,merge-或- rebase步.但是,你可以运行git pull --rebase=preserve.
何时(以及是否)使用任何类型的rebase,无论是否合并,更多的是意见问题.这意味着它首先在stackoverflow上表现不佳.:-)
不过,我在这里做一个要求:如果你知道(在那种一般意义上的),你应该只重订,你在做什么,1,如果你不知道自己在做什么,你可能会喜欢一个合并保变基作为一般规则,虽然当您决定变基是一个好主意时,您可能会发现具有自己的嵌入式分支和合并点的历史记录不一定是正确的"最终重写历史记录".
也就是说,如果根本不适合进行变基,那么至少相当可能的是,重新定位的历史本身是线性的,因此无论如何,保留与展平的问题都没有实际意义.
这是一张提交图的一部分,显示了两个命名分支,mainline以及experiment.为共基极mainline和experiment是提交节点A,并且mainline已经提交G,是不是在experiment分支:
...--o--A-------------G <-- mainline
\
\ .-C-.
B E--F <-- experiment
\_D_/
Run Code Online (Sandbox Code Playgroud)
注意,experiment分支在其中也有一个分支和合并,但是:这两个分支的基础是B,一个分支持有提交C,另一个分支持有提交D.这两个(未命名的)分支在合并提交时缩减回单个开发线程E,然后提交F位于合并提交的顶部,并且是分支的提示experiment.
如果您正在experiment运行并发生以下情况git rebase mainline:
$ git rebase mainline
First, rewinding head to replay your work on top of it...
Applying: B
Applying: C
Applying: D
Applying: F
Run Code Online (Sandbox Code Playgroud)
这是提交图中现在的内容:
...--o--A--G <-- mainline
\
B'-C'-D'-F' <-- experiment
Run Code Online (Sandbox Code Playgroud)
以前在分支上的"结构分支" experiment已经消失.该rebase操作复制了所有的变化我会在提交了几次B,C,D,和F; 这些成为了新的提交B',C',D',和F'.(提交E是纯粹的合并,没有任何更改,也不需要复制.我没有测试如果我使用嵌入式更改来修改合并会发生什么,要么解决冲突,要么就像有人称之为"邪恶合并".)
另一方面,如果我这样做:
$ git rebase --preserve-merges mainline
[git grinds away doing the rebase; this takes a bit longer
than the "flattening" rebase, and there is a progress indicator]
Successfully rebased and updated refs/heads/experiment.
Run Code Online (Sandbox Code Playgroud)
我得到这个图:
...--o--A--G <-- mainline
\
\ .-C'.
B' E'-F' <-- experiment
\_D'/
Run Code Online (Sandbox Code Playgroud)
这保留了合并,因此保留了"内部分支" experiment.这样好吗?坏?冷漠?阅读(很长)脚注!
1无论如何,学习"什么是rebase"是一个好主意,这在git(唉!)中非常需要学习"它是如何做到的",至少在中等水平上.基本上,rebase会复制(之前的更改)提交,然后您应用于(您或其他人的)稍后提交,使其"看起来像"您以其他顺序完成工作.一个简单的例子:两个开发人员,比如Alice和Bob,都在同一个分支上工作.假设Marketing已经要求使用代号为Strawberry的功能,并且Alice和Bob都在做一些工作来实现strawberry,两者都在一个名为的分支上strawberry.
Alice和Bob都运行git fetch带来strawberry结束origin.
Alice发现该文件abc需要进行一些更改以准备新功能.她写道并承诺,但尚未推出.
Bob写了一个新功能的描述,它改变了文件README,但没有其他效果.鲍勃承诺改变并推动.
Alice随后更新文件feat以提供实际功能.她(并单独)编写并提交,现在已经准备好了.但是,哦,不,鲍勃打败她:
$ git push origin strawberry
...
! [rejected] strawberry -> strawberry (non-fast-forward)
Run Code Online (Sandbox Code Playgroud)
然后,Alice应该获取更改并查看它们(不只是盲目合并或重新绑定):
$ git fetch
...
$ git log origin/strawberry
Run Code Online (Sandbox Code Playgroud)
(或者使用gitk或者其他 - 我倾向于使用git lola自己,git show如果需要,个人提交).
她可以从中看出鲍勃只是改变了README,所以她的改变绝对不会受到任何影响.此时,她可以告诉她将更改改为origin/strawberry:
$ git rebase origin/strawberry
Run Code Online (Sandbox Code Playgroud)
(请注意,没有合并要保留),这使得它看起来(就git历史而言)就像她第一次等待Bob更新文档一样,然后实际上才开始实现更改 - 这些仍然分为两个单独的提交以便以后很容易判断文件的更改是否abc破坏了其他内容.这两个不同的提交现在是相邻的,虽然如此,很容易分辨,后来,该点的变化的abc是让变化到文件feat.而且,由于变革README首先出现,更为明确的是,这是变革的重点abc.并不是说即使爱丽丝刚才这么做也很难说:
$ git merge origin/strawberry
Run Code Online (Sandbox Code Playgroud)
相反,虽然这会创建一个合并提交,其唯一的一点似乎就是说"Alice abc在Bob完成更新之前就开始了README,然后完成feat了",这实际上没有用.
在更复杂的情况下,Bob所做的不仅仅是更新文档,Alice可能会发现最好将自己的提交(在这种情况下可能超过两个)重新排列成一个新的,不同的线性历史记录,以便Bob的一些更改(例如,这次,可能不止一次提交)"在中间",好像他们实时合作(谁知道,也许他们这样做).或者她可能会发现,最好将她的变化作为一个单独的开发线,与Bob的变化合并,甚至可能不止一次.
这一切都是为了向某人提供最有用的信息 - 可能是爱丽丝和鲍勃,可能是其他开发人员 - 将来,如果有必要回去看看(显而易见,如果已经重新定位,或者实际如果不是)事件序列.有时每次提交都是有用的信息.有时重新排列和组合提交,或完全删除一些提交更有用:例如,被证明是一个坏主意的更改.(但考虑让他们留下来只是为了指出"这是一个坏主意,所以不要再尝试它了!")