“git merge”和“git rebase”有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16666089/
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
What's the difference between 'git merge' and 'git rebase'?
提问by Daniel Pe?alba
What's the difference between git merge
and git rebase
?
git merge
和 和有git rebase
什么区别?
回答by mvp
Suppose originally there were 3 commits, A
,B
,C
:
假设最初有 3 个提交,A
, B
, C
:
Then developer Dan created commit D
, and developer Ed created commit E
:
然后开发人员 Dan 创建了 commit D
,开发人员 Ed 创建了 commit E
:
Obviously, this conflict should be resolved somehow. For this, there are 2 ways:
显然,这种冲突应该以某种方式解决。为此,有两种方法:
MERGE:
合并:
Both commits D
and E
are still here, but we create merge commit M
that inherits changes from both D
and E
. However, this creates diamondshape, which many people find very confusing.
两个提交D
和E
仍然在这里,但我们创建了合并提交M
,它继承了D
和 的更改E
。然而,这会产生菱形,很多人觉得很困惑。
REBASE:
重新定位:
We create commit R
, which actual file content is identical to that of merge commit M
above. But, we get rid of commit E
, like it never existed (denoted by dots - vanishing line). Because of this obliteration, E
should be local to developer Ed and should have never been pushed to any other repository. Advantage of rebase is that diamondshape is avoided, and history stays nice straight line - most developers love that!
我们创建 commit R
,其实际文件内容与M
上面的合并提交相同。但是,我们摆脱了 commit E
,就像它从未存在过一样(用点表示 - 消失线)。由于这种删除,E
对于开发人员 Ed 来说应该是本地的,并且不应该被推送到任何其他存储库。rebase 的优点是避免了菱形形状,并且历史保持良好的直线 - 大多数开发人员都喜欢它!
回答by mvw
I really love this excerpt from 10 Things I hate about git(it gives a short explanation for rebase in its second example):
我真的很喜欢这节我讨厌 git 的 10 件事的摘录(它在第二个示例中简要解释了 rebase):
3. Crappy documentation
The man pages are one almighty “f*** you”1. They describe the commands from the perspective of a computer scientist, not a user. Case in point:
git-push – Update remote refs along with associated objects
Here's a description for humans:
git-push – Upload changes from your local repository into a remote repository
Update, another example: (thanks cgd)
git-rebase – Forward-port local commits to the updated upstream head
Translation:
git-rebase – Sequentially regenerate a series of commits so they can be applied directly to the head node
3.蹩脚的文档
手册页是一个全能的“f *** you” 1。他们从计算机科学家的角度而不是用户的角度描述命令。案例:
git-push – Update remote refs along with associated objects
以下是对人类的描述:
git-push – Upload changes from your local repository into a remote repository
更新,另一个例子:(感谢 cgd)
git-rebase – Forward-port local commits to the updated upstream head
翻译:
git-rebase – Sequentially regenerate a series of commits so they can be applied directly to the head node
And then we have
然后我们有
git-merge - Join two or more development histories together
git-merge - Join two or more development histories together
which is a good description.
这是一个很好的描述。
1. uncensored in the original
1.原版未经
回答by Steve Bennett
Personally I don't find the standard diagramming technique very helpful - the arrows always seem to point the wrong way for me. (They generally point towards the "parent" of each commit, which ends up being backwards in time, which is weird).
就我个人而言,我不认为标准的图表技术很有帮助 - 箭头似乎总是指向错误的方向。(它们通常指向每个提交的“父级”,最终会在时间上倒退,这很奇怪)。
To explain it in words:
用文字来解释:
- When you rebaseyour branch onto their branch, you tell Git to make it look as though you checked out their branch cleanly, then did all your work starting from there. That makes a clean, conceptually simple package of changes that someone can review. You can repeat this process again when there are new changes on their branch, and you will always end up with a clean set of changes "on the tip" of their branch.
- When you mergetheir branch into your branch, you tie the two branch histories together at this point. If you do this again later with more changes, you begin to create an interleaved thread of histories: some of their changes, some of my changes, some of their changes. Some people find this messy or undesirable.
- 当你将你的分支变基到他们的分支上时,你告诉 Git 让它看起来好像你干净地签出了他们的分支,然后从那里开始做你所有的工作。这样就形成了一个干净的、概念上简单的更改包,可供某人查看。当他们的分支上有新的更改时,您可以再次重复此过程,并且您将始终在其分支的“尖端”上得到一组干净的更改。
- 当您将他们的分支合并到您的分支时,此时您将两个分支历史联系在一起。如果您稍后以更多更改再次执行此操作,您就会开始创建一个交错的历史线索:他们的一些更改,我的一些更改,他们的一些更改。有些人觉得这很混乱或不受欢迎。
For reasons I don't understand, GUI tools for Git have never made much of an effort to present merge histories more cleanly, abstracting out the individual merges. So if you want a "clean history", you need to use rebase.
出于我不明白的原因,Git 的 GUI 工具从来没有努力更清晰地呈现合并历史,抽象出单个合并。所以如果你想要一个“干净的历史”,你需要使用 rebase。
I seem to recall having read blog posts from programmers who onlyuse rebase and others that neveruse rebase.
我似乎记得读过那些只使用 rebase 的程序员和其他从不使用 rebase 的程序员的博客文章。
Example
例子
I'll try explaining this with a just-words example. Let's say other people on your project are working on the user interface, and you're writing documentation. Without rebase, your history might look something like:
我将尝试用一个简单的例子来解释这一点。假设您项目中的其他人正在处理用户界面,而您正在编写文档。如果没有 rebase,您的历史记录可能类似于:
Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md
That is, merges and UI commits in the middle of your documentation commits.
也就是说,在文档提交的中间合并和 UI 提交。
If you rebased your code onto master instead of merging it, it would look like this:
如果您将代码重新定位到 master 而不是合并它,它将如下所示:
Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger
All of your commits are at the top (newest), followed by the rest of the master
branch.
您的所有提交都在顶部(最新),然后是master
分支的其余部分。
(Disclaimer: I'm the author of the "10 things I hate about Git" post referred to in another answer)
(免责声明:我是另一个答案中提到的“我讨厌 Git 的 10 件事”帖子的作者)
回答by Frank Nocke
While the accepted and most upvoted answer is great, I additionally find it useful trying to explain the difference only by words:
虽然被接受和最受好评的答案很好,但我也发现尝试仅通过文字来解释差异很有用:
merge
合并
- “okay, we got two differently developed states of our repository. Let's merge them together. Two parents, one resulting child.”
- “好吧,我们的存储库得到了两种不同的发展状态。让我们将它们合并在一起。两个父母,一个孩子。”
rebase
变基
- “Give the changes of the main branch (whatever its name) to my feature branch. Do so by pretending my feature work started later, in fact on the current state of the main branch.”
- “Rewrite the history of my changes to reflect that.” (need to force-push them, because normally versioning is all about nottampering with given history)
- “Likely —if the changes I raked in have little to do with my work— history actually won't change much, if I look at my commits diff by diff (you may also think of ‘patches').“
- “将主分支(不管它的名称)的更改提供给我的功能分支。假装我的功能工作稍后开始,实际上是在主分支的当前状态下进行。”
- “重写我的更改历史以反映这一点。” (需要强制推送它们,因为通常版本控制就是不篡改给定的历史记录)
- “很可能——如果我所做的更改与我的工作几乎没有关系——如果我逐个查看我的提交,历史实际上不会有太大变化(你也可能会想到‘补丁’)。”
summary:When possible, rebase is almost always better. Making re-integration into the main branch easier.
总结:如果可能,rebase 几乎总是更好。使重新集成到主分支更容易。
Because? ? your feature work can be presented as onebig ‘patch file' (aka diff) in respect to the main branch, not having to ‘explain' multiple parents: At least two, coming from one merge, but likely many more, if there were several merges. Unlike merges, multiple rebases do not add up.(another big plus)
因为?? 您的功能工作可以作为一个大的“补丁文件”(又名差异)相对于主分支呈现,而不必“解释”多个父级:至少两个,来自一次合并,但可能更多,如果有几次合并。与合并不同,多个变基不会相加。(另一个大加分)
回答by Willem Franco
Git rebase is closer to a merge. The difference in rebase is:
Git rebase 更接近于合并。rebase 的区别在于:
- the local commits are removed temporally from the branch.
- run the git pull
- insert again all your local commits.
- 本地提交暂时从分支中删除。
- 运行 git pull
- 再次插入所有本地提交。
So that means that all your local commits are moved to the end, after all the remote commits. If you have a merge conflict, you have to solve it too.
所以这意味着在所有远程提交之后,所有本地提交都被移到最后。如果您有合并冲突,您也必须解决它。
回答by Nhan Cao
回答by nagendra547
I found one really interesting article on git rebase vs merge, thought of sharing it here
我发现了一篇关于 git rebase vs merge 的非常有趣的文章,想在这里分享一下
- If you want to see the history completely same as it happened, you should use merge. Merge preserves history whereas rebase rewrites it.
- Merging adds a new commit to your history
- Rebasing is better to streamline a complex history, you are able to change the commit history by interactive rebase.
- 如果你想看到完全相同的历史,你应该使用合并。Merge 保留历史,而 rebase 重写它。
- 合并为您的历史记录添加了新的提交
- Rebase 可以更好地简化复杂的历史记录,您可以通过交互式 rebase 更改提交历史记录。