git 詳解及實用指南之三(分支管理)

1. git 詳解及實用指南之一 (本地操做)java

2. git 詳解及實用指南之二 (遠程操做)git

1.建立與合併分支

利用分支就能夠實現多人開發的偉大模式,從而提升生產效率。在整個 GIT 之中,主分支(master)主要是做爲程序 的發佈使用,通常而言不多會在主分支上進行代碼的開發,都會在各自的子分支上進行。github

1)mastr 分支segmentfault

默認狀況下,mastr是一條線,git 利用 master 指向最新的提交,再用 "HEAD" 批向 "master",就能肯定當前分支以及當前分支的提交點。服務器

clipboard.png

以上操做屬於項目發佈版本的執行順序,由於最終發佈就是 master 分支。可是對於其它的開發者,不該該應該在mastr 分支上進行。因此應該創建分支,而子分支最起碼創建的時候應該是當前的 master 分支的狀態。而分支的一但建立以後, HEAD 指針就會發生變化。app

2)分支提交 學習

若是有新的提交,則 master 分支不會改變,只有 brh 分支會發生變化。測試

clipboard.png

那麼此時 master 分支的版本號就落後於子分支了。可是無論子分支再怎麼開發,也不是最新發布版本,全部的發佈版本都保存在 master 分支上,那麼就必須將分支與 master 的分支進行合併。fetch

3)分支提交 url

若是有新的提交,剛 master 分支不會改變,只有 bth 分支會發生改變。

clipboard.png

當分支合併以後,實際上就至關於 master 的分支的提交點修改成子分支的提交點,然後這個合併應該在 master 分支上完成,然後 HEAD 須要修改指針,斷開 brh 分支,而指向本來的 master 分支。

4)刪除子分支

若是有新的提交,剛 master 分支不會改變,只有 brh 分支會發生改變。

clipboard.png

分支刪除掉以後全部的內容也就都取消了。

5)建立一個分支

git branch brh

6)當分支建立完成以後能夠經過以下命令進行察看

git branch

clipboard.png

能夠發現如今提示當前工做區中有兩個分支:一個是 brh 分支,另一個是 master 分支,而如今的分支指向的 是 master 分支。

7)切換到brh分支

git checkout brh

clipboard.png

可是不少時候咱們建立分支的最終目的就是爲了切換到此分支上進行開發,因此爲了方便操做,在 git 之中提供了一 個更加簡單的功能。

建立並切換分支

若是想要刪除子分支,那麼不能在當前分支上,因此切換回了 master 分支

git checkgout master

刪除子分支

git branch -d brh

創建分支的同時能夠自動的切換到子分支

git checkout -b brh

8)切換到brh分支

如今已經成功的在brh分支上了,那麼下面進行代碼的修改;

修改 hello.js

btn.onclick = function() {
   console.log('git 分支管理練習!');
}

這個時候的 Hello.java 文件是屬於子分支上的,而如今也在子分支上,那麼下面查詢一會兒分支的狀態。

clipboard.png

此時更新的是子分支的內容,可是主分支上的數據呢?

9)在子分支上將修改進行提交

git commit -a -m "modified hello.js file"

當子分支的數據提交以後實際上並不會去修改 master 分支的內容。這就證實了,兩個分支上的內容是彼此獨立的。

10)麼既然分支都已經存在了,那麼如今爲了更加清楚,將master和brh兩個分支都提交到遠程服務器上(GITHUB)

git remote set-url origin https://github.com/yootk/mldn.git 
git push origin master
git push origin brh

11)最終發佈的版本必定是在master分支上,因此下面須要將brh分支與master分支進行合併(在主分支上)

git merge brh

clipboard.png

在以前講解的時候說過其實是修改了 master 指針爲 brh 分支的指針信息。因此此時的合併方式爲「Fast-forward」,表示是快速合併方式,快速的合併方式並不會產生任何的 commit id。 它只是利用了合併子分支的 commit id 繼續操做。

12)此時的brh分支沒有任何的用處了,那麼就能夠執行刪除操做

git branch -d brh

13)提交 master 分支

git push origin master

如今在本地上已經沒有了子分支,可是在遠程服務器上依然會存在子分支。那麼下面要刪除遠程分支。

14)刪除遠程分支

git push origin --delete brh

那麼此時遠程分支就已經被成功的刪除掉了。

2.分支的操做管理

