当我使用 Git 时,我应该在合并之前重新设置基准吗?
Posted
技术标签:
【中文标题】当我使用 Git 时,我应该在合并之前重新设置基准吗?【英文标题】:When I am using Git, should I rebase before I merge? 【发布时间】:2012-02-25 09:22:41 【问题描述】:我正在处理一个大型 Rails 项目,我正在与之合作的团队正在使用 Github 来管理该项目。虽然许多更改是在本地进行的,然后直接推送到我们的开发分支,但当我们要进行非常大的更改时,我们会创建一个分支。当需要将该分支合并回开发时,我经常尝试在将功能分支合并到开发之前将开发重新设置回我的功能分支(以防止覆盖其他人的工作)。我发现当我这样做时,我似乎遇到了两次相同的合并冲突。我在变基时遇到了整个冲突列表,然后在合并时再次遇到相同的冲突列表。在将我的功能合并到开发之前,我应该将开发重新设置到我的功能分支中,还是应该将我的功能合并到开发中?
假设我的功能分支称为“new_feature”。我将它与“开发”分支合并的过程如下:
git checkout develop
git pull (this is set up on our rig to always pull rebase)
git checkout new_feature
git rebase develop
(lots of merge conflicts ensue)
git checkout develop
git merge -no-ff new_feature
(same set of merge conflicts again)
就好像时间线从我的 rebase 发生变化导致我的新功能分支一路镜像开发,然后与自身的伪副本发生冲突。
【问题讨论】:
为什么是git merge -no-ff
?如果您只是将 new_feature 重新定位到 develop 上,它应该是一个快进。
我真的不确定。有一段时间,我们这里有个真正了解 Git 的人,他告诉我,出于某种与清理时间线有关的原因,我应该这样做。我真的不知道是什么原因。
我可以看到它可能会使时间线混乱......嗯。 rebase 将 new_feature
上的所有提交替换为应用于 develop
而不是原始分支点的等效更改,这意味着您将获得(副本)旧提交,其父母(在原始分支点和 @987654325 之间) @) 比他们老。
我没有将 new_feature 重新定位到开发上,是吗?我以为我正在重新开发新功能。
使用--no-ff
背后的原因是即使合并是快进的,它也会对提交进行逻辑分组,从而保持它们在历史上的某个时间点位于分支中的事实。当分支上有许多提交时,它特别有用,并且看到它们都是与添加的上下文相同的功能分支的一部分是有意义的。
【参考方案1】:
重新定义您的功能分支,合并它,完成。在我看来,“在合并之前重新定义功能分支”是一种最佳实践。
永远不要改变开发,永远不要修改主干的历史(除非你和你的团队,你知道自己在做什么)。
变基只是从分支的开头开始的一系列精选。当你 rebase 开发到特性分支时,你实际上把所有的开发提交放在特性分支的顶部,这没有任何意义。
在合并功能分支后继续工作时,只需从开发中启动一个新分支,即可开始工作。
【讨论】:
【参考方案2】:由于您在同一个问题中指定“大规模”和“变基”,我建议您不要这样做。请改用合并。
在合并中使用 --no-ff 非常适合保留原始分支点。我支持使用它。
【讨论】:
声称“大规模”和“变基”相互不合适是不正确的。无论项目有多大,在使用功能分支时,在合并之前对其进行变基实际上是最佳实践。出了什么问题,这些尝试变基开发是否被团队使用,无论项目规模如何(在绝大多数情况下),这是一种不好的做法。【参考方案3】:好的,现在评论太长了。
解释手册 (git help rebase
)
Assume the following history exists and the current branch is "new_feature":
A---B---C new_feature
/
D---E---F---G develop
From this point, the result of either of the following commands:
git rebase develop
git rebase develop new_feature
would be:
A'--B'--C' <new_feature
/
D---E---F---G <develop
现在,如果您有冲突,第一次运行 rebase
后的实际状态将是
A'--B'--C'--[local state]
/ ^
D---E---F---G new_feature
^ develop
其中[local state]
是您尚未修复的冲突合并。
解决合并冲突并将已解决的文件添加到索引后,运行 git rebase --continue
:现在您的状态将是
A'--B'--C'--H <new_feature
/
D---E---F---G <develop
显然,此时将 new_feature 合并回 develop 可以像这样快进:
A'--B'--C'--H <new_feature <develop
/
D---E---F---G
但如果不是,你会得到这个
A'--B'--C'--H <new_feature
/ \
D---E---F---G---------------I <develop
现在,从时间线的角度来看,无论你喜欢哪一个,都不清楚为什么会有问题......除非你从未完成 rebase 并解决了与 H
的冲突,但我认为 git 会抱怨关于那个。
【讨论】:
“但如果不是,你会得到这个”? “不是”什么?我不明白如何导致这两种情况。有什么区别? "...可以快进...但如果不是..."。如果您选择不快进合并,使用--no-ff
,您将获得合并提交,而不是仅仅移动分支指针,如图所示。但是,如果您一开始不了解这两种情况,您可能需要提出自己的问题或以其他方式了解有关 git 的更多信息,因为我无法真正猜出这个答案在哪里迷失了您。【参考方案4】:
在我看来,您好像是在向后使用变基,但这可能只是一个令人困惑的措辞。
我会将功能分支重新设置为基础到开发,然后(在开发时)执行git merge --ff-only feature
。
【讨论】:
我正在编辑我的帖子以显示过程,看看我是否弄错了。 正如@Useless 评论的那样,合并应该是快进的(我更喜欢使用--ff-only 来强制它)。其余的似乎都还可以,尽管您用文字表达的方式不是标准。我建议阅读progit.org/book以上是关于当我使用 Git 时,我应该在合并之前重新设置基准吗?的主要内容,如果未能解决你的问题,请参考以下文章