快进合并对于短期的分支是有意义的,但是对于更复杂的历史记录,非快进合并可能会使历史记录更容易理解,并且更容易恢复一组提交。
警告:非快进也有潜在的副作用。请查看https://sandofsky.com/blog/git-workflow.html,避免“no-ff”的“检查点提交”打破平分或责备,并仔细考虑它是否应该是您的master默认方法。
(来自nvie.com, Vincent Driessen, post“一个成功的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 narabbski也提到了config 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在评论中补充道:
对于[短寿命]分支,我认为快进是有意义的,但将其作为默认操作意味着git假设您……通常有[短命的]分支。合理吗?
杰弗罗米回答:
I think the lifetime of branches varies greatly from user to user. Among experienced users, though, there's probably a tendency to have far more short-lived branches.
To me, a short-lived branch is one that I create in order to make a certain operation easier (rebasing, likely, or quick patching and testing), and then immediately delete once I'm done.
That means it likely should be absorbed into the topic branch it forked from, and the topic branch will be merged as one branch. No one needs to know what I did internally in order to create the series of commits implementing that given feature.
更笼统地说,我补充说:
这取决于你的开发流程:
如果它是线性的,一个分支是有意义的。
如果您需要隔离特性,并在它们上花费很长一段时间并反复地合并它们,那么几个分支是有意义的。
参见“何时应该进行分支?”
实际上,当您考虑Mercurial分支模型时,它的核心是每个存储库一个分支(即使您可以创建匿名头、书签甚至命名分支)。
参见“Git和Mercurial -比较和对比”。
Mercurial, by default, uses anonymous lightweight codelines, which in its terminology are called "heads".
Git uses lightweight named branches, with injective mapping to map names of branches in remote repository to names of remote-tracking branches.
Git "forces" you to name branches (well, with the exception of a single unnamed branch, which is a situation called a "detached HEAD"), but I think this works better with branch-heavy workflows such as topic branch workflow, meaning multiple branches in a single repository paradigm.