【筆記】Git 中的分支建立和衝突解決(命令列)

weixin_33890499發表於2018-01-12

注:文章圖片和部分內容來自廖雪峰的git教程,鼎力推薦!!!學習交流所用 傳送門

git的分支操作

可以通過https://github.com/CameloeAnthony/GitTest 進行操作練習,首先在命令列,將遠端倉庫(github上的專案)clone到本地.

$ git clone https://github.com/CameloeAnthony/GitTest.git
1 檢視遠端分支(git branch -a)

這裡可以看到我本地和遠端分支如下:(前面帶*號的代表你當前工作目錄所處的分支)

$ git branch -a
  dev-activity
  dev-app
  develop
*  master
  test
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev-activity
  remotes/origin/dev-app
  remotes/origin/develop
  remotes/origin/master
  remotes/origin/test
  remotes/origin/mydev
2 檢視本地分支(git branch)

這是目前在我本地的分支, 工作目錄分支在master分支:

$ git branch
  dev-activity
  dev-app
  develop
* master
  test
3 切換分支(git checkout 分支名)

比如這裡切換mydev分支,本地沒有,會"自動獲取"遠端分支

$ git checkout mydev
Switched to branch 'mydev'
Your branch is up-to-date with 'origin/mydev'.

再次檢視分支,已經切換到mydev了

$  git branch
  dev-activity
  dev-app
  develop
  master
  test
* mydev

可以在github上看到分支情況


1833901-3ad73d72cffe8755.png

這裡獲取一個遠端沒有的分支, 這裡會找不到

$ git checkout develop01
error: pathspec 'develop01' did not match any file(s) known to git.

是因為遠端倉庫沒有嘛? 我在github(遠端倉庫)建立了一個branchCreateRemote,然後我再次嘗試切換到遠端分支,同樣會找不到

$ git checkout branchCreateRemote
error: pathspec 'branchCreateRemote' did not match any file(s) known to git.

這是因為git在獲取遠端倉庫(github)上的分支的時候(第一次clone到本地的時候),是把分支資訊也一次性clone到了本地,而不是每次checkout的時候去請求的。問題迎刃而解 git
pull 再次把遠端資訊獲取過來,現在可以checkout到新分支了。

$ git pull
From https://github.com/CameloeAnthony/GitTest
 * [new branch]      branchCreateRemote -> origin/branchCreateRemote
Already up-to-date.
4 在本地建立分支(git branch 分支名)
$  git branch test01  

當然我們也可以加上-b

$ git checkout -b test01
Switched to a new branch 'test01'

git checkout命令加上-b參數列示建立並切換,相當於以下兩條命令:

$ git branch test01
$ git checkout test01
Switched to branch 'test01'
5 把本地的分支推到遠端倉庫( git push origin 分支名)
$ git push origin test01
6 刪除本地分支( git branch -d 分支名)

這裡就把本地的test01分支刪除了

$ git branch -d test01
Deleted branch test01 (was 641b395b).

如果你在test01上,就不能準確刪除,需要先切換到其他分支,才能刪除test01分支哦。

7 刪除遠端分支( git branch -r -d 分支名)

操作6中我們把本地的test01 分支刪了,這裡使用下面兩種方法刪除遠端的test01

#第一種方法
$ git branch -r -d origin/test01
Deleted remote-tracking branch origin/test01 (was d8e6798).
#第二種方法
$ git push origin :branch-name  

