git Rebase 变基 教程
在上一節(jié)我們看到了,多人在同一個分支上協(xié)作時,很容易出現(xiàn)沖突。即使沒有沖突,后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 101 |\ \ | * | 4c805e2 fix bug 101 |/ / * | e1e9c68 merge with no-ff |\ \ | |/ | * f52c633 add merge |/ * cf810e4 conflict fixed總之看上去很亂,有強迫癥的童鞋會問:為什么Git的提交歷史不能是一條干凈的直線?
其實是可以做到的!
Git有一種稱為rebase的操作,有人把它翻譯成“變基”。
先不要隨意展開想象。我們還是從實際問題出發(fā),看看怎么把分叉的提交變成直線。
在和遠程分支同步后,我們對hello.py這個文件做了兩次提交。用git log命令看看:
$ git log --graph --pretty=oneline --abbrev-commit * 582d922 (HEAD -> master) add author * 8875536 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,本地分支比遠程分支快兩個提交。
現(xiàn)在我們嘗試推送本地分支:
$ 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.很不幸,失敗了,這說明有人先于我們推送了遠程分支。按照經(jīng)驗,先pull一下:
$ git pull remote: Counting objects: 3, done. remote: Compressing objects: 100% (1/1), done. remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0 Unpacking objects: 100% (3/3), done. From github.com:michaelliao/learngitd1be385..f005ed4 master -> origin/master* [new tag] v1.0 -> v1.0 Auto-merging hello.py Merge made by the 'recursive' strategy.hello.py | 1 +1 file changed, 1 insertion(+)再用git status看看狀態(tài):
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits.(use "git push" to publish your local commits)nothing to commit, working tree clean加上剛才合并的提交,現(xiàn)在我們本地分支比遠程分支超前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=1 * | 582d922 add author * | 8875536 add comment |/ * d1be385 init hello ...對強迫癥童鞋來說,現(xiàn)在事情有點不對頭,提交歷史分叉了。如果現(xiàn)在把本地分支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 3-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 3-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=1 * d1be385 init hello ...原本分叉的提交現(xiàn)在變成一條直線了!這種神奇的操作是怎么實現(xiàn)的?其實原理非常簡單。我們注意觀察,發(fā)現(xiàn)Git把我們本地的提交“挪動”了位置,放到了f005ed4 (origin/master) set exit=1之后,這樣,整個提交歷史就成了一條直線。rebase操作前后,最終的提交內(nèi)容是一致的,但是,我們本地的commit修改內(nèi)容已經(jīng)變化了,它們的修改不再基于d1be385 init hello,而是基于f005ed4 (origin/master) set exit=1,但最后的提交7e61ed4內(nèi)容是一致的。
這就是rebase操作的特點:把分叉的提交歷史“整理”成一條直線,看上去更直觀。缺點是本地的分叉提交已經(jīng)被修改過了。
最后,通過push操作把本地分支推送到遠程:
Mac:~/learngit michael$ git push origin master Counting objects: 6, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done. Total 6 (delta 2), reused 0 (delta 0) remote: Resolving deltas: 100% (2/2), completed with 1 local object. To github.com:michaelliao/learngit.gitf005ed4..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=1 * d1be385 init hello ...遠程分支的提交歷史也是一條直線。
小結
-
rebase操作可以把本地未push的分叉提交歷史整理成直線;
-
rebase的目的是使得我們在查看歷史提交的變化時更容易,因為分叉的提交需要三方對比。
from:?https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0015266568413773c73cdc8b4ab4f9aa9be10ef3078be3f000?
總結
以上是生活随笔為你收集整理的git Rebase 变基 教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用git rebase合并
- 下一篇: git Rebase 代替合并