理解git結構與簡單操作(四)合并分支的方法與策略

接上節,此時的dev分支與master分支的進度就不一樣了,所以需要將dev分支與master分支同步。這里需要的就是合并分支的操作,大家應該都知道用git merge或者git rebase

git merge

merge,即「合并」。

fast-forward

當出現我們上面圖中的那種情況時,時間線只有一條,dev分支只不過是落后master分支而已。此時我們在dev分支上執行git merge maseter時,git就僅僅會把dev分支指針移動到master分支所在的位置,假裝合并了,就變成了這樣:

這種merge的方式叫做「fast-forward」,也是git默認的merge方式。

如果情況改變了,舉個例子:我們在開發過程中,一直使用的是master分支,這時出了一個很嚴重的bug,我們就需要建立一個叫topic的分支來處理這個bug,但主要的功能工期又不能拖,所以master分支與topic分支就同時向前推進,此時時間線如圖所示:

(此圖出自git自己的幫助文件,使用命令git help merge即可看到。想看其他命令的幫助就git help <command>即可):

這時候,topic上的bug修改完畢,需要合并回master分支,需要的操作為:切換到master分支git checkout master,合并devgit merge dev

注意,這時候的這兩條分支是真正的「分支」了,他們在時間線上岔開了,各自分支都有自己獨有的東西。

因為此時的topic分支的末端并不在master分支的父端,需要把不同的修改同步起來,單純的指針移動不能完成這一步,fast-forward方式也就不可能實現了。

這時,git便會將兩個分支不同的地方取出,合并成一個commit,然后把master指針指向這個新的commit(就是在master上生成了一次commit)。這樣,topic分支上的修改就同步到master分支上了。此時分支情況如圖:

no fast-forward

BTW,能夠進行fast-forward的merge情況下,也可以通過增加--no-ff命令來強制不使用fast-forward模式。假如還是回到我們master-dev兩個分支的例子,master領先于dev分支:

這時我們不用fast-forward,在落后的dev分支上執行git merge master --no-ff,git會在dev上強行創建一個commit,把master分支上不同于dev的修改加進去,分支線就會變成這種詭異的樣子:

(本手殘渣畫圖實在是不好看,就直接用GUI工具source tree上的情況截圖了)

底層上,git會把將要合并的兩個分支的各個commit快照進行差異比較,求出它們之間的最長公共子序列,并把公共子序列從中去掉,得出各自存在兩個分支中的不同修改,并將其合并成一個commit放在當前分支的頂端。

這里僅僅說明一點原理,具體實現方式與算法本人也只是懂一點皮毛,只要明白fast-forward與不使用的情況下merge,分支會產生什么樣的情況,用來工作就沒有任何問題了。

squash

除了--no-ff,merge還有另一種合并的方式:--squash。這種方法在符合fast-forward的情況下依然會執行fast-forward方式,不會有任何改變。但當遇到如下情況時:

假設我們要將topic合并到master上來,squash方式會集中topic的「A、B、C」三次commit中的修改合并,并添加到暫存區中

這時master分支與topic分支不會有任何的變動,只不過暫存區中會被添加topic上修改的集合(暫存區=A+B+C)。

這時我們就可以查看暫存區中的內容是不是符合一次提交,之后commit就可以了。git help merge里是這么描述的:「create a single commit instead of doing a merge」,結合上面的講解就可以理解squash的意思了吧。

git merge 解決沖突

fast-forward中是沒有沖突的(不明白為啥沒沖突的面壁思過)。而在其他情況時,如果兩個分支同時有對同一個文件(行)的修改,就會產生沖突。這時git會在產生沖突的文件里寫一堆這樣的東西:

上面的「<<<<<<<< HEAD」直到「========」的部分,就是當前分支的修改(看到HEAD就知道是指向當前分支的指針了)。而「========」到下面的「>>>>>>> dev」的部分自然就是dev分支合并過來的修改啦。

這時需要你仔細對比沖突,如果跟同事合作的話就要商量好,然后把「<<<<< HEAD ===== >>>>> dev」之類git給你加上的東西和不需要的修改部分刪掉。接下來git status就會看到下面的提示:

上面綠的的東西自然就在暫存區了,這些代表dev分支上并不沖突的部分。下面的紅色文件就代表你沖突的文件,當你修改之后需要走一遍add -> commit的流程(這個commit可以不指定commit message),也可以直接執行git commit -a,就完成merge創建新commit的過程了。

涉及操作:git merge <branch>, git merge <branch> --no-ff, git merge <branch> --squash, git checkout <branch>, git help <command>

