git - 在分支上工作时变基和合并

git - rebase and merge when working on a branch

我已经阅读了很多,但合并和变基仍然让我感到困惑。

我有 2 个分支 -- DevelopFeatureFeature 分支是分支来自 Develop 提交之一。我用Dx代表Develop的提交,用Fx代表[的提交=35=]特征,其中x表示数字。

一开始,我想添加一个新功能,所以我从 Develop

分支了一个 Feature
Develop D1----D2
               \     
Feature         F1

几天后,我推送 Feature 中的一些提交,Develop 也是如此.

Develop D1----D2----D3----D4
               \
Feature         F1----F2----F3

我发现 Feature 需要 Develop 的更新,所以我决定应用 D3 和 D4 到我的 Feature

在我看来,rebase 是一个更好的选择,我的日志是这样的

Develop D1----D2----D3----D4
                           \
Feature                     F1----F2----F3

但实际上日志变成了

Develop D1----D2----D3----D4
               \
Feature         F1----F2----F3----D3----D4

现在是我的问题...在这种情况下我应该使用合并还是变基?

我认为这里 rebase 更好,但我在一些网站上发现了一条黄金法则,例如 git-scm.com 告诉 Do not rebase commits that exist outside你的仓库。

在我的情况下,D3 和 D4 是存在于我的存储库之外的提交吗?

据我了解,您只能在这种情况下合并。原因是您 已经推送 一些功能提交(我猜至少是 F1)。 这意味着那些提交不能被重新设置,否则你会把整个事情搞砸。

(除非你想对未推送的提交进行变基 - 但这意味着将功能提交分为两部分,这可能不好,具体取决于你的情况)


编辑以从评论中澄清更多内容

就像计算中的一切一样,这取决于您的意图:

我使用 rebase 来清理我的本地提交,我尝试尽可能频繁地提交,这意味着它有时会非常混乱,所以我会在推送之前使用 rebase 来清理它。

所以我的经验法则是变基用于需要清理的本地提交。因此,如果您正处于清理提交的阶段,请这样做。

如果将此更多地应用到您的场景中,

如果功能是由您单独开发的,那么我会使用 rebase 进行合并(因为在完成之前不会将任何内容推送到中央仓库)- 这不是您的情况。

由于功能可能与不同的人一起开发,您可能需要推送(如您的情况),在这种情况下,唯一的选择是合并。

我猜你的 D3 和 D4 更像是修补程序(希望尽早应用),然后有时这样做的方法是会有一个名为 hotfix 的开发分支,开发和功能都合并到.

实际上,您可以选择 mergerebase。变基会永久改变分支历史,但会产生更清晰的日志。

示例从 develop 分支开始


初始状态:

Develop*  D1----D2

CHECKOUT 新 feature 分支机构:(git checkout -b feature)

Develop  D1----D2
                \
Feature*         F1

中期:

Develop  D1----D2----D3----D4
                \
Feature*         F1----F2----F3

合并(git pull upstream develop):

Develop  D1----D2----D3---------D4
                                  \
Feature*         F1----F2----F3----[D3+D4]

引入新的合并提交。


重置 (git rebase upstream/develop)

Develop  D1----D2----D3----D4
                            \
Feature*                     F1'----F2'----F3'

这会更改 feature 分支的历史记录,并更改 feature 分支中所有提交的 SHA。这就是为什么 rebase 不推荐在分支 pushedremote.

上的原因

remotes/upstream/feature 分支现在与 local/feature 不同,您将无法使用 git push upstream feature 更新远程分支。

要使用当前更改重新启动分支,请使用 --force, -f 标志

# Use with caution. Cannot be reverted.
git push upstream feature -f

通过这一步,任何可能已经拉取/分叉您的分支的用户现在基本上与您的分支分离,并且在不改变他们的本地历史记录的情况下将无法推送到上游的 feature 分支。

But in fact, the log become

Develop D1----D2----D3----D4
               \
Feature         F1----F2----F3----D3----D4

我认为这是不正确的。根据this,日志应该是这样的

Develop D1----D2----D3----D4
                           \
Feature                     F1'----F2'----F3'

事实上,您的情况看起来与我上面提供的 link 中的 master-topic 分支示例非常相似。

你已经在你的代码中实现了你想要的:你有你的主人的变化以及你的 Features 的变化。现在的问题是与您的遥控器同步。

Do not rebase commits that exist outside your repository.

您已经在 Feature 分支中推送了提交。这意味着,有人可能一直在拉取这些提交,并且目前正在处理这些提交。当你像上面那样做 rebase 时,请注意你的提交 F1F2F3 变成了 F1'F2'F3'。这些是全新的提交,尽管它们包含相同的更改。如果你现在将它们推送到你的远程,覆盖旧的历史记录,在旧提交之上工作的人将 运行 在他们想要推送他们的工作时遇到问题。

这样的 Rebase 总是会引入新的提交。 Git 将不允许你推送这些提交,如果你已经推送了你的旧提交,除非你使用 --force 选项。一般而言,rebase 仅在本地更改更安全,这样您可以确定没有人在它们之上工作,因此修改它们的历史记录是安全的。

另见 this question 的解释。

编辑:正如评论中 Tim Biegeleisen 所述,不需要合并或变基,因为您已经有了所有更改。但是,如果您现在推送,则必须执行强制推送,因为您重写了您的 Feature 分支历史记录,如果其他人可能已经在您的更改之上工作,则不建议这样做。