656

来自 mercurial,我使用分支来组织功能。自然,我也想在我的历史中看到这种工作流程。

我使用 git 开始了我的新项目并完成了我的第一个功能。合并功能时,我意识到 git 使用快进,即如果可能,它会将我的更改直接应用到主分支,而忘记我的分支。

所以想想未来:我是唯一一个在这个项目上工作的人。如果我使用 git 的默认方法(快进合并),我的历史将导致一个巨大的主分支。没有人知道我为每个功能都使用了一个单独的分支,因为最终我将只有那个巨大的 master 分支。会不会显得不专业?

通过这种推理,我不希望快进合并,也看不出它为什么是默认值。它有什么好?

4

2 回答 2

732

快进合并对短暂的分支有意义,但在更复杂的历史中,非快进合并可能会使历史更容易理解,并且更容易恢复一组提交。

警告:非快进也有潜在的副作用。请查看https://sandofsky.com/blog/git-workflow.html,避免使用“检查点提交”打破平分或指责的“no-ff”,并仔细考虑它是否应该是您的默认方法master

替代文字
(来自nvie.comVincent Driessen,发表“一个成功的 Git 分支模型”)

在开发中合并一个已完成的功能

完成的功能可以合并到开发分支中,以将它们添加到即将发布的版本中:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

--no-ff标志会导致合并始终创建一个新的提交对象,即使可以使用快进执行合并。这样可以避免丢失有关功能分支的历史存在的信息,并将所有添加该功能的提交组合在一起。

Jakub Narębski提到配置merge.ff

默认情况下,Git 在合并作为当前提交的后代的提交时不会创建额外的合并提交。相反,当前分支的尖端是快进的。
当设置为 时false,这个变量告诉 Git 在这种情况下创建一个额外的合并提交(相当于--no-ff从命令行提供选项)。
当设置为 ' only' 时,只允许这样的快进合并(相当于--ff-only从命令行给出选项)。


快进是默认设置,因为:

  • 短期分支在 Git 中很容易创建和使用
  • 短暂的分支通常会隔离许多可以在该分支内自由重组的提交
  • 这些提交实际上是主分支的一部分:一旦重组,主分支就会快速转发以包含它们。

但是,如果您期望在一个主题/功能分支上进行迭代工作流(即,我合并,然后我返回此功能分支并添加更多提交),那么在主分支中仅包含合并是有用的,而不是功能分支的所有中间提交。

在这种情况下,您最终可以设置这种配置文件

[branch "master"]
# This is the list of cmdline options that should be added to git-merge 
# when I merge commits into the master branch.

# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.

# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.

mergeoptions = --no-commit --no-ff

OP在评论中添加:

我认为 [short-lived] 分支的快进有些意义,但将其设为默认操作意味着 git 假设您......经常有 [short-lived] 分支。合理的?

杰弗罗米回答:

我认为分支的生命周期因用户而异。但是,在有经验的用户中,可能倾向于拥有更多短命的分支。

对我来说,一个短暂的分支是我创建的,目的是使某个操作更容易(变基、可能或快速修补和测试),然后在我完成后立即删除。
这意味着它可能应该被吸收到它派生出来的主题分支中,并且主题分支将合并为一个分支。没有人需要知道我在内部做了什么来创建实现该给定功能的一系列提交。

更一般地说,我补充说:

这实际上取决于您的开发工作流程

  • 如果它是线性的,那么一个分支是有意义的。
  • 如果您需要隔离特征并长时间处理它们并反复合并它们,那么几个分支是有意义的。

请参阅“什么时候应该分支?

实际上,当您考虑 Mercurial 分支模型时,它的核心是每个存储库一个分支(即使您可以创建匿名头、书签甚至命名分支
请参阅“Git 和 Mercurial - 比较和对比”

Mercurial 默认使用匿名轻量级代码行,在其术语中称为“heads”。
Git 使用轻量级命名分支,通过单射映射将远程存储库中的分支名称映射到远程跟踪分支的名称。
Git“强制”你命名分支(嗯,除了单个未命名的分支,这是一种称为“分离的 HEAD ”的情况),但我认为这更适用于分支繁重的工作流程,例如主题分支工作流程,意思是单个存储库范例中的多个分支。

于 2010-05-17T15:31:36.253 回答
45

让我稍微扩展一下VonC非常全面的答案


首先,如果我没记错的话,Git 默认情况下不会在快进情况下创建合并提交这一事实来自考虑单分支“相等存储库”,其中相互拉动用于同步这两个存储库(a您可以在大多数用户的文档中找到作为第一个示例的工作流,包括“The Git 用户手册”和“示例版本控制”)。在这种情况下,您不使用 pull 来合并完全实现的分支,而是使用它来跟上其他工作。当您碰巧将同步保存并存储在存储库中以备将来使用时,您不希望有短暂且不重要的事实。

Note that usefulness of feature branches and of having multiple branches in single repository came only later, with more widespread usage of VCS with good merging support, and with trying various merge-based workflows. That is why for example Mercurial originally supported only one branch per repository (plus anonymous tips for tracking remote branches), as seen in older revisions of "Mercurial: The Definitive Guide".


其次,当遵循使用特性分支的最佳实践时,即特性分支都应该从稳定版本开始(通常从上一个版本开始),以便能够通过选择要合并的特性分支来挑选和选择要包含的特性,你通常不会处于快进状态......这使得这个问题没有实际意义。在合并第一个分支时,您需要担心创建真正的合并而不是快进(假设您没有将单次提交更改直接放在“master”上);所有其他后来的合并当然都处于非快进的情况。

高温高压

于 2013-05-31T13:30:21.787 回答