git rebase

除了merge,git還有一種分支合并的方式,叫做git rebase。

rebase,就是「re」與「base」結合,官方譯名「變基」(咖喱gaygay? ????)。這個「變基」的含義從字面上確實不是很好理解,先來看一下rebase示例:

回到我們master-dev兩個分支的例子,master領先于dev分支:

這時候我們在dev分支上執行git rebase master,master便與dev合并了,如圖所示:

此時你內心OS:這不是跟fast-forward模式下的merge一樣么?莫急莫急,我們再看一下出現這樣情況下的分支(作者偷懶拿前面圖糊弄了嘿嘿嘿):

不著急解釋原理,我們先看看在topic上執行git rebase master的結果(就是將master合并到topic上):

看圖得知:master上的「F」「G」兩次提交,變成了topic分支的父節點,整個分支又重新合成為一條時間線。在本例中,你可以想象「biu」的一下把topic分支拔下來,然后「pu」的一下把它插到了master的頂端(大霧)。

當然,git肯定不是像上面那樣「biu」「pu」地操作分支的。

git help rebase中是這樣描述git rebase的:

git-rebase - Reapply commits on top of another base tip

翻譯一下,就是「將你的commit們在另一個基準點上重新應用」。注意這里的「reapply」,git并不會直接移動commit本身,而是會為需要rebase的分支上的commit分別創建一個patch「補丁」,然后將patch在基準點上依次應用,重建出一條時間線

可以參照上面的兩張圖梳理一下流程:

當我們在topic分支上執行git rebase master時,代表了我們要將我們當前的分支(topic)應用到指定的master分支上。

此時topic與master的共同父節點是「E」,topic的特有commit是「A」「B」「C」,git就會按照時間點,分別創建「A」「B」「C」的patch「A'」「B'」「C'」,然后將topic分支的基準點設置為master分支的頂點「G」(「變基」了!),依次將「A'」「B'」「C'」Apply到「G」上。

現在是不是理解「rebase變基」是什么意思了!

git rebase 解決沖突

rebase產生的沖突與merge其實是相同的。但由于rebase操作會按照patch一個個打補丁上去,每打一個都有可能會產生沖突,跟merge的產生一個commit這種一次性操作不一樣,解決沖突之后也就不是提交commit,而是git add <file>之后執行git rebase --continue

也就是「打一個補丁,解決一次沖突,然后繼續下一個補丁」的過程。

如果你不耐煩了,也可以git rebase --abort直接不進行rebase了。

涉及操作:git rebase <branch>, git rebase <branch> --onto <commit id>, git rebase --continue, git rebase --abort

關于分支處理策略的選擇

上面講了好多關于分支的東西,可能會讓人困惑:分支涉及到的東西這么多,本身又復雜,多分支處理也復雜,應該怎樣利用分支才好?分支合并的策略選哪一種呢?這里我說一下個人的見解:

首先,git保存的是修改這一點,可以很清楚的讓我們知道代碼發生了哪些改變。在這樣的情況下,我們利用commit時間線就可以明確地區分哪個人在什么時間做了什么事情,也就是給了你「查看歷史」與「修改歷史」的權力,這對一個軟件項目來說是至關重要的。

有關git多個分支的設計,其實是非常巧妙的。多個分支解決了以代碼本身不同版本、不同功能或不同目的的開發方向(比如開發新功能或改bug,又暫時不想修改主要版本)開發時的代碼版本管理問題,能夠很方便地管理工作區的文件內容。

所以,我對多分支系統利用的理解是這樣的:

  • 分支是需要充分利用的。首先要確定一個master分支,作為這個項目最終上線的版本,要保證合并到master分支上的代碼都是確定無誤的、測試通過的。
  • 在開發過程中,可以使用一個development分支來開發,用其部署測試環境,使這個分支成為可以隨意修改的分支,增加開發的靈活度。
  • 在master或者dev分支出現問題,或者要分頭行動時,為每個分支在合適的父節點上創建新的功能分支或bug分支來處理這些問題,可以保證主要的代碼不會出錯,就算是開發出問題,直接刪除該分支便是,基本不用涉及到文件層面的修改。
  • 所以,對工作區的修改應該僅限于增加新內容和修復bug之類的操作,其他的都應該交給git去處理,保證版本樹是一條路,復雜的功能刪除也不用一行一行找。
  • 當某個分支的某些commit出現問題時,可以先將沒有問題的部分建立分支保存起來,保證那些內容不會出問題。