上面演示了分支的各個操做,包括使用分支、以及合併分支,同時也清楚了對於分支有兩種方式一種 是本地分支,另一種是遠程分支,可是對於分支在 GIT 使用之中依然會有一些小小的問題,因此下面進行集中式的說明:

1)爲了方便仍是創建一個新的分支 —— brh

git checkout -b brh

2)在此分支上創建一些文件

public class HelloWorld() {
  console.log('Hello World');
}
git add .
    git commit -a -m "Add Emp.java File"

以上的代碼是在子分支(brh)上創建的。

3)此時並無進行分支數據的提交,可是有人以爲這個brh分支名稱很差,應該使用本身的姓名簡寫完成「wzy」

git branch -m brh wzy

如今至關於分支名稱進行了從新的命名。

4)將分支推送到遠程服務器端

git push origin wzy

5)在本地察看遠程的分支

// 察看所有的分支,包括遠程和本地的分支
git branch -a 

// 只察看遠程的分支
git branch -r

// 只察看本地分支
git branch -l

6)此時「wzt」分支上已經作出了修改,可是並無與master分支進行合併,由於如今所開發的功能開發到一半發現再也不須要了,因此就要廢除掉所做出的修改。因而發出了刪除 wzy 分支的命令

git branch -d wzy

clipboard.png

此時直接提示,分支並不可以被刪除掉,由於這個分支所作出的修改尚未進行合併。若是要想強制刪除此分支, 則可使用「-D」的參數完成。

clipboard.png

但是如今在遠程服務器上依然會存在此分支,那麼就必須也一塊兒刪除掉,可是對於刪除操做,除了以前使用過的方 式以外,也能夠推送一個空的分支,這樣也表示刪除。

刪除方式一

git push origin --delete wzy

刪除方式二

git push origin :wzy

3.衝突解決

分支能夠很好的實現多人開發的互操做,可是有可能出現這樣種狀況:

  • 如今創建了一個新的分支 brh,而且有一位開發者在此分支上修改了 hello.js 文件。
  • 可是這個開發者因爲不當心的失誤,又將分支切換回了 master 分支上,而且在 master 分支上也對 hello.js文件進行修改。

等於如今有兩個分支對同一個文件進行了修改,那麼在進行提交的時候必定會出現一個衝突。由於系統不知道到底 提交那一個分支的文件。

master 和 brh 兩個分支上都有各自的信息提交,那麼此時就造成了衝突:

clipboard.png

那麼很明顯,此時有兩個提交點,那麼會出現怎樣的衝突警告呢?爲了更好的說明問題,下面經過代碼進行驗證:

1)創建並切換到 brh 分支上

git checkout -b brh

2)在此分支上修改hello.js文件

btn.onclick = function() {
   console.log('git 分支管理練習!');
   console.log('git 分支衝突練習!')
}

3)在brh分支上提交此文件

git commit -a -m "add static attribute"

4)切換回 master 分支

git checkout master

5)在 master 分支上也修改 Hello.js 文件

btn.onclick = function() {
   console.log('git 分支管理練習!');
   console.log('git Mast 分支修改測試! ')
}

6)在master分支上進行修改的提交

git commit -a -m "add master change file"

如今在兩個分支上都存在了代碼的修改,並且很明顯,修改的是同一個文件,那麼天然進行分支合併的時候是沒法 合併的。

7)合併分支(此時已經存在於master分支上)

git merge brh

clipboard.png

此時會直接提示出現了衝突。

8)察看衝突的內容

clipboard.png

直接提示用戶,兩次修改了 Hello.java 文件。

9) 察看 Hello.js 文件

btn.onclick = function() {
   console.log('git 分支管理練習!');
<<<<<<< HEAD
   console.log('git Mast 分支修改測試! ')
=======
   console.log('git 分支衝突練習!')
>>>>>>> brh
}

它如今把衝突的代碼進行了標記,那麼如今就必須人爲手工修改發生衝突的文件。

10)手工修改 Hello.js 文件

btn.onclick = function() {
   console.log('git 分支管理練習!');
   console.log('git Mast 分支修改測試! ')
   console.log('git 分支衝突練習!')
}

如今是但願這幾個輸出的內容都同時進行保留。

11)此時已經手工解決了衝突,然後繼續進行提交

git commit -a -m "conflict print"

那麼如今的衝突問題就解決了。

