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

Flo*_*ilz 637 git git-merge fast-forward git-branch

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

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

因此,思考未来:我是唯一一个从事这个项目的人.如果我使用git的默认方法(快进合并),我的历史将导致一个巨大的主分支.没有人知道我为每个功能使用了一个单独的分支,因为最后我只有那个巨大的主分支.这看起来不专业吗?

通过这种推理,我不想要快进合并,也不知道为什么它是默认的.这有什么好处的?

Von*_*onC 713

快速合并对于短期分支是有意义的,但是在更复杂的历史中,非快进合并可以使历史更容易理解,并且更容易恢复一组提交.

警告:非快进也有潜在的副作用.请查看https://sandofsky.com/blog/git-workflow.html,避免'no-ff'及其"checkpoint commit"打破平分或责备,并仔细考虑它是否应该是您的默认方法master.

替代文字
(来自nvie.com,Vincent 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
Run Code Online (Sandbox Code Playgroud)

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

JakubNarę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
Run Code Online (Sandbox Code Playgroud)

OP在评论中添加:

我认为[短命]分支的快进有一定意义,但是将其作为默认动作意味着git假设你...通常有[短命]分支.合理?

Jefromi回答:

我认为分支的生命周期因用户而异.然而,在有经验的用户中,可能存在更多短期分支的趋势.

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

更一般地说,我补充说:

这真的取决于您的开发工作流程:

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

请参阅" 何时应该分支? "

实际上,当你考虑Mercurial分支模型时,它的核心每个存储库的一个分支(即使你可以创建匿名头,书签甚至命名分支)
参见"Git和Mercurial - 比较和对比".

默认情况下,Mercurial使用匿名轻量级代码行,在其术语中称为"头".
Git使用轻量级命名分支,使用内射映射将远程存储库中分支的名称映射到远程跟踪分支的名称.
Git"强迫"你命名分支(好吧,除了一个未命名的分支,这是一种称为" 分离的HEAD "的情况),但我认为这对于分支繁重的工作流程(如主题分支工作流程,意义更好)更有效单个存储库范例中的多个分支.

  • @BehrangSaeedzadeh:一个rebase本身不会使历史成为线性的.这是*如何*将你的`feature`分支的变化整合回到`master`中,这使得历史记录成为线性或非线性.一个简单的快速合并将使其成为线性.如果你在快进合并之前清理了那个`feature`分支*的历史记录,那么这是有意义的,只留下重要的提交,如http://stackoverflow.com/questions/7425541/git-newbie-question-中所述 - 承诺式提交 - 全变 - 文件 - 在一次或 - 一个-AT-A/7425751#7425751. (4认同)
  • @BehrangSaeedzadeh:变基是另一个主题(在本页中没有提到):只要你没有将你的`feature`分支推送到公共仓库,你就可以在`master`之上重新定义它.很多时候你想要的.见http://stackoverflow.com/questions/5250817/git-rebase-loses-history-then-why-rebase/5250878#5250878 (2认同)

Jak*_*ski 41

让我展开一个有点VonC非常全面的回答:


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

请注意,功能分支的有用性以及在单个存储库中具有多个分支的功能仅在稍后出现,具有良好的合并支持的VCS的更广泛使用以及尝试各种基于合并的工作流.这就是为什么例如Mercurial最初只支持每个存储库一个分支(加上用于跟踪远程分支的匿名提示),如旧版"Mercurial:The Definitive Guide"中所示.


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

HTH


归档时间:

查看次数:

149721 次

最近记录:

6 年,10 月 前