小编典典

为什么git默认执行快进合并?

all

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

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

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

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


阅读 199

收藏
2022-03-04

共1个答案

小编典典

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

警告 :非快进也有潜在的副作用。请查看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 默认使用匿名轻量级代码行,在其术语中称为“heads”。
Git 使用轻量级命名分支,通过单射映射将远程存储库中的分支名称映射到远程跟踪分支的名称。
Git“强制”你命名分支(嗯,除了单个未命名的分支,这是一种称为“分离的
HEAD ”的情况),但我认为这更适用于分支繁重的工作流,例如主题分支工作流,意思是单个存储库范例中的多个分支。

2022-03-04