12)向服務器端提交信息

git push origin master

那麼在實際的開發之中,必定會存在有許多的分支合併的狀況,那麼我怎麼知道分支合併的歷史呢?

13) 察看合併的狀況

git log --graph --pretty=oneline

clipboard.png

「-graph」指的是採用繪圖的方式進行現實。

14) 刪除掉 brh 分支

git branch -d brh

那麼此時的代碼就能夠迴歸正常的開發模式。

4.分支管理策略

在以前進行分支合併的時候使用的所有都是「Fast forward」方式完成的,而此種方式只是改變了master指針,但是 在分支的時候也能夠不使用這種快合併,即:增長上一個「--no-ff」參數,這樣就表示在合併以後會自動的再生成一個新 的 commit id,從而保證合併數據的完整性。

"-no-ff": 合併後動建立一個新的 commit

clipboard.png

1)建立一個新的分支

git checkout -b brh

2)創建一個新的 empty.js 文件

public class Empty() {
  console.log('empty file');
}

3) 提交修改

git add.
git commit -m "add empty.js file"

4) 切換回master分支

git checkout master

5) 使用非快速合併的方式進行代碼合併

git merge --no-ff -m "no ff commit" brh

「--no-ff」方式會帶有一個新的提交,因此須要爲提交設置一個提交的註釋。

6) 察看一下提交的日誌信息

git log --graph --pretty=oneline --abbrev-commit

clipboard.png

分支策略

  • master 分支應該是很是穩定的,也就是僅用來發布新的版本,不要在此分支上開發;
  • 在各個子分支上進行開發工做;
  • 團隊中的每一個成員都在各個分支上工做;

clipboard.png

5.分支暫存

譬如說同在你正在一個分支上進行代碼的開發,可是忽然你的領導給了你一個新的任務,而且告訴你在半個小時內 完成,那麼怎麼辦?

難道那開發一半的分支要提交嗎?不可能的,由於對於版本控制的基本的道德方式:你不能把有問題的代碼提交上 去,你所提交的代碼必定都是正確的代碼,那麼爲了這樣的問題,在 GIT 中提供了一個分支暫存的機制,能夠將開發一半 的分支進行保存,然後在適當的時候進行代碼的恢復。

那麼下面首先建立一個基本的開發場景。

1)建立並切換到一個新的分支

git checkout -b brh

2)下面在分支上編寫empty.js 類的文件

public class Empty() {
  console.log('empty file');
  console.log('我正在開發一半中。。。。。。')
}

3)將此文件保存在暫存區之中

git add .

這個時候因爲代碼尚未開發完成,因此不可以進行代碼的提交。可是你的老闆給了你一個新的任務,那麼你就不得不去中止當前的開發任務,因此就須要將當前的開發進度進行「暫存」,等往後有時間了繼續進行恢復開發。

4)將工做暫存

git stash

clipboard.png

5)察看一下當前的工做區中的內容

clipboard.png

此處會直接告訴用戶當前的工做區之中沒有任何的修改。

6)察看一下當前的工做區中的內容

然後如今假設要修改的代碼還處於master分支上,因此下面切換到master分支。

那麼如今假設說建立一個新的分支,用於完成老闆的需求,假設分支的名稱爲「dev」(也有多是一個 bug 調試)。

7)建立並切換分支

git checkout -b dev

8) 在新的分支中修改Hello.js文件

btn.onclick = function() {
   console.log('git 分支管理練習!');
   console.log('git Mast 分支修改測試! ')
   console.log('git 分支衝突練習!')
   console.log('臨時任務 dev 上的修改')
}

9) 提交修改的操做

git commit -a -m "dev change"

10) 提交修改的操做

合併 deve 分支,使用 no fast forward

git merge --no-ff-m "merge dev branch" dev

11) 那麼如今突發的問題已經被解決了,被解決以後對於 dev 的分支將沒有任何的存在乎義,能夠直接刪除;

git branch -d dev

12) 那麼須要迴歸到已有的工做狀態,可是有可能會存在有許多的暫存的狀態,能夠直接使用以下命令進行列出。

git stash list

clipboard.png

13)從暫存區之中進行恢復

暫存區恢復以後那麼所暫停的操做將沒有存在的意義,可是也有人會認爲它有意義,因此對於恢復有兩種形式:

形式一:先恢復,然後再手工刪除暫存

