1. 程式人生 > >Git教程十九:分支管理之Rebase

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 authord1be385 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碉堡功能二檢視網頁原始碼

     因為大三下的時候選修了搜尋技術,瞭解了網路上搜索引擎和網路爬蟲的資訊扒取的一些東西,後來我們做了一個比較水的東西,就是隻扒取了幾家較大的下載網站幾十個軟體的評分下載量等資訊,當用戶輸入一