有關git代碼合并策略的選擇,雖然git提供了非常豐富的方法,但一個team使用的方法應該大體固定成同一個,這樣能避免很多混亂,然后在適當的時機使用不同的策略。在《Pro Git》這本書中總結的就很好,我摘下來總結下:

選擇merge還是rebase取決于你對commit歷史時間線的定義。

有兩種觀點:第一種認為,commit歷史應該顯示的是什么時候具體發生了什么事,比如分支的創建與合并過程,有哪些分支,分別合并在了什么地方等等。另一種認為,commit歷史應該顯示的是這個項目經歷過的狀態,而不考慮具體的分支構建過程。

每一個團隊,每一個人都是不同的。git作為一個如此強大的工具提供給了你解決任何問題的思路,你就要考慮清楚你的團隊到底需要什么。

一個兩全其美的方法就是:rebase你本地的修改,push到多人環境中時用merge。

亂糟糟的時間線&&完整的分支結構 vs 清爽的一條線&&舍棄修改過程,看你團隊取舍咯。

文章鏈接

理解git結構與簡單操作(一)git的本質

理解git結構與簡單操作(二)工作區與暫存區

理解git結構與簡單操作(三)認識版本庫與分支

理解git結構與簡單操作(四)合并分支的方法與策略

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255199.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255199.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255199.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HALCON示例程序color_segmentation_pizza.hdev披薩肉餅識別。