git stash apply
git stash drop

形式二:恢復的同時也將 stash 內容刪除

git stash pop

clipboard.png

那麼下面的任務就能夠像以前那樣進行代碼的提交,然後刪除掉 brh 分支:

git commit -a -m "change empty.js"
git branch -d brh

使用暫存策略能夠很方便的解決代碼忽然暫停修改的操做,是很是方便。

6.補丁: patch

補丁並非針對於全部代碼的修改,只是針對於局部的修改。在不少的代碼維護之中,若是按照最先克隆的方式將 代碼總體克隆下來實際上所花費的資源是很是龐大的,可是修改的時候可能只修改很小的一部分代碼,因此在這種狀況下 就但願能夠將一些代碼的補丁信息發送給開發者。而發給開發者以後他須要知道那些代碼被修改了,這樣的話就可使用 一個極低的開銷實現代碼的修改操做,而在 GIT 之中也提供了兩種簡單的補丁方案:

  • 使用 git diff 生成標準的 patch
  • 使用 git format-patch 聲稱 git 專用的 patch

1) 利用 git diff 生成標準的 patch

當前的empty.js文件

public class Empty() {
  console.log('empty file');
  console.log('我正在開發一半中。。。。。。')
}

2) 創建一個新的分支 —— cbrh

git checkout -b cbrh

3) 修改 empty.js文件

public class Empty() {
  console.log('empty file');
  console.log('我正在開發一半中。。。。。。')

  console.log('補丁修改1');
  console.log('補丁修改2');
}

4) 然後察看先後代碼的不一樣

git diff empth.js

clipboard.png

此時能夠發現 Emp.java 文件修改先後的對比狀況。

5) 在cbrh上進行代碼的提交

git commit -a -m "add 2 line empty.js "

此時並無和主分支進行提交,可是代碼已經改變了,須要的是將代碼的變化提交給開發者。

6) 生成補丁文件 —— mypatch

git diff master > mypatch

7)切換回master分支

此時會自動在項目目錄中生成一個 mypat 的補丁文件信息。這個文件是能夠由 git 讀懂的信息文件,那麼完成以後如今須要模擬另一個開發者,另一個開發者假設是專門進行補丁合併的開發者。

8)建立並切換一個新的分支

git checkout -b patchbrh

9)應用補丁信息

git apply mypatch

此時補丁能夠成功的使用了。

10)提交補丁的操做

git commit -a -m "patch apply"

11)切換回 master 分支之中進行分支合併

git checkout master
git merge --no-ff -m "Merge Patch" patchbrh

這樣若是隻是將補丁數據的文件發送給開發者,那麼就沒有必要進行大量代碼的傳輸,而且在建立補丁的時候也能夠針對於多個文件進行補丁的建立。

7. 利用 git format-patch 生成 GIT 專用補丁

1)建立並切換到cbrh分支

git branch -D cbrh
git branch -D patchbrh 
git checkout -b cbrh

2)建立並切換到cbrh分支

public class Empty() {
  console.log('empty file');
  console.log('git format-patch 測試')
}

3)建立並切換到cbrh分支

git commit -a -m "add formatch test"

4)下面須要與原始代碼作一個比較,並且比較後會自動的生成補丁文件

git format-patch -M master

如今表示要與 master 分支進行比較(而-M 參數就是指定分支)。

clipboard.png

此時已經生成了一個補丁文件,由於只修改了一次的內容。這個補丁文件嚴格來將就是一個 email 數據,須要將此數據發送給開發者,然後開發者能夠進行補丁的應用。

5)建立並切換到patchbrh分支上

git checkout master
git checkout -b patchbrh

6) 應用補丁的信息,利用「git am」完成

git am 0001-add-formatch-test.patch

clipboard.png

如今是將發送過來的,帶有 email 格式的補丁文件進行了應用。

7) 提交應用的更新

git commit -a -m "method patch apply"

那麼此時就能夠成功的應用補丁進行代碼的更正。

關於兩種補丁方式的說明

  • 使用git diff生成補丁兼容性是比較好的,若是你是在不是git管理的倉庫上,此類方式生成的補丁是很是容易接受的;
  • 可是若是你是向公共的開發社區進行代碼的補丁更正,那麼建議使用git format-patch,這樣不只標準,並且也能夠將更正人的信息進行公佈。

8. 多人協做開發

