Git014--Rebase
Git--Rebase
本文来自于:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0015266568413773c73cdc8b4ab4f9aa9be10ef3078be3f000
在上一节我们看到了,多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。
每次合并再push后,分支变成了这样:
$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
* e5e69f1 Merge branch 'dev'
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/
* | 12a631b merged bug fix
|\ \
| * | 4c805e2 fix bug
|/ /
* | e1e9c68 merge with no-ff
|\ \
| |/
| * f52c633 add merge
|/
* cf810e4 conflict fixed
总之看上去很乱,有强迫症的童鞋会问:为什么Git的提交历史不能是一条干净的直线?
其实是可以做到的!
Git有一种称为rebase的操作,有人把它翻译成“变基”。
先不要随意展开想象。我们还是从实际问题出发,看看怎么把分叉的提交变成直线。
在和远程分支同步后,我们对hello.py
这个文件做了两次提交。用git log
命令看看:
$ git log --graph --pretty=oneline --abbrev-commit
* 582d922 (HEAD -> master) add author
* add comment
* d1be385 (origin/master) init hello
* e5e69f1 Merge branch 'dev'
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
...
注意到Git用(HEAD -> master)
和(origin/master)
标识出当前分支的HEAD和远程origin的位置分别是582d922 add author
和d1be385 init hello
,本地分支比远程分支快两个提交。
现在我们尝试推送本地分支:
$ git push origin master
To github.com:michaelliao/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
很不幸,失败了,这说明有人先于我们推送了远程分支。按照经验,先pull一下:
$ git pull
remote: Counting objects: , done.
remote: Compressing objects: % (/), done.
remote: Total (delta ), reused (delta ), pack-reused
Unpacking objects: % (/), done.
From github.com:michaelliao/learngit
d1be385..f005ed4 master -> origin/master
* [new tag] v1. -> v1.
Auto-merging hello.py
Merge made by the 'recursive' strategy.
hello.py | +
file changed, insertion(+)
再用git status
看看状态:
$ git status
On branch master
Your branch is ahead of 'origin/master' by commits.
(use "git push" to publish your local commits) nothing to commit, working tree clean
加上刚才合并的提交,现在我们本地分支比远程分支超前3个提交。
用git log
看看:
$ git log --graph --pretty=oneline --abbrev-commit
* e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit
|\
| * f005ed4 (origin/master) set exit=
* | 582d922 add author
* | add comment
|/
* d1be385 init hello
...
对强迫症童鞋来说,现在事情有点不对头,提交历史分叉了。如果现在把本地分支push到远程,有没有问题?
有!
什么问题?
不好看!
有没有解决方法?
有!
这个时候,rebase就派上了用场。我们输入命令git rebase
试试:
$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and -way merge...
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and -way merge...
Auto-merging hello.py
输出了一大堆操作,到底是啥效果?再用git log
看看:
$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=
* d1be385 init hello
...
原本分叉的提交现在变成一条直线了!这种神奇的操作是怎么实现的?其实原理非常简单。我们注意观察,发现Git把我们本地的提交“挪动”了位置,放到了f005ed4 (origin/master) set exit=1
之后,这样,整个提交历史就成了一条直线。rebase操作前后,最终的提交内容是一致的,但是,我们本地的commit修改内容已经变化了,它们的修改不再基于d1be385 init hello
,而是基于f005ed4 (origin/master) set exit=1
,但最后的提交7e61ed4
内容是一致的。
这就是rebase操作的特点:把分叉的提交历史“整理”成一条直线,看上去更直观。缺点是本地的分叉提交已经被修改过了。
最后,通过push操作把本地分支推送到远程:
Mac:~/learngit michael$ git push origin master
Counting objects: , done.
Delta compression using up to threads.
Compressing objects: % (/), done.
Writing objects: % (/), bytes | 576.00 KiB/s, done.
Total (delta ), reused (delta )
remote: Resolving deltas: % (/), completed with local object.
To github.com:michaelliao/learngit.git
f005ed4..7e61ed4 master -> master
再用git log
看看效果:
$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master, origin/master) add author
* 3611cfe add comment
* f005ed4 set exit=
* d1be385 init hello
...
远程分支的提交历史也是一条直线。
小结
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
相关Git学习参考博客:
https://blog.csdn.net/xiaohanluo/article/details/53214933
Git教程,里面有介绍到Git的工作原理,可以仔细阅读。
Git Community Book 中文版介绍了Git具体使用,这本书也是关于Git的一本好书。
Git练习,实战练习Git的各种指令
Git014--Rebase的更多相关文章
- Git 进阶指南(git ssh keys / reset / rebase / alias / tag / submodule )
在掌握了基础的 Git 使用 之后,可能会遇到一些常见的问题.以下是猫哥筛选总结的部分常见问题,分享给各位朋友,掌握了这些问题的中的要点之后,git 进阶也就完成了,它包含以下部分: 如何修改 ori ...
- 利用rebase来压缩多次提交
我们可以用Git merge –squash来将分支中多次提交合并到master后,只保留一次提交历史.但是有些提交到github远程仓库中的commit信息如何合并呢? 历史记录 首先我们查看一下m ...
- git rebase
git rebase -i HEAD~[number_of_commits] git rebase -i HEAD~2
- git 开发merge rebase 记录
git status git lg git add src/ git commit -m "restful api and portal" //先commit到自己的本地branc ...
- git commit之后未submit,rebase之后找不到自己代码的处理方法
今天使用sourceTree提交代码的时候,commit之后未submit,直接rebase主分支代码,完了发现自己本地做的修改都没了,且远程没有本地分支.google之后发现有一个简单方法可以恢复到 ...
- git rebase与 git合并(error: failed to push some refs to)解决方法
1.遇到的问题 本地有一个git仓库,在github上新建了一个空的仓库,但是更新了REWADME.md的信息,即在github上多了一个提交. 关联远程仓库,操作顺序如下: git remote a ...
- 聊下git pull --rebase
有一种场景是经常发生的. 大家都基于develop拉出分支进行并行开发,这里的分支可能是多到数十个.然后彼此在进行自己的逻辑编写,时间可能需要几天或者几周.在这期间你可能需要时不时的需要pull下远程 ...
- 聊下 git rebase -i
在使用git作为源代码管理工具的时候,开发的时经常会面临一个常见的问题,多个commit 需要合并为一个完整的commit提交. 在一个基本的迭代周期里,你会有很多次commit,有跟配置文件相关的, ...
- [译]merge vs rebase
git rebase和git merge设计的初衷是解决相同的一件事, 即把一个分支合并到另外一个分支--只是他们两个处理的方式非常不一样. 当你在一个特定的分支开发新功能, 团队的其它成员在mast ...
- [git]rebase和merge
转自:http://blog.csdn.net/wh_19910525/article/details/7554489 Git merge是用来合并两个分支的. git merge b # 将b分支合 ...
随机推荐
- 七层模型? IP ,TCP/UDP ,HTTP ,RTSP ,FTP 分别在哪层?
IP: 网络层TCP/UDP: 传输层HTTP.RTSP.FTP: 应用层协议
- MIT 6.824学习笔记4 Lab1
现在我们准备做第一个作业Lab1啦 wjk大神也在做6.824,可以参考大神的笔记https://github.com/zzzyyyxxxmmm/MIT6824_Distribute_System P ...
- 自定义django中间件
自定义中间件 第一步:在根目录创建路径Middle/m1.py(注意如果是python2的话Middle下要有__init__.py文件,不然会报找不到模块错误) m1.py的内容: # -*- co ...
- javascript Math取整&获取随机数
1.方法介绍 Math.ceil(n) 上取整,大于等于n返回与它最接近的整数 Math.floor(n) 下取整,小于等于n返回与它最接近的整数 Math.round(n) 四舍五入取整 Math. ...
- 关键字static介绍
static关键字 java中针对多个对象有共同的成员变量值得时候,就提供了static关键字来修饰. (1)静态的意思.可以修饰成员变量和成员方法. (2)静态的特点: A:随着类的加载而加载 B: ...
- [转载]浅谈JavaScript函数重载
原文地址:浅谈JavaScript函数重载 作者:ChessZhang 上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都 ...
- 采用pacemaker+corosync实现postgresql双机热备、高可用方案
环境说明 参照上章已完成postgresql流复制配置,并关闭postgres服务. su - postgres pg_ctl -D /data/postgresql/data/ stop -m fa ...
- Nginx 的总结
目录 Nginx 的产生 Nginx 的用武之地 Web 服务器对比 Nginx 的产生 Nginx 同 Apache 一样都是一种 Web 服务器.基于 REST 架构风格,以统一资源描述符(Uni ...
- c++函数参数或返回值为函数指针
C++中函数指针的形式为:返回值类型 + 参数类型,函数没有值类型,但是却可以声明函数的指针,因为函数是可寻址的,存放在内存中的代码段,可以从指针访问. 函数指针可以声明为: void (*pF)(v ...
- CSP2019初赛训练
[解释执行语言] C,C++,Pascal都是编译执行的语言,Python是解释执行. 扩展:JS.PHP也是解释运行语言.解释性灵活但是效率较低.一些解释性语言也有了也能在一定程度上编译,或者使用虚 ...