HALCON示例程序color_segmentation_pizza.hdev披薩肉餅識別。 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_update_off () dev_close_window () read_image (Image, ‘color/pizza_01’) get_image_size (Image, Width, Height) dev_open_window (0,…

攝像機標定

利用攝像機所拍攝到的圖像來還原空間中的物體。在這里&#xff0c;不妨假設攝像機所拍攝到的圖像與三維空間中的物體之間存在以下一種簡單的線性關系&#xff1a;[像]M[物],這里&#xff0c;矩陣M可以看成是攝像機成像的幾何模型。 M中的參數就是攝像機參數。通常&#xff0c;這…

Linux下Tomcat重新啟動

在Linux系統下&#xff0c;重啟Tomcat使用命令操作的&#xff01; 首先&#xff0c;進入Tomcat下的bin目錄 cd /usr/local/tomcat/bin 使用Tomcat關閉命令 ./shutdown.sh 查看Tomcat是否以關閉 ps -ef|grep java 如果顯示以下相似信息&#xff0c;說明Tomcat還沒有關閉 root …

大數據和人工智能的關系是什么?

何為大數據&#xff1f;何為人工智能&#xff1f; 大數據&#xff0c;百度百科上是這么定義的&#xff0c;指無法在一定時間范圍內用常規軟件工具進行捕捉、管理和處理的數據集合&#xff0c;是需要新處理模式才能具有更強的決策力、洞察發現力和流程優化能力的海量、高增長率…

【2017-03-09】SQL Server 數據庫基礎、四種約束

一、數據庫和內存的區別 數據庫&#xff1a;一些存儲在硬盤上的數據文件 內存&#xff1a;計算機臨時存儲的一些數據 二、常用數據庫 .Net - SQL Server PHP - MySql Java - Oreacl 三、SQL Server使用方法 1、新建數據庫 右鍵點擊“數據庫”&#xff0c;點擊“新建數據庫”。在…

HALCON示例程序color_simple.hdev在HSV空間篩選黃色線

HALCON示例程序color_simple.hdev在HSV空間篩選黃色線 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_close_window () dev_open_window (0, 0, 640, 480, ‘black’, WindowHandle) for i : 1 to 2 by 1 read_image (Image, ‘cable’ i) 將彩色圖片…

張正友標定法 【計算機視覺學習筆記--雙目視覺幾何框架系列】

三、致敬“張正友標定” 此處“張正友標定”又稱“張氏標定”&#xff0c;是指張正友教授于1998年提出的單平面棋盤格的攝像機標定方法。張氏標定法已經作為工具箱或封裝好的函數被廣泛應用。張氏標定的原文為“A Flexible New Technique forCamera Calibration”。此文中所提到…

SQL基礎三

關系數據庫操作語言 對關系數據庫進行操作標準語言是所謂的結構化查詢語言SQL&#xff0c;和其他程序語言不一樣的是&#xff0c;它是非過程語言。 SQL采用自然英語的結構&#xff0c;比較容易上手&#xff0c;目前SQL已經有了ANSI標準&#xff0c;哥哥數據庫廠商除了SQL語法外…

HTTP狀態碼詳解

HTTP狀態碼介紹 createTime--2016年9月24日09:41:48 參考鏈接&#xff1a;http://www.w3school.com.cn/tags/html_ref_httpmessages.asp概括&#xff1a;   1字開頭&#xff1a;消息。信息性狀態碼&#xff0c;代表請求已被接受&#xff0c;需要繼續處理。&#xff08;接受的…

HALCON示例程序connection.hdev分割連通域

HALCON示例程序connection.hdev分割連通域 示例程序源碼&#xff08;加注釋&#xff09; read_image (Image, ‘mreut’) 二值化 threshold (Image, Region, 190, 255)分割連通域 connection (Region, ConnectedRegions)使用面積進行篩選 select_shape (ConnectedRegions, S…

一張圖學習常見this的指向

在寫JS代碼時&#xff0c;this的出場頻率頗高&#xff0c;擔負了傳遞對象&#xff0c;作用域等等功能&#xff0c;堪稱全能超人。 但是this復雜多變&#xff0c;初學的時候想弄清楚并不簡單&#xff0c;繞著繞著就迷路了。“我是誰&#xff1f;我從哪來&#xff1f;我要到哪去&…

HALCON示例程序count_fish_sticks.hdev魚棒完整性檢測

HALCON示例程序count_fish_sticks.hdev魚棒完整性檢測 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_update_off () dev_close_window () read_image (Image, ‘food/fish_stick_package_01’) get_image_size (Image, Width, Height) dev_open_windo…

關于相機標定的問題答復網友

網友snow2012720 我剛開始學習計算機視覺的雙目三維重建內容&#xff0c;感覺好多內容不懂&#xff0c;看到你的博文&#xff0c;了解到你對雙目標定三維重建這些有深入的研究&#xff0c;您是過來人了&#xff0c;能否幫忙給我在學習標定匹配三維重建過程中給予指點&#xff…

轉:ORACLE的JDBC連接方式:OCI和THIN

oracle的jdbc連接方式:oci和thin oci和thin是Oracle提供的兩套Java訪問Oracle數據庫方式。 thin是一種瘦客戶端的連接方式&#xff0c;即采用這種連接方式不需要安裝oracle客戶端,只要求classpath中包含jdbc驅動的jar包就行。thin就是純粹用Java寫的ORACLE數據庫訪問接口。oci是…

軟工網絡15個人閱讀作業2——提問題

提出問題 快速通讀教材《構建之法》&#xff0c;并參照提問模板&#xff0c;提出5個問題。 問題一&#xff1a; p83有一段話&#xff1a; 兩人在一起合作&#xff0c;自然會出現不同意見&#xff0c;每個人都有自己的想法&#xff0c;在兩個人平等合作的情況下&#xff0c;不存…

HALCON示例程序count_pellets.hdev分割豆子,基本形態學的使用

HALCON示例程序count_pellets.hdev分割豆子&#xff0c;基本形態學的使用 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_update_off () read_image (Image, ‘pellets’) dev_close_window () get_image_size (Image, Width, Height) dev_open_window…

絕對路徑VS相對路徑

絕對路徑&#xff1a;不必贅述&#xff0c;就是從盤符開始寫直到找到你所需要的文件為止&#xff0c;把所有的目錄寫完整即可。但是在做網站的時候絕對不推薦用絕對路徑&#xff0c;因為不可能服務器中的路徑和在做設計時候所用的電腦的路徑一致&#xff0c;也不可能說在服務器…

四、極大似然參數估計

四、極大似然參數估計 此篇博文&#xff0c;玉米將和大家分享一下“張氏標定”除幾何推導外的另外一大精髓&#xff1a;參數估計。 張教授在大作“A Flexible New Technique for Camera Calibration”中的原話如下&#xff1a;” The above solution is obtained through minim…

xtrabackup安裝使用

2019獨角獸企業重金招聘Python工程師標準>>> 【MySQL】xtrabackup安裝使用 拾荒者charley 關注 2018.03.19 09:19 字數 186 閱讀 17評論 0喜歡 0 前言&#xff1a;說到MySQL備份&#xff0c;主要采用的方法無非就是mysqldump/mysqldumper以及我們今天要說的熱備利器…

HALCON示例程序crystal.hdev通過局部閾值處理和區域處理提取六角形晶體

HALCON示例程序crystal.hdev通過局部閾值處理和區域處理提取六角形晶體 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_close_window () dev_update_window (‘off’) read_image (Image, ‘crystal’) get_image_size (Image, Width, Height) dev_ope…