分支的處理其實是爲了更好的多人開發作出的準備,那麼下面就將利用兩個命令行方式(模擬其餘的開發者)進行項目代碼的編寫。首先說明一下:

  • 通常而言,master 分支項目的核心分支,只要進行代碼的克隆,那麼此分支必定會被保存下來;
  • 開發者每每會創建一系列的分支,譬如,本次練習創建了一個 brh 的分支進行代碼的編寫;
  • 若是要進行調試能夠創建一個 bug 分支;
  • 若是要增長某些新的功能則能夠創建 feature 分支。

1) 建立並切換到一個新的分支:brh

git checkout -b brh

2) 在新的分支上創建一個新的文件 —— Dept.js

public class Dept() {
  console.log('多人協做開發!');
}

3) 將此代碼進行提交

git commit -a -m 'add dept.js files'

4) 將兩個分支提交到服務器上去

git push origin master    
git push origin brh

5) [二號]爲了模擬第二個開發者,因此創建一個新的命令行窗口,而且將代碼複製下來(d:proclone)

git clone https://github.com/qq449245884/HelloGitHub.git

6) [二號] 察看分支信息

git branch -a

clipboard.png

發現如今只是將 master 分支拷貝下來了,可是 brh 分支並無存在。

7) [二號]創建並切換到brh分支上

git checkout -b brh

8) [二號]將遠程服務器端上的brh分支的內容拷貝到本地的brh分支上

git merge origin/brh

9) [二號]如今開發者增長了一個Admin.js文件

public class Admin() {
  console.log('多人協做測試!:')
}

10) [二號]將新的代碼進行提交

git add .
git commit -m 'add admin.js files'

11) [二號]如今本地的 brh 分支代碼發生了變化,那麼應該將此變化提交到遠程的 brh 分支上

git push origin brh

如今代碼已經發送到了服務器上了,而且在 brh 分支上增長了新的 Admin.java 文件。

12) [一號]這個時候最原始的開發者目錄下還只是上一次提交的內容。那麼須要取得最新的數據才能夠

對於取得最新的分支數據有兩種方式:

  • git fetch: 此操做只是取得最新的分支數據,可是不會發生 merge 合併操做
  • git pull: 此操做取出最新分支數據,而且同時發生 merge 合併操做

    git pull

clipboard.png

實際上錯誤信息也很簡單,指的是,當前的 brh 分支和服務器上的分支沒有關係,因此若是要想讀取代碼,必須讓兩 個分支產生關聯關係。

git branch --set-upstream-to=origin/brh

隨後再次讀取全部的代碼。

13) [二號]修改 Admin.js 類文件

public class Admin() {
  console.log('多人協做測試!:')
  console.log('二號我來個性了!');
}

14) [二號]將以上的代碼進行提交

git commit -a -m 'update admin.js file'

15) [二號]向服務器端提交代碼的修改

git push origin brh

16) [一號]開發者也進行 Admin.js 文件的修改

public class Admin() {
  console.log('多人協做測試!:')
  console.log('一號也進行修改了!')
}

17) [一號]將代碼提交

git commit -a -m "1 update admin.js file"

可是這個時候很明顯,兩個用戶一塊兒修改了同一個文件。

18) [一號]抓取最新的更新數據

git pull

clipboard.png

如今能夠發現,此時的程序,是兩位開發者修改了同一個代碼,因此產生了衝突。同時一號開發者之中的 Admin.js 文件的內容已經變動爲以下情:

public class Admin() {
  console.log('多人協做測試!:')
<<<<<<< HEAD
  console.log('一號也進行修改了!')
=======
  console.log('二號我來個性了!');
>>>>>>> a600e113d2d139efc73eee2052ad509fa95d16e3
}

19) [一號]手工解決衝突文件內容

public class Admin() {
  console.log('多人協做測試!:')
  console.log('一號也進行修改了!')
  console.log('二號我來個性了!');
}

20) 再次執行提交和服務器推送

git commit -a -m "3 Update Admin.js File" 
 git push origin brh

如今已經成功的由本地的衝突擴充到了遠程的衝突,相信經過一系列的代碼你們也能夠更好的理解分支的操做問題。

你的點贊是我持續分享好東西的動力,歡迎點贊!

一個笨笨的碼農,個人世界只能終身學習!

更多內容請關注公衆號《大遷世界》

相關文章
相關標籤/搜索