何时在 Git 中使用“--no-ff”合并选项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18126297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use the '--no-ff' merge option in Git
提问by Leif
A Successful Git Branching Modelrecommends to use --no-ff
when merging branches:
--no-ff
合并分支时建议使用成功的 Git 分支模型:
The
--no-ff
flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature. […]Yes, it will create a few more (empty) commit objects, but the gain is much bigger that that cost. Unfortunately, I have not found a way to make
--no-ff
the default behavior of git merge yet, but it really should be.
该
--no-ff
标志导致合并总是创建一个新的提交对象,即使合并可以用快进执行。这避免了丢失有关功能分支的历史存在的信息,并将所有一起添加功能的提交组合在一起。[…]是的,它会创建更多(空)提交对象,但收益比成本要大得多。不幸的是,我还没有找到一种方法来使
--no-ff
git merge 的默认行为,但它确实应该是。
Understanding the Git Workflow, however, recommends notto use --no-ff
:
然而,了解 Git Workflow建议不要使用--no-ff
:
So you add a new rule: “When you merge in your feature branch, use
–-no-ff
to force a new commit.” This gets the job done, and you move on. […]The
--no-ff
band-aid, brokenbisect
, andblame
mysteries are all symptoms that you're using a screwdriver as a hammer. […]
所以你添加了一个新规则:“当你在你的功能分支中合并时,使用
–-no-ff
来强制一个新的提交。” 这完成了工作,然后您继续前进。[…]
Both approaches seem reasonable for difference scenarios, but what is considered "good practice?"
对于不同的场景,这两种方法似乎都是合理的,但什么被认为是“好的做法”?
When do you use --no-ff
, when do you not, why?
什么时候用--no-ff
,什么时候不用,为什么?
采纳答案by Tomas
It's really dependent on what you're trying to do. My rule of thumb is that if the merge "means something" I use the --no-ff option. When the merge doesn't really mean anything and you might have used a rebase there's no reason to use --no-ff
这真的取决于你想要做什么。我的经验法则是,如果合并“有意义”,我会使用 --no-ff 选项。当合并实际上没有任何意义并且您可能使用了 rebase 时,就没有理由使用 --no-ff
The thing with git is that it's a very powerful tool, and you can use it in many ways - most of which are not wrong. Asking what's the "right way" to do it is like asking what's the right way to paint a picture.
git 的问题在于它是一个非常强大的工具,您可以通过多种方式使用它——其中大部分都没有错。问什么是“正确的方法”,就像问画画的正确方法是什么。
At least for me it's an evolving set of ways I like to do it, with frequent discussions in the team of how we want to collaborate on the code - from this we try to derive a kind of "how it's done here" standard, but it's just our way of doing it.
至少对我来说,这是一套不断发展的方法,我喜欢这样做,团队中经常讨论我们希望如何在代码上进行协作——由此我们试图推导出一种“这里是如何完成的”标准,但是这只是我们的做法。
回答by Tomas
For the case of a finished branch with a single commit, don't use --no-ff
, just fast-forward it, because the history will be much simpler and less cluttered. It's hard to argue that --no-ff
gets you any advantages in this case, because it's uninteresting to see a parallel branch of development with just a single commit, vs a single commit in a sequential line:
对于具有单个提交的已完成分支的情况,不要使用--no-ff
,只需快进它,因为历史会更简单且不那么混乱。--no-ff
在这种情况下,很难说这会给你带来任何好处,因为看到一个并行的开发分支只有一个提交,而不是一个顺序行中的单个提交,这很无趣:
# No fast-forward
$ git merge --no-ff awesome-feature
* 3aa649c Merge branch 'awesome-feature'
|\
| * 35ec88f Add awesome feature
|/
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003
# versus fast-forward
$ git merge awesome-feature
* 35ec88f Add awesome feature
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003
For the case of a finished branch with more than a single commit, it's up to you, whether or not you want to keep the fact that the branched development happened in parallel vs sequential. I would probably use --no-ff
for more than one commit, just so that I can visually see this branched work, and so that I can manipulate it easily with a single git revert -m 1 <sha-of-merge-commit>
if I had to.
对于具有多个提交的完成分支的情况,这取决于您,是否要保留分支开发并行而不是顺序发生的事实。我可能会--no-ff
用于多次提交,这样我就可以直观地看到这个分支工作,并且git revert -m 1 <sha-of-merge-commit>
如果需要的话,我可以轻松地用一个来操作它。
# No fast-forward
$ git merge --no-ff epic-feature
* d676897 Merge branch 'epic-feature'
|\
| * ba40d93 Add octocat.txt
| * b09d343 Add bye.txt
| * 75e18c8 Add hello.txt
|/
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003
# versus fast-forward
$ git merge epic-feature
* ba40d93 Add octocat.txt
* b09d343 Add bye.txt
* 75e18c8 Add hello.txt
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003
See how in this case of fast-forward merge, without additional information in the commit messages themselves, it's hard to tell that the last 3 commits actually belong together as one feature?
看看在这种快进合并的情况下,在提交消息本身没有附加信息的情况下,很难说最后 3 个提交实际上属于一个功能吗?
回答by Jonatan Goebel
That really depends on your workflow, and how you are using branches.
这真的取决于你的工作流程,以及你如何使用分支。
Let′s say you have a "master" and two feature branches, "foo" and "bar", in development.
假设您有一个“master”和两个功能分支,“foo”和“bar”,正在开发中。
In this case, the branches only exist to allow different developer work without conflict, when the features are done, they need to be merged into master, and it is not important to know if those features were implemented in different branches.
在这种情况下,分支的存在只是为了让不同的开发人员工作而不会发生冲突,当功能完成时,它们需要合并到 master 中,而知道这些功能是否在不同的分支中实现并不重要。
But you could have a different workflow, were the branches, "foo" and "bar", refers to independent modules in your system.
但是你可以有一个不同的工作流程,分支“foo”和“bar”是指你系统中的独立模块。
In this case, some commits may change files outside the module scope. When you merge those two branches to the master, the log of the files, outside the specific module, may become confusing and hard to know where those changes come from.
在这种情况下,某些提交可能会更改模块范围之外的文件。当您将这两个分支合并到 master 时,特定模块之外的文件日志可能会变得混乱并且难以知道这些更改来自何处。
You need to decide if the historic of branch′s merge is important to your workflow.
您需要确定分支合并的历史记录对您的工作流程是否重要。
And following the comments, I prefer the rebase
, and pull --rebase
workflow.
根据评论,我更喜欢rebase
, 和pull --rebase
工作流程。