rebase和git merge rebase的区别

7257人阅读
几乎所有的版本控制工具都有branch功能,branch主要用于以下几个场景:
1,控制产品OEM。
基本上做产品,不同的客户都会提出多种不同特性需求,最简单的例子就是LOGO和标题完全不一样。但是可能产品自身的大部分功能和模块的代码一样的,这个时候如何管理多个客户定制的功能特性,并且不会干扰其他OEM版本的功能呢?
如果你一开始就用if加N多变量定义的话,早晚会累死你,如果你把代码拷贝很多份,每多一个新的OEM就多拷贝一份代码,那如果发现公用模块里面有个BUG,难道你要每个版本的源代码都要修改?万一改错地方了,或者哪个版本的忘记改了,又是一件麻烦事。
这个时候我们就可以考虑使用branch功能,在第一个OEM的基础上分支出第二个OEM,第三个OEM完全取决于和哪个版本更像,就在那个版本的基础上做新的分支,有新的OEM特性需求,就切换到那个分支上修改,放心,所有的的单独分支上的代码看起来都是独立的,不会影响其他版本。
2,多人协作长时间开发功能模块
如果你在一个团队中,那几乎很难做到每天都能按期完成某个模块功能,并且测试通过。那团队成员又必须每日下班前把自己的代码保存一下,万一机器故障了之类的还能有代码备份机制。如果提交了不能工作的代码,别人又获取到了,那其他人的事情就做不下去了。所以,branch另外一个适用场景就是为team单独成员开辟个人工作区域,单元测试无误之后再把成员的工作代码合并到主分支中,既能达到个人代码备份的目的,又能不影响其他人的工作。
其实上面所说的就是rebase和merge的不同适用场景。
在场景1的情况下,如果修改了某个公用代码的BUG,这个时候就应该是把所有的OEM版本分支rebase到这个修复BUG的分支上来,在rebase过程中,Git会要你手动解决代码上的冲突,你需要做的就是把修复BUG的代码放到目标分支代码里面去。rebase的结果是:所有的分支依然存在
在场景2的情况下,因为成员的代码开发工作已经完成了,也不需要再保留这个分支了,所以我们可以把这个成员分支merge到主分支上,当然冲突在所难免,手工解决的工作肯定逃不掉,但是利大于弊不是吗。merge以后,分支就不存在了,但是在Git的所有分支历史中还能看到身影。
根据适用场景不同,采用不同的分支合并策略,让你团队的代码保持生命力吧。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:64807次
排名:千里之外
原创:21篇
评论:11条
(2)(3)(1)(5)(5)(6)1868人阅读
Tool(36)
As you’re no doubt aware, Git and Mercurial are great at re-integrating divergent lines of development through merging. They have to be, since their design strongly encourages developers to commit changes in parallel in their own distributed environments. Eventually
some or all of these commits have to be brought together into a shared graph, and merging and rebasing are two primary ways that let us do that. So which one do you use?
What does Merge or Rebase mean?
Let’s start by defining what merging and rebasing are.
Merging&brings two lines of development together while preserving the ancestry of each commit history.
In contrast,&rebasing&unifies the lines of development by re-writing changes from the source branch so that they appear as children
of the destination branch – effectively pretending that those commits were written on top of the destination branch all along.
Here’s a visual comparison between merging and rebasing a branch ‘feature/awesomestuff’ back to the master branch (click for full size):
So merging keeps the separate lines of development explicitly, while rebasing always ends up with a single linear path of development for both branches. But this rebase requires the commits on the source branch to be&re-written,
which changes their content and their SHAs. This has important ramifications which we’ll talk about below.
[An aside: merging in Git can sometimes result in a special case: the 'fast forward merge'. &This only applies if there are no commits in the
destination branch which aren't already in the source branch. Fast-forward merges create no merge commit and the result looks like a rebase, because the commits just move over to the destination branch - except no history re-writing is needed (we'll talk about
this re-writing in a second). You can turn fast-forward merges off in SourceTree so that a merge commit is always created if you want - check the 'Create a commit' option in the Merge dialog or set it globally in Preferences & Git.]
So, what are the pros and cons of merging and rebasing?
Pros and Cons
Merging Pros
Simple to use and understand.
Maintains the original context of the source branch.
The commits on the source branch remain separate from other branch commits, provided you don’t perform a fast-forward merge. This separation can be useful in the case of feature branches, where you might want to take a feature and merge it into another branch
Existing commits on the source branch are unchan it doesn’t matter if they’ve been shared with others.
Merging Cons
If the need to merge arises simply because multiple people are working on the same branch in parallel, the merges don’t serve any useful historic purpose and create clutter.
Rebase Pros
Simplifies your history.
Is the most intuitive and clutter-free way to combine commits from multiple developers in a shared branch
Rebase Cons
Slightly more complex, especially under conflict conditions. Each commit is rebased in order, and a conflict will interrupt the process of rebasing multiple commits. With a conflict, you have to resolve the conflict in order to continue the rebase. SourceTree
guides you through this process, but it can still become a bit more complicated.
Rewriting of history has ramifications if you’ve previously pushed those commits elsewhere. In Mercurial, you simply cannot push commits that you later intend to rebase, because anyone pulling from the remote will get them. In Git, you may push commits you
may want to rebase later (as a backup) but&only&if it’s to a remote branch that&only&you
use.&If anyone else checks out that branch and you later rebase it, it’s going to get very confusing.
Practical tips
Looking at the above pros/cons, it’s clear that it’s generally not a case of choosing between one or the other, but more a case of using each at the appropriate times.
To explore this further, let’s say you work in a development team with many committers, and that your team uses both shared branches as well as personal feature branches.
Shared branches
With shared branches, several people commit to the same branch, and they find that when pushing, they get an error indicating that someone else has pushed first. In this case, I would always recommend the ‘Pull with rebase’ approach. In other words, you’ll
be pulling down other people’s changes and immediately rebasing your commits on top of these latest changes, allowing you to push the combined result back as a linear history. It’s important to note that your commits must not have been shared with others yet.
In SourceTree, you can do this in the Pull dialog:
You can also set this as the default behavior in your Preferences if you like:
By taking this approach, when developing in parallel on a shared branch, you and your colleagues can still create a linear history, which is much simpler to read than if each member merges whenever some commits are built in parallel.
The only time you shouldn’t rebase and should merge instead is if you’ve shared your outstanding commits already with someone else via another mechanism, e.g. you’ve pushed them to another public repository, or submitted a patch or pull request somewhere.
Feature branches
Now let’s take the case where you deliberately create a separate branch for a feature you’re developing, and for the sake of this example, you are the only person working on that feature branch. This approach is common with&&for example. This feature branch may take a while to complete, and you’ll only want to re-integrate it into other lines of development once you’re done. So how do you manage that? There are actually two separate issues here that we must address.
The final merge:&When building a feature on a separate branch, you’re usually going to want to keep these commits together in order
to illustrate that they are part of a cohesive line of development. Retaining this context allows you to identify the feature development easily, and potentially use it as a unit later, such as merging it again into a different branch, submitting it as a pull
request to a different repository, and so on. Therefore, you’re going to want to merge rather than rebase when you complete your final re-integration, since merging gives you a single defined integration point for that feature branch and allows easy identification
of the commits that it comprised.
Keeping the feature branch up to date:&While you’re developing your feature branch, you may want to periodically keep it in sync with
the branch which it will eventually be merged back into. For example, you may want to test that your new feature remains compatible with the evolving codebase well before you perform that final merge. There are two ways you can bring your feature branch up
Periodically merge from the (future) destination branch into your feature branch. This approach used to cause headaches in old systems like Subversion, but actually works fine in Git and Mercurial.
Periodically rebase your feature branch onto the current state of the destination branch
The pros and cons of each are generally similar to those for merging and rebasing. Rebasing keeps things tidier, making your feature branch appear quite compact. If you use the merge approach instead, it means that your feature branch will always branch off
from its original base commit, which might have happened quite a long time ago. If your entire team did this and there’s a lot of activity, your commit history would contain a lot of parallel feature branches over a long period of time. Rebasing continually
compacts each feature branch into a smaller space by moving its base commit to more recent history, cleaning up your commit graph.
The downside of rebasing your feature branches in order to keep them up to date is that this approach rewrites history. If you never push these branches outside your development machine, this is no problem. But assuming that you do want to push them somewhere,
say for backup or just visibility, then rebasing can cause issues. On Mercurial, it’s always a bad idea – you should never push branches you intend to rebase later. With git, you have a bit more flexibility. For example, you could push your feature branches
to a different remote to keep them separate from the rest, or you could push your feature branches to your usual remote, as your development team is aware that these feature branches will likely be rewritten so they should not check them out from this remote.
Conclusion
The consensus that I come across most frequently is that both merge and rebase are worth using. The time to use either is entirely dependent on the situation, the experience of your team, and the specific DVCS you’re using.
When multiple developers work on a shared branch, pull & rebase your outgoing commits to keep history cleaner (Git and Mercurial)
To re-integrate a completed feature branch, use merge (and opt-out of fast-forward commits in Git)
To bring a feature branch up to date with its base branch:
Prefer rebasing your feature branch onto the latest base branch if:
You haven’t pushed this branch anywhere yet, or
You’re using Git, and you know for sure that other people will not have checked out your feature branch
Otherwise, merge the latest base changes into your feature branch
I hope this helps! Please let me know in the comments if you have any questions or suggestions.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:783497次
积分:10198
积分:10198
排名:第1102名
原创:240篇
转载:339篇
评论:63条
(5)(3)(1)(1)(3)(1)(13)(23)(5)(2)(6)(10)(9)(4)(13)(1)(1)(1)(7)(16)(4)(1)(23)(32)(23)(22)(11)(6)(23)(13)(7)(14)(2)(7)(5)(15)(14)(15)(9)(9)(8)(10)(21)(23)(11)(21)(32)(19)(14)(3)(1)(6)(8)(6)(1)(4)(5)(2)(6)(12)(10)(1)(2)对于解决 Git 的 Merge Conflict 你有哪些经验和技巧?
子问题:有哪些不错的 merge tool ?
贴一个在公司写的wiki page,
meld 很好用。Configuration
meld is a useful
three-way-compare merge tool. you can use it in Git.
(install meld)
git config --global merge.
(set Git merge tool default as meld)
When you merge a branch in Git, it may get into conflict state, if you need to go on, you need fix these conflict, but if you need to go back to the state before merge, you can you use
git reset -- (get me back)
If you want to fix the conflicts, use
这样的问题我们就看看stackoverflow上都是怎么回答的好了,正好最近也遇到类似的问题。这个是关注和赞同最高的帖子:排名第一的答案是用 git mergetool. 还有这两个隐藏的很深的参数:git checkout --ours file 和 git checkout --theirs file。子问题关于mergetool的推荐:答案里已经有人说到用meld了。个人感觉kdiff3也不错,3-way merge的GUI工具。窗口的布局大概就是:还算简单明了,上方依次是base,local和remote三个版本的代码,下面是解决冲突后的代码,直接在下方冲突处来选择使用哪个版本。这里有篇关于kdiff3和meld的介绍:
(测了下国内好像可以访问)另外有些是在没法用工具解决的conflict只能手动改改了。最后附上:kdiff3的主页:meld的主页:
这些git的用法,用多了就好了。我刚开始也是这样的。首先在pull的时候加上rebase,解决conflict,最后pushgit pull --rebase origin remoteif there is conflict, clean it and execute the following commandgit add . git rebase --continueif all be donegit push origin remote每次都用这种方式,就不会有错了。如果直接用merge命令也一样,记住要rebase就对了。如git merge feature-1234first pull master code. -& git pull --rebase origin remoteif conflict, clean it , then -& git add .; git rebase --continuecheckout to feature being merged to master branch -& git checkout feature-1234merge it to master branch -& git merge feature-1234push to master -& git push origin remote有多个conflict,也可用下面的命令git rebase --continuegit mergetoolgit rebase --continuegit mergetool
tortoisegit+beyondcompair,tortois的冲突文件列表窗口极度方便,一目了然,比在命令行下方便一万倍,至于BC,最好用的3路merge工具,没有之一,没有它简直没法用git。我一直停留在windows上的唯一理由就是其他平台上没有这么方便的git工具
至少自己写的代码逻辑自己是清楚的备份自己的代码,还原冲突文件至最新。再将自己的代码逻辑尝试添加回去。
我的经验:在特性分支上开发的过程中就要经常与主干分支进行rebase,能让你最后在合并代码的时候轻松很多。都知道集成是个很痛苦的事,各种冲突。与其把它放到最后让人痛苦,不如平时就抽出一些时间来解决这些问题。我习惯2~3天就和主干分支进行一次rebase,这个时候即使有冲突也是很好解决的。在分支开发完毕的时候进行最后一次rebase,然后在进行merge的时候不会有任何冲突了。
我的经验是使用rebase。具体操作1.git add &FILE&
2.git commit ...
3.git pull --rebase (将你的版本加在最后的节点上)
如果有冲突,会提示你。冲突分为两种,一种是在不同地方的冲突,通常情况下,git是可以自己合并的。另外一种是因为可能是同一个文件的编辑,git没法自动合并,需要二选一,这时候打开冲突的文件,手动编辑文件到可用的版本。然后。。4.git rebase --continue
重复3,4直到所有的都solve5.git push
上传到remote,搞定!
Tower + diffMerge
Vim + fugitive.
man git-rerere
已有帐号?
无法登录?
社交帐号登录两个使用场景是不一样的,merge只是合并另外一个分支的内容,rebase也合并另外一个分支的内容,但是会把本分支的commits顶到最顶端假设我们现在有3个分支master分支:线上环境使用的分支testing分支:测试环境使用的分支my_feature分支:开发新功能的分支,也就是当前分支A. 假设我在my_feature上开发了一段时间,之后另外的同事开发的功能正式上线到master分支了,那么我可以在当前的分支下rebase一下master分支,这样我这个分支的几个commits相对于master还是处于最顶端的,也就是说rebase主要用来跟上游同步,同时把自己的修改顶到最上面B. 我在my_feature上开发了一段时间了,想要放到testing分支上,那就切到testing,然后merge my_feature进来,因为是个测试分支,commits的顺序无所谓,也就没必要用rebase (当然你也可以用rebase)另外,单独使用rebase,还有调整当前分支上commits的功能(合并,丢弃,修改commites msg)
哈哈哈,想起来以前给 WebIDE 写的一个推广。内含 WebIDE 的轻微广告。当时 WebIDE 上线了 Merge、Stash、Rebase、Reset 和 Tag 几个功能。这篇文章介绍了这个功能的使用方式。(啊啊啊,公众号复制过来的图片清晰度好差,找了一下发现原图删了T-T)&br&原文如下:&br&&br&&blockquote&&p&CODING 的 WebIDE 上了不少新功能。你和同事激动的讨论着。隔壁产品小妹十分好奇,问你:&strong&『你们都在说的变基、Merge 都是做什么的?』&/strong&&br&你想了想,这么解释给她听:&/p&&br&&strong&Merge 合并与冲突&br&&/strong&&br&&p&『你和你的男朋友生活非常幸福』你说:『两个人一起为共同生活而努力,我们来假设家庭生活是你们两个人的主线,每天工作、休息、吃爱吃的食物,做爱做的事情,像这样』&/p&&br&&img src=&/38017ac43fbc937fdbdc77c8_b.png& data-rawwidth=&885& data-rawheight=&263& class=&origin_image zh-lightbox-thumb& width=&885& data-original=&/38017ac43fbc937fdbdc77c8_r.png&&&br&&p&『而分支就是偶尔他和朋友看个球,你和闺蜜逛个街。主线之外,你们还有各自的支线任务。但是完成支线任务之后,你们两个还是可以去一起看个电影啊,像这样支线任务完成回到了主线任务,并且可能你去逛了街穿了美美的衣服,有了一次很棒的约会,支线任务也是为主线添砖加瓦的。』&/p&&br&&img src=&/31a54ada700c486dadb841_b.png& data-rawwidth=&632& data-rawheight=&193& class=&origin_image zh-lightbox-thumb& width=&632& data-original=&/31a54ada700c486dadb841_r.png&&&br&&p&&strong&『那你们平常说的冲突呢?』&/strong&&/p&&p&『冲突是这样的。比如今天他下班去踢球,说好今晚约会,结果他一身臭汗的回来。你会不会不开心?』&br&&strong&『生气啊,他都记不得今晚有约会。』&/strong&&/p&&p&『恩,这个时候冲突就产生了,冲突产生的时候,他的支线任务就很难合并到主线任务中。在我们使用 WebIDE 的时候,合并的时候会提示你「发现冲突」,并且弹出冲突列表,再进行逐行处理,协调主线任务和支线任务。比如他早点回来洗澡,你花点时间补妆。』&/p&&p&&strong&『啊啊啊,这挺好,省的男朋友老问我为什么生气。笨死了。』&/strong&&/p&&p&『然后我们再来说说储藏。』&/p&&br&&strong&Stash 储藏&br&&/strong&&br&&p&&strong&『储藏的话,是不是说工作做到一半,要存着接着做?』&/strong&&/p&&p&『某种程度上说是的,你做到一半要有其他事情的时候,就需要把这件事情存起来。比如男朋友要送你一个手工的礼物,像这样可爱的龙猫』&/p&&br&&img src=&/757d21dade4221afdf8bf241db61f4c9_b.png& data-rawwidth=&886& data-rawheight=&345& class=&origin_image zh-lightbox-thumb& width=&886& data-original=&/757d21dade4221afdf8bf241db61f4c9_r.png&&&br&&p&&strong&『哇,好萌。』&/strong&&/p&&p&『对的,但是又有了别的工作,可是他做到一半的时候可能是这样的,所以不想让你看到,不能放家里只能放在办公室。就把现在的工作存储下来。并不提交到主线任务。而且可以顺利恢复上次的进度。』&/p&&br&&img src=&/c1d5ab99150_b.png& data-rawwidth=&802& data-rawheight=&373& class=&origin_image zh-lightbox-thumb& width=&802& data-original=&/c1d5ab99150_r.png&&&br&&p&&strong&『这么说就很好理解了,那你快告诉我变基是什么啊。是不是男朋友跟别的男孩子跑了。』&/strong&&/p&&p&『额,怎么会,你男朋友又不是程序员……』&/p&&br&&strong&Rebase 变基&br&&/strong&&br&&p&『变基的基其实是基础的意思,简单来说就是把支线任务变成主线任务。』&/p&&p&&strong&『哎?听起来和 Merge 有点像啊。』&/strong&&/p&&p&『是的,目的上都是把分支任务整合到主线任务上,但是还是有一些区别的,画个图你就了解了,第一张图是 Merge。』&br&&/p&&br&&img src=&/120f71e3e31aa1b9857d79_b.png& data-rawwidth=&946& data-rawheight=&345& class=&origin_image zh-lightbox-thumb& width=&946& data-original=&/120f71e3e31aa1b9857d79_r.png&&&br&&br&&p&『第二张图是 Rebase,他会对比主线「工作」之后两个支线分支 A「追番」和 B「烧饭」的相似与不同,将不同之处「炉子上要炖汤」提取出来作为 B1,然后把「A+B1」即「追番(一起)」和「炖汤 ing」放在主线任务里。』&/p&&br&&img src=&/1b0d5ef5751_b.png& data-rawwidth=&918& data-rawheight=&276& class=&origin_image zh-lightbox-thumb& width=&918& data-original=&/1b0d5ef5751_r.png&&&br&&strong&『哦?看起来变基是个好功能呢。』&/strong&&p&『是的, Merge 的线路更加流畅整洁,特别是支线任务复杂的时候。』&/p&&br&&strong&Reset 重置&br&&/strong&&br&&p&『重置就是你和男朋友吵架了,他特别想用的功能……』&/p&&p&&strong&『就是返回到不生气的状态是吗?』&/strong&&/p&&p&『是的是的。』&/p&&br&&img src=&/fca28ec5bb2cc_b.png& data-rawwidth=&938& data-rawheight=&372& class=&origin_image zh-lightbox-thumb& width=&938& data-original=&/fca28ec5bb2cc_r.png&&&br&&strong&Tag 标签&/strong&&br&&p&&strong&『这就是给任务改名字吗?』&/strong&&br&『是的,常常会把任务改成更有意义的名字,比如这样。』&/p&&br&&img src=&/1c13074cdde853a29eef2a8e7a2bd232_b.png& data-rawwidth=&806& data-rawheight=&426& class=&origin_image zh-lightbox-thumb& width=&806& data-original=&/1c13074cdde853a29eef2a8e7a2bd232_r.png&&&br&&p&所以你不想了解一下怎么在 WebIDE 里使用这些功能吗?&/p&&p&点击了解:&a href=&///?target=http%3A//mp./s%3F__biz%3DMzA3ODUxMjMyMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D0e60ecb1def%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Coding WebIDE 增加 Git 五大高级特性&i class=&icon-external&&&/i&&/a&&br&&/p&&p&当然欢迎直接体验:&a href=&///?target=http%3A//ide.coding.net& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&ide.coding.net&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&/blockquote&&br&原文:&a href=&///?target=http%3A//mp./s%3F__biz%3DMzA3ODUxMjMyMw%3D%3D%26mid%3D%26idx%3D1%26sn%3D091ab93c0e15f02c7d8d45cf634a8820%23rd& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何和产品妹子解释什么是变基&i class=&icon-external&&&/i&&/a&
哈哈哈,想起来以前给 WebIDE 写的一个推广。内含 WebIDE 的轻微广告。当时 WebIDE 上线了 Merge、Stash、Rebase、Reset 和 Tag 几个功能。这篇文章介绍了这个功能的使用方式。(啊啊啊,公众号复制过来的图片清晰度好差,找了一下发现原图删了T-T) 原文如…
&b&rebase&/b&,合并的结果好看,一条线,但合并过程中出现冲突的话,比较麻烦(rebase过程中,一个commit出现冲突,下一个commit也极有可能出现冲突,一次rebase可能要解决多次冲突);&br&&b&merge&/b&,合并结果不好看,一堆线交错,但合并有冲突的话,只要解一次就行了;&br&所以我都是先rebase,如果有冲突,git rebase --abort,再换用merge~~
rebase,合并的结果好看,一条线,但合并过程中出现冲突的话,比较麻烦(rebase过程中,一个commit出现冲突,下一个commit也极有可能出现冲突,一次rebase可能要解决多次冲突); merge,合并结果不好看,一堆线交错,但合并有冲突的话,只要解一次就行了;…
已有帐号?
无法登录?
社交帐号登录
也是个傻逼}

我要回帖

更多关于 git merge rebase 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信