天天看點

了解分支(轉)

git在建立分支的時候,實際上是從整個送出曆史裡的某個起點開始(該起點被記錄為分支的祖先,辨別分支的起始位置),建立送出曆史樹的枝幹。

由于git每次送出的時候均會記錄當次送出的校檢和,配合将資料打包存儲,記錄目前倉庫相對于前一版本的變化。是以git的分支,實際上隻是一串包含對象校檢和(SHA-1)的檔案。通過這個校檢和,得出分支在送出曆史樹上的走向。

git裡建立删除分支變得非常簡單。這一點不像svn那樣每建立一個分支就需要整個目錄拷貝一份。在git上非常推薦頻繁使用分支。

甚至可以一個issue(bug)一個分支,解決完切回主分支合并;沒解決完就讓分支繼續走,主分支繼續正常任務。

基本操作

建立和銷毀

分支清單:

$: git branch
* master
  prepub
  product
      

建立分支:

$: git branch prepub
      

切換已有分支:

$: git checkout prepub
Switched to branch 'prepub'
      

建立并切換分支:

$: git checkout -b issue1234
Switched to branch 'issue1234'
      

删除分支:

$: git branch -d issue1234
Deleted branch issue1234 (was b904c07).
      

合并和沖突

合并前要先切回 要并入 的分支。

以下表示

issue1234

分支合并入

master

分支

$: git checkout master
$: git merge issue1234
Merge made by recursive.
 README |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
      

沖突的時候,git會報出哪些檔案沖突,這時候需要手動解決完沖突方可送出。

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

通過

git status

檢視沖突檔案。

$: git status
index.html: needs merge
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	unmerged:   index.html
#
      

打開

index.html

,git會在沖突位置做上标示。

<<<<<<< HEAD:index.html
<div id="footer">contact : [email protected]</div>
=======
<div id="footer">
  please contact us at [email protected]
</div>
>>>>>>> iss53:index.html
      

解決完沖突,這時候需要手動辨別該沖突已經解決,類似svn的

resolved

$: git add index.html
$: git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   index.html
#
      

這時候就可以送出了。

$: git commit -m "合并issue1234"
[master e3ece67] 合并issue1234
 1 files changed, 1 insertions(+), 0 deletions(-)
      

管理多個分支

前面提到,git非常推薦頻繁使用分支,在大量分支的情況下,我們需要對分支做好管理(曾經一次上線,開了13個分支 

= =

通過

-v

可以看到最後一次送出日志。

$: git branch -v
* master          b904c07 把丘遲的産品搜改動合并一下
  p4popt          8b93380 p4p加上refpid,開發給出來的配置是 P4P_refpid
  prepub          a6cc66b P4P解析參數少一次替換,順便解決/!失效的問題
  product         301ae4e rankbar圖檔換成data uri
      

通過

--merged

--no-merged

來檢視分支是否已經合并完成。

$: git branch --merged
* master
  p4popt
$: git branch --no-merged
  prepub
  product
      

未合并的分支,在删除時會提示分支未合并。

$: git branch -d product
warning: deleting branch 'product' that has been merged to
         'refs/remotes/s/product', but it is not yet merged to HEAD.
Deleted branch product (was 301ae4e).
      

分支管理流程

一般情況下,分支可以劃分為長分支和短分支兩種。

長分支

  • 長期任務
    • prepub

      :上線前合并,根據上線清單,從各個分支中集中到該分支,統一部署提測
    • master

      :上線後合并,長期保留一個穩定可用的分支應付緊急任務
  • 項目
  • 較難解決的bug
  • 新特性試驗田
  • 重構

長分支,經常會落後其他分支一大截,需要養成習慣,适時從其他重要分支進行合并, 尤其是項目分支 。

短分支

  • 臨時需求
  • 小bug

分支可視化

git本身的

log

提供

--gragh

選項,可以提供字元界面的分支可視化視圖。

$: git log --graph --pretty=oneline
| *   50cc7a78b7f2704a2014afa3667f6ac5b5b47374 merging refs/remotes/origin/prepub into HEAD
| |/  
| | * 8f685bd1be3757effe32d6ff37f86bd07dd2b549 又被無情地沖掉了代碼
| * | 75a17b4ad610327a9b0e1eecfc6c4bf9cade7359 修改icon
| |/  
| *   146a0990de450c854b1a7d9995e12979fff2d537 merging refs/remotes/origin/prepub into HEAD
| |/  
| | *   93b379680796eb443961bb8c59008f8ae5678be4 Merge branch 'prepub' of search.ued.taobao.net:projects/search into prepub
| | |/  
| | * | 8b93380ccfb9020bf8f8e1e8a4a553601de3c788 p4p加上refpid,開發給出來的配置是 P4P_refpid
| * | | 08201de89834f6fecb195c2b7c3546b5cafccc85 秒殺折扣浮動層樣式
| | |/  
| |/|   
| * | 0f4d1df17f79c7aa3ca3d36ab848c10b78029010 修改icon
| * | ae719fc29cc550321f284323db06a294b97c1398 p4p創意優化
| |/  
| * a6d4501e1456589d30ab1a5800b651876629c8ca 修改icon
      

git還有很多GUI工具,可以提供可視化地分支走勢圖,比如

gitk

qgit

GitX

等等。

遠端分支

至今為止,前面所有提到的概念都是直接本地操作的,并不需要任何網絡連接配接。

而git本身是一個分布式代碼管理工具(DVCS),是以分支管理上,存在本地分支和遠端分支兩種概念。

可以簡單的了解,遠端分支就是别人的本地分支

push

到伺服器上的時候産生的。比如

master

就是一個最典型的遠端分支(預設)。

$: git push origin master
      

除了

master

之外,我們還可以随便建立分支,然後

push

到伺服器上去。

$: git push origin prepub
Counting objects: 27, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (15/15), 7.30 KiB, done.
Total 15 (delta 10), reused 0 (delta 0)
To [email protected]:projects/search.git
   1b95a57..779dbe1  prepub -> prepub
      

遠端分支的辨別形式為

{remote/branch}

,比如

origin/product

$: git branch -a
  master
  p4popt
* prepub
  product
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/p4popt
  remotes/origin/prepub
  remotes/origin/product
      

遠端分支和本地分支需要區分,是以,在從伺服器上拉取特定分支的時候,需要指定本地分支名字。

$: git branch product origin/product
Branch product set up to track remote branch product from origin.
      

而1.6.2以上版本的git,可以通過

--track

選項,簡化這一過程。這也是為什麼直接執行

git clone

的時候,會自動建立本地

master

分支的原因。(實際上,

pull

操作相當于

fetch

+

merge

。)

$: git checkout --track origin/product
Branch product set up to track remote branch refs/remotes/origin/product.
Switched to a new branch "product"
      

遠端分支和本地分支是松散的結構,可以把任意遠端分支合并到任意本地分支裡;同樣,也可以把任意本地分支

push

到任意遠端分支上。

# THIS WILL MESS UP YOUR REPO!!
$: git branch
  master
* prepub
  p4popt
  product
$: git pull origin product
$: git push origin master
      

同步本地遠端分支。

$: git fetch origin
      

删除遠端分支。

$: git push origin :p4popt
To [email protected]:projects/search.git
 - [deleted]         p4popt
      

References

  • Pro Git(zh,chp.3)