gpt4 book ai didi

git - git pull --rebase --preserve-merges

转载 作者:行者123 更新时间:2023-12-02 06:41:52 25 4
gpt4 key购买 nike

简洁版本:
仅在执行本地提交后才明确合并,才需要保留合并吗?否则会发生什么?是否将您提交的代码重新应用于合并分支?

请说明git pull --rebase --preserve-merges与常规git pull --rebase相比何时有用?
我在这里阅读了有关git pull --rebase的问题:
http://notes.envato.com/developers/rebasing-merge-commits-in-git/
这可能会导致代码更改重复。

我在这里阅读:When will `git pull --rebase` get me in to trouble?

仅当您在推送某些提交后基本重新建立基础之后,才会发生这种情况。

所以我不确定我何时需要git pull --rebase --preserve-merges以及与git pull --rebase一起使用是否不好。

最佳答案

从技术上讲-我声称这是git的愚蠢,pull脚本(这是一个Shell脚本)应该为您做到这一点-您必须运行git pull --rebase=preserve而不是尝试使用git pull --rebase --preserve-merges。 (或者,正如我在a comment上的Vlad Nikitin's answer中指出的那样,您可以将branch.name.rebase设置为preserve以自动获得相同的效果。)

换句话说,您永远不要运行git pull --rebase --preserve-merges,因为它(错误地)将--preserve-merges传递给fetch步骤,而不是merge-或-rebase步骤。但是,您可以运行git pull --rebase=preserve

何时(以及是否)使用任何类型的rebase(是否保留合并)的问题更多地是一个意见问题。首先,这意味着它在stackoverflow上确实表现不佳。 :-)

不过,在这里我要提出一个主张:只有在知道(从某种意义上来说)您正在做的事情时,才应该重新设置基准1,如果您知道自己在做什么,则可能更喜欢保留合并的基准作为一般规则,尽管当您决定重新定级是个好主意时,您可能会发现具有自己的嵌入式分支和合并点的历史记录不一定是正确的“最终重写历史记录”。

也就是说,如果完全适合进行重新基准设置,至少相当有可能要重新建立历史的记录本身是线性的,因此,无论如何,fserve-vs-flatten问题都无济于事。

编辑:添加图纸

这是提交图一部分的图形,显示了两个命名分支mainlineexperimentmainlineexperiment的共同基础是提交节点A,而mainline的提交G不在experiment分支上:

...--o--A-------------G   <-- mainline
\
\ .-C-.
B E--F <-- experiment
\_D_/

但是请注意 experiment分支中也有一个分支并合并:这两个分支的基础是 B,一个分支保存commit C,另一个分支保存commit D。这两个(未命名)分支在合并提交 E时收缩回到单个开发线程,然后commit 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

现在是提交图中的内容:
...--o--A--G               <-- mainline
\
B'-C'-D'-F' <-- experiment

分支 experiment上曾经存在的“结构分支”已消失。 rebase操作复制了我在commit BCDF中所做的所有更改;这些成为了新的提交 B'C'D'F'。 (commit 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.

我得到此图:
...--o--A--G               <-- mainline
\
\ .-C'.
B' E'-F' <-- experiment
\_D'/

这保留了 experiment的合并,并因此保留了“内部分支”。这样好吗坏?冷漠?阅读(很长)脚注!

1无论如何,学习“rebase的功能”是一个好主意,至少在中级水平上,这在git(alas!)中几乎也需要学习“它的操作方式”。基本上,rebase会复制(以前的更改)提交的副本,然后将其应用于(您或其他人的)以后的提交,使其“好像”以其他顺序进行了工作。一个简单的例子:两个开发人员(例如Alice和Bob)都在同一个分支上工作。假设Marketing要求提供一个功能代码,命名为Strawberry,而Alice和Bob都在为 strawberry的分支上做一些工作来实现 strawberry

爱丽丝(Alice)和鲍勃(Bob)都运行 git fetchstrawberryorigin引入。

爱丽丝发现文件 abc需要进行一些更改以准备新功能。她写下并提交,但尚未推送。

鲍勃(Bob)撰写了有关新功能的说明,该说明更改了文件 README,但没有其他效果。鲍勃做出改变并 push 。

然后,爱丽丝更新文件 feat以提供实际功能。她编写并提交(单独),现在可以进行推送了。但是,哦,不,鲍勃击败了她:
$ git push origin strawberry
...
! [rejected] strawberry -> strawberry (non-fast-forward)

然后,Alice应该获取更改并查看它们(不仅仅是盲目地合并或变基):
$ git fetch
...
$ git log origin/strawberry

(或使用 gitk或其他任何方法-我倾向于自己使用 git lola ,如果需要,可以单独使用 git show进行提交)。

从中可以看出,Bob仅更改了 README,因此她的更改绝对不会受到任何影响。在这一点上,她可以告诉您将更改重新基于 origin/strawberry是安全的:
$ git rebase origin/strawberry

(请注意,没有要保留的合并),这使它看起来(就git历史而言)就像她首先等待Bob更新文档,然后才真正开始实现更改-仍然分为两个单独的更改提交,以便稍后可以轻松判断对文件 abc的更改是否破坏了其他任何内容。不过,这两个单独的提交现在是相邻的,因此稍后可以很容易地看出,对 abc进行更改的目的是使对文件 feat的更改成为可能。而且,由于首先更改了 README,因此更加清楚的是,这就是更改 abc的目的。即使爱丽丝刚刚做了,也不是很难说:
$ git merge origin/strawberry

相反,尽管这会创建一个合并提交,其唯一的作用似乎是说“爱丽丝在鲍勃完成更新 abc之前就在 README上开始,然后在鲍勃完成了 feat的之后完成”,这并没有真正的帮助。

在更复杂的情况下,鲍勃所做的不仅仅是更新文档,爱丽丝可能会发现最好将自己的提交(在这种情况下,可能要超过两个)重新排列为新的,不同的线性历史记录,以便鲍勃的某些更改(例如,这次可能有多个提交)在“中间”,就好像它们是实时合作的一样(谁知道,也许他们做了)。或者,她可能会发现最好将更改保留为单独的开发线,并与Bob的更改进行合并,甚至可能不止一次。

将来,是否以及何时有必要回头看看(明显的,如果是重新定位的,如果有的话,)这一切都取决于将来如何向某人(可能是Alice和Bob,可能还有其他开发人员)提供最有用的信息。或实际(如果没有,则为实际)事件序列。有时,每个单独的提交都是有用的信息。有时重新排列和合并提交,或完全删除某些提交会更有用:例如,被证明是个坏主意的更改。 (但是考虑将它们留在上面的值(value)在于指出“这是一个坏主意,因此不要在将来再次尝试”!)

关于git - git pull --rebase --preserve-merges,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21364636/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com