8 修改並提交( git add 檔名, git commit -m "提交說明)

首先我們切換到develop分支進行開發,這裡模擬更改,增加一行文字。


1833901-6ffbe24bde91975a.png

這個時候沒有提交更新,是不能切換分支的

$  git checkout master
error: Your local changes to the following files would be overwritten by checkout:
    README.md
Please commit your changes or stash them before you switch branches.
Aborting

這裡提交develop

$ git add README.md
$ git commit -m "branch test on develop branch"
[develop fd94b13] branch test on develop branch
1 file changed, 1 insertion(+)

這裡再次嘗試切換到master分支,提示我們當前分支超出master分支1次提交(這是因為我們在develop分支上還沒有push到遠端倉庫),不過這裡成功切換到了master。


1833901-76c5133d86b3d093.png
在develop分支做更改
git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

這裡我們直接對master 分支進行更改並提交:


1833901-16c7f603a2c39dee.png
$ git add README.md
git commit -m  "branch test on master branch"
[master 27f26f4] branch test on master branch
1 file changed, 2 insertions(+), 1 deletion(-)

這裡我們切換回develop分支還是master分支,我們發現我們的修改都在。這裡工作就完成了嗎?當然不是 。
我在我們的遠端倉庫(github)上可以看到develop和master的內容並沒有提交上去。(哈哈,這是我以前剛學git的一個錯誤,總是忘記push)


1833901-c53cc184034016d2.png

9 合併(git merge)並解決衝突

針對上面,我們對master和develop分支分別做了一次更改。但是都還沒有push到遠端倉庫,但是這不會影響本地的合併。


1833901-39edb453b8d253a7.png
分別做了一次更改,目前在master分支

現在,我們把develop分支的工作成果合併到master分支上(合併(git merge)命令用於合併指定分支到當前分支。):

$ git merge develop
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

這裡報錯了,我們開啟檔案,可以清晰的看到我們master上和develop上的兩個修改。


1833901-6de8cedf4274538f.png

Git用<<<<<<<,=======,>>>>>>>標記出不同分支的內容,這裡合併,解決衝突。


1833901-d27fe6cdc8e63b82.png

10 push到遠端倉庫(github)

我們在9中完成了衝突的修改,這裡我們提交master分支。

$ git add README.md 
$ git commit -m "merge and fix conflicts in develop and master"
$ git push origin master
Counting objects: 12, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (12/12), 1.03 KiB | 526.00 KiB/s, done.
Total 12 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/CameloeAnthony/GitTest.git
   d8e6798..687157a  master -> master

可以看到這裡Github已經收到了更新


1833901-6e95e09772ba4e36.png

develop分支同樣沒有提交到github,這裡也進行同樣的提交(因為我們在8中已經commit了,所以這裡不需要commit操作)。

$ git push origin develop

成功提交。

11 檢視分支合併圖(用git log --graph命令可以看到分支合併圖)

在8中,我們看到我們在master(藍色)和develop(紅色)上分別做了修改,如下圖


1833901-ab217d560955ce26.png
分別做了一次更改,目前在master分支

然後我們在9,10中merge develop到了master,如下圖


1833901-7f6fbe900f9986ff.png
將develop分支合併到了master分支

所以我們通過git log --graph命令可以看到分支合併圖(下圖) 可以和上圖對應理解。
1833901-5fb964746d3d3c9d.png

12 git工作現場儲存(git stash )

我們對develop分支再次做更改


1833901-28d19b5426525750.png

然後切換到master分支的時候回收到下面的提示,意思說在切換的之前要麼git commit提交 更改,要麼使用git stash 儲存工作現場。

$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
    README.md
Please commit your changes or stash them before you switch branches.
Aborting

執行git stash

$ git stash
Saved working directory and index state WIP on develop: fd94b13 branch test on develop branch

然後現在就可以切換到其他分支,並做更改了。修改回來之後我們回到develop分支。我們可以通過git status檢視當前分支狀態,工作區間很乾淨

$ git status
On branch develop
nothing to commit, working tree clean

通過 git stash list 檢視我們儲存的工作區間

$ git stash list
stash@{0}: WIP on develop: fd94b13 branch test on develop branch

工作現場還在,Git把stash內容存在某個地方了,但是需要恢復一下,有兩個辦法:

一是用git stash apply恢復,但是恢復後,stash內容並不刪除,你需要用git stash drop來刪除;

另一種方式是用git stash pop,恢復的同時把stash內容也刪了:

$ git stash pop
On branch develop
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (ae4c714f9643327a2739b3a323d0786fcb936756)

再用git stash list檢視,就看不到任何stash內容了:

$ git stash list

可以多次stash,恢復的時候,先用git stash list檢視,然後恢復指定的stash,用命令:

$ git stash apply stash@{0}

13 利用分支進行團隊協作

13.1 幾個工作環境

按照我這邊的開發流程會分為這幾個環境:
私人環境:比如我上面的mydev分支,是我開發的分支,然後開發好之後會將mydev的更改提交到開發環境(develop分支)。

開發環境:開發環境時程式猿們專門用於開發的伺服器,配置可以比較隨意,為了開發除錯方便,一般開啟全部錯誤報告和測試工具,是最基礎的環境。開發環境的分支,比如我上面的develop分支。

測試環境:一般是克隆一份生產環境的配置,一個程式在測試環境工作不正常,那麼肯定不能把它釋出到生產伺服器上,是開發環境到生產環境的過度環境。測試環境的分支一般是test分支,部署到公司私有的伺服器或者區域網伺服器上,主要用於測試是否存在bug,一般會不讓使用者和其他人看到,並且測試環境會盡量與生產環境相似。但是我們的專案按照客戶要求,也會專門為內部客戶配置測試環境。我在develop分支和別人的程式碼合併後會被推到test分支,公司會安排專門的人員進行test分支管理和合並測試。

生產環境: 生產環境是指正式提供對外服務的,一般會關掉錯誤報告,開啟錯誤日誌,是最重要的環境。部署分支一般為master分支。在test分支確認無誤後會推到master分支。

三個環境也可以說是系統開發的三個階段:開發->測試->上線,其中生產環境也就是通產說的真實的環境,最後交給使用者的環境。

13.2 分支管理

在實際開發中,我們應該按照幾個基本原則進行分支管理:

首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;

那在哪幹活呢?每個人分別在自己的分支是幹活,比如我自己的mydev分支,然後提交到develop分支(dev分支),dev分支是不穩定的,到某個時候,比如1.0版本釋出時,再把dev分支合併到master上,在master分支釋出1.0版本;

你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合併就可以了。

所以,團隊合作的分支看起來就像這樣:

1833901-2857718d3cfd49ff
圖片來自廖雪峰部落格,這裡沒有單獨新增test分支
13.3 推送分支

推送分支,就是把該分支上的所有本地提交推送到遠端庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠端庫對應的遠端分支上:

$ git push origin master

如果要推送其他分支,比如develop,就改成:

$ git push origin develop

master分支是主分支,因此要時刻與遠端同步;

dev分支是開發分支,團隊所有成員都需要在上面工作,所以也需要與遠端同步;

bug分支只用於在本地修復bug,就沒必要推到遠端了,除非老闆要看看你每週到底修復了幾個bug;

feature分支是否推到遠端,取決於你是否和你的小夥伴合作在上面開發。

13.4 多人工作模式

多人協作的工作模式通常是這樣:

  • 首先,可以試圖用git push origin branch-name推送自己的修改;

  • 如果推送失敗,則因為遠端分支比你的本地更新,需要先用git pull試圖合併;

  • 如果合併有衝突,則解決衝突,並在本地提交;

  • 沒有衝突或者解決掉衝突後,再用git push origin branch-name推送就能成功!

  • 如果git pull提示“no tracking information”,則說明本地分支和遠端分支的連結關係沒有建立,用命令git branch --set-upstream branch-name origin/branch-name。

這就是多人協作的工作模式,一旦熟悉了,就非常簡單。

參考文件

http://blog.csdn.net/arkblue/article/details/9568249
廖雪峰的Git教程
軟體開發環境-開發環境、測試環境、生產環境的區別

相關文章