git - 在分支上工作时变基和合并
git - rebase and merge when working on a branch
我已经阅读了很多,但合并和变基仍然让我感到困惑。
我有 2 个分支 -- Develop 和 Feature,Feature 分支是分支来自 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 的开发分支,开发和功能都合并到.
实际上,您可以选择 merge
或 rebase
。变基会永久改变分支历史,但会产生更清晰的日志。
示例从 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 不推荐在分支 pushed 到 remote
.
上的原因
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 分支示例非常相似。
你已经在你的代码中实现了你想要的:你有你的主人的变化以及你的 Feature
s 的变化。现在的问题是与您的遥控器同步。
Do not rebase commits that exist outside your repository.
您已经在 Feature
分支中推送了提交。这意味着,有人可能一直在拉取这些提交,并且目前正在处理这些提交。当你像上面那样做 rebase 时,请注意你的提交 F1
、F2
、F3
变成了 F1'
、F2'
、F3'
。这些是全新的提交,尽管它们包含相同的更改。如果你现在将它们推送到你的远程,覆盖旧的历史记录,在旧提交之上工作的人将 运行 在他们想要推送他们的工作时遇到问题。
这样的 Rebase 总是会引入新的提交。 Git 将不允许你推送这些提交,如果你已经推送了你的旧提交,除非你使用 --force
选项。一般而言,rebase
仅在本地更改更安全,这样您可以确定没有人在它们之上工作,因此修改它们的历史记录是安全的。
另见 this question 的解释。
编辑:正如评论中 Tim Biegeleisen
所述,不需要合并或变基,因为您已经有了所有更改。但是,如果您现在推送,则必须执行强制推送,因为您重写了您的 Feature
分支历史记录,如果其他人可能已经在您的更改之上工作,则不建议这样做。
我已经阅读了很多,但合并和变基仍然让我感到困惑。
我有 2 个分支 -- Develop 和 Feature,Feature 分支是分支来自 Develop 提交之一。我用Dx代表Develop的提交,用Fx代表[的提交=35=]特征,其中x表示数字。
一开始,我想添加一个新功能,所以我从 Develop
分支了一个 FeatureDevelop 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 的开发分支,开发和功能都合并到.
实际上,您可以选择 merge
或 rebase
。变基会永久改变分支历史,但会产生更清晰的日志。
示例从 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 不推荐在分支 pushed 到 remote
.
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 分支示例非常相似。
你已经在你的代码中实现了你想要的:你有你的主人的变化以及你的 Feature
s 的变化。现在的问题是与您的遥控器同步。
Do not rebase commits that exist outside your repository.
您已经在 Feature
分支中推送了提交。这意味着,有人可能一直在拉取这些提交,并且目前正在处理这些提交。当你像上面那样做 rebase 时,请注意你的提交 F1
、F2
、F3
变成了 F1'
、F2'
、F3'
。这些是全新的提交,尽管它们包含相同的更改。如果你现在将它们推送到你的远程,覆盖旧的历史记录,在旧提交之上工作的人将 运行 在他们想要推送他们的工作时遇到问题。
这样的 Rebase 总是会引入新的提交。 Git 将不允许你推送这些提交,如果你已经推送了你的旧提交,除非你使用 --force
选项。一般而言,rebase
仅在本地更改更安全,这样您可以确定没有人在它们之上工作,因此修改它们的历史记录是安全的。
另见 this question 的解释。
编辑:正如评论中 Tim Biegeleisen
所述,不需要合并或变基,因为您已经有了所有更改。但是,如果您现在推送,则必须执行强制推送,因为您重写了您的 Feature
分支历史记录,如果其他人可能已经在您的更改之上工作,则不建议这样做。