Git教程十九:分支管理之Rebase
在上一節我們看到了,多人在同一個分支上協作時,很容易出現衝突。即使沒有衝突,後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的操作,有人把它翻譯成“變基”。
先不要隨意展開想象。我們還是從實際問題出發,看看怎麼把分叉的提交變成直線。
在和遠端分支同步後,我們對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,本地分支比遠端分支快兩個提交。
現在我們嘗試推送本地分支:
$ git push origin master
To github.com:michaelliao/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to ' [email protected]: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: 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/learngit
d1be385..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看看狀態:
$ 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
加上剛才合併的提交,現在我們本地分支比遠端分支超前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
...
對強迫症童鞋來說,現在事情有點不對頭,提交歷史分叉了。如果現在把本地分支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
...
原本分叉的提交現在變成一條直線了!這種神奇的操作是怎麼實現的?其實原理非常簡單。我們注意觀察,發現Git把我們本地的提交“挪動”了位置,放到了f005ed4 (origin/master) set exit=1之後,這樣,整個提交歷史就成了一條直線。rebase操作前後,最終的提交內容是一致的,但是,我們本地的commit修改內容已經變化了,它們的修改不再基於d1be385 init hell,而是基於f005ed4 (origin/master) set exit=1,但最後的提交7e61ed4內容是一致的。
這就是rebase操作的特點:把分叉的提交歷史“整理”成一條直線,看上去更直觀。缺點是本地的分叉提交已經被修改過了。
最後,通過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.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=1
* d1be385 init hello
...
遠端分支的提交歷史也是一條直線。
小結
rebase操作可以把本地未push的分叉提交歷史整理成直線;
rebase的目的是使得我們在檢視歷史提交的變化時更容易,因為分叉的提交需要三方對比。
相關推薦
Git教程十九:分支管理之Rebase
在上一節我們看到了,多人在同一個分支上協作時,很容易出現衝突。即使沒有衝突,後push的童鞋不得不先pull,在本地合併,然後才能push成功。 每次合併再push後,分支變成了這樣: $ git log --graph --pretty=oneline
Git安裝教程(三)分支管理之分支管理策略
ive comm 歷史 -a adg txt文件 post graph 刪除 通常,合並分支時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。 如果要強制禁用Fast forward模式,Git就會在merge時生成一個新的co
opencv學習筆記五十九:影象融合之背景替換
以證件照為例,圖片中有大部分為背景,先用kmeans對影象進行分割,可以得到背景的標籤,然後將影象分為前景和背景兩部分,非背景的都當作前景,顯示kmeans分割後的影象dst,將原影象前景賦給dst, 背景都設為0,得到kmeans分割後的影象如下,可看到邊緣處有一些小藍邊,
Eclipse整合Git做團隊開發:分支管理
在日常開發工作中,我們通常使用版本控制軟體管理團隊的原始碼,常用的SVN、Git。與SVN相比,Git有分支的概念,可以從主分支建立開發分支,在開發分支測試沒有問題之後,再合併到主分支上去,從而避免了直接在主分支修改程式碼。 本文介紹如何使用eclipse管理Git分支。
Android實戰技巧之四十九:Usb通訊之USB Host
零 USB背景知識 USB是一種資料通訊方式,也是一種資料匯流排,而且是最複雜的匯流排之一。 硬體上,它是用插頭連線。一邊是公頭(plug),一邊是母頭(receptacle)。例如,PC上的插座就是母頭,USB裝置使用公頭與PC連線。 目前USB硬體介面
Git知識總覽(四) git分支管理之rebase 以及 cherry-pick相關操作
上篇部落格聊了《》,本篇部落格我們主要來看一下 rebase 變基相關的操作。rebase 操作和 merge 操作最終都可以達到合併程式碼的效果,不過其對分支的影響不同。上篇部落格中我們聊到了 merge操作。簡單的說merge操作就是將兩個commit進行合併,然後在這兩個分支合併的基礎上建立一個新的co
Cocos2D-x遊戲開發之十九:瓦塊地圖之碰撞檢測
昨天我們有了精靈和背景,並且精靈可以跑動了,但是我們不能讓精靈無窮無盡地跑下去吧,於是今天我們要在地圖上新增一些障礙物了; 首先開啟精靈的TMX地圖,然後我們自定義一個32X32畫素的圖片新增到圖層中,然後設定此圖層的屬性為:“collidable” 值為“true”,下一
Alink漫談(十九) :原始碼解析 之 分位點離散化Quantile
# Alink漫談(十九) :原始碼解析 之 分位點離散化Quantile [Toc] ## 0x00 摘要 Alink 是阿里巴巴基於實時計算引擎 Flink 研發的新一代機器學習演算法平臺,是業界首個同時支援批式演算法、流式演算法的機器學習平臺。本文將帶領大家來分析Alink中 Quantile 的
轉:【Java並發編程】之十九:並發新特性—Executor框架與線程池(含代碼)
接口類 容易 20px 了解 大小 執行c 生命周期 schedule p s Executor框架簡介 在Java 5之後,並發編程引入了一堆新的啟動、調度和管理線程的API。Executor框架便是Java 5中引入的,其內部使用了線程池機制,它在java.
[Python爬蟲] 之十九:Selenium +phantomjs 利用 pyquery抓取超級TV網數據
images 判斷 nco dex onf etc lac lin 利用 一、介紹 本例子用Selenium +phantomjs爬取超級TV(http://www.chaojitv.com/news/index.html)的資訊信息,輸入給定關鍵字抓取
Git 最佳實踐:分支管理
數據 ken 參考 更新 讓其 vincent 兼容 ucc 足夠 5月份,為統一團隊git分支管理規範,剛開始準備自己寫,在網上搜了下,發現不少不錯的git分支管理實踐。最後我為團隊選擇了這個git分支管理實踐 A successful Git branchi
Git----分支管理之分支管理策略04
font image span 切換 ade chan sim 分支策略 ice 通常,合並分支時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。 如果要強制禁用Fast forward模式,Git就會在merge時生產一個
git操作總結(3):分支管理
1.建立並且切換 git checkout -b testbranch 2.檢視本地當前分支 git branch 3.切換某一分支 git checkout master 4.合併分支 例如:testbranch合併到master 先進入到主分支 gi
skyfans之每天一個Liunx命令系列之十九:usermod
今天我們繼續來學習USER INFORMATION AND MANAGEMENT(使用者資訊和管理),今天學習的是什麼命令呢,那就是usermod(修改使用者帳號) Ready Go!!! usermod --help -c, --comment COMMENT 修改使用者賬
SpringBoot | 第二十八章:監控管理之Spring Boot Admin使用
前言 上一章節,我們介紹了Actuator的使用,知道了可通過訪問不同的端點路徑,獲取相應的監控資訊。但使用後也能發現,返回的監控資料都是以JSON串的形式進行返回的,對於實施或者其他人員來說,不是很直觀,而當需要監控的應用越來越多時,依次去訪問對應的應用也過於繁瑣和低效了。所以,本章節來介紹下Spring
【Visual C++】遊戲開發五十一 淺墨DirectX教程十九 網格模型進階之路
最近幾個星期,不停地收到大家的評論和郵件,大家都說希望淺墨早點講骨骼動畫。本來按淺墨擬定的寫作計劃是把骨骼動畫放到很後面,因為骨骼動畫知識需要前面的網格模型知識為基礎,知識量本身有些大,很可能要佔很多次更新的篇幅。但是看到大家一致的評論,都說非常期待骨骼動畫。那就好吧,我們就來
Java併發程式設計系列之十九:原子操作類
原子操作類簡介 當更新一個變數的時候,多出現資料爭用的時候可能出現所意想不到的情況。這時的一般策略是使用synchronized解決,因為synchronized能夠保證多個執行緒不會同時更新該變數。然而,從jdk 5之後,提供了粒度更細、量級更輕,並且在多核
Android Studio 使用教程(十九)之AndroidStudio怎麼載入並使用okHttp
一、引用okHttp框架 1、點選File-->Project Structure,如圖: 2、點選左側欄的“app”,然後點選頂部導航的“Dependenci
GIT學習筆記(3):分支管理
tree 目錄樹 兩個 基本 使用 ranch ast strong 不同的 GIT學習筆記(3):分支管理 何謂分支 GIT是如何存儲數據的 GIT不是存儲文件差異或者變化量,而是一系列文件的快照。在Git提交時,會保存一個提交(commit)對象,該對象包含一個指向
Mac OS使用技巧十九:Safari碉堡功能之二檢視網頁原始碼
因為大三下的時候選修了搜尋技術,瞭解了網路上搜索引擎和網路爬蟲的資訊扒取的一些東西,後來我們做了一個比較水的東西,就是隻扒取了幾家較大的下載網站幾十個軟體的評分下載量等資訊,當用戶輸入一