Git 版本控制與工作流
原文 http://www.jianshu.com/p/67afe711c731

Git Version Control
這篇文章是針對git版本控制和工作流的 總結 ,如果有些朋友之前還沒使用過git,對git的基本概念和命令不是很熟悉,可以從以下基本教程入手:
基本概念
Git是什么?
Git 是 分布式 版本控制系統,與SVN類似的 集中化 版本控制系統相比,集中化版本控制系統雖然能夠令多個團隊成員一起協作開發,但有時如果中央服務器宕機的話,誰也無法在宕機期間提交更新和協同開發。甚至有時,中央服務器磁盤故障,恰巧又沒有做備份或備份沒及時,那就可能有丟失數據的風險。
但Git是分布式的版本控制系統,客戶端不只是提取最新版本的快照,而且將整個代碼倉庫鏡像復制下來。如果任何協同工作用的服務器發生故障了,也可以用任何一個代碼倉庫來恢復。而且在協作服務器宕機期間,你也可以提交代碼到本地倉庫,當協作服務器正常工作后,你再將本地倉庫同步到遠程倉庫。
為什么要使用Git
- 能夠對文件 版本控制 和 多人協作開發
- 擁有強大的 分支特性 ,所以能夠靈活地以 不同的工作流 協同開發
- 分布式版本控制系統 ,即使協作服務器宕機,也能繼續提交代碼或文件到本地倉庫,當協作服務器恢復正常工作時,再將本地倉庫同步到遠程倉庫。
- 當團隊中某個成員完成某個功能時,通過 pull request 操作來通知其他團隊成員,其他團隊成員能夠review code后再合并代碼。
Git有哪些特性
- 文件三種狀態(modified, staged, committed)
- 直接記錄快照,而非差異比較
- 多數操作僅添加操作
- 近乎所有操作都是本地執行
- 時刻保持數據完整性
有關以上特性的詳細解釋,請查看Pro git的 git基礎章節
Git基本工作流程
- 在git版本控制的目錄下修改某個文件
- 使用 git add 命令對修改后的文件快照,保存到暫存區域
- 使用 git commit 命令提交更新,將保存在暫存區域的文件快照永久轉儲到 Git 目錄中
Git基本技巧
- 自動補全
- Git 命令別名
關于具體如何使用自動補全和命名別名技巧,請查看Pro git的 技巧和竅門
Git版本控制
創建倉庫
- git init
- git clone
- git config
保存修改
- git add
- git commit
查看倉庫
- git status
- git log --oneline
撤銷修改
查看之前的commit
- git checkout <commit> <file>
- git checkout <commit>
- git checkout <branch>
撤銷公共修改
- git revert <commit>
撤銷本地修改
- git reset
- git clean
重寫Git歷史記錄
- git commit --amend
- git rebase
- git reflog
Git協作開發
分支
- git branch
- git checkout
- git merge
倉庫同步
- git remote
- git fetch
- git pull
- git push
Git工作流
由于git擁有強大的 分支特性 ,它的工作流比較靈活而缺乏約束,于是參考 Atlassian Git Tutorial 的 Comparing Workflows 章節提供 四種Git工作流 :
- Centralized Workflow
- Feature Branch Workflow
- Gitflow Workflow
- Forking Workflow
以上工作流只是 參考指南 ,而不是具體規則。你可以根據自己實際情況來選擇適合自己的工作流或微調來滿足自己的需要。
Centralized Workflow
過渡到分布式版本控制系統看起來像一個艱巨的任務,但如果你充分利用好git的話,你不必改變你既有的工作流,你的團隊可以采用與之前使用SVN一樣的方式來開發項目。
如何工作

Centralized Workflow
- 從遠程倉庫(central repository)克隆工程到本地倉庫(local repository) --- git clone
- 在本地倉庫編輯文件和提交更新 --- git add 和 git commit
- fetch遠程倉庫已更新的commit到本地倉庫和rebase到已更新的commit的上面 --- git fetch 和 git rebase 或 git pull --rebase
- push本地主分支(master branch)到遠程倉庫 --- git push
管理沖突

-
何時發生沖突:在開發者發布它們功能之前,他們需要fetch遠程倉庫已更新的commit到本地倉庫和rebase到已更新的commit的上面。有時,本地提交與遠程提交會發生沖突,git會暫停rebase過程來讓你手動解決沖突。
-
如何解決沖突:你可以使用 git status 和 git add 來手動解決合并時沖突。
Feature Branch Workflow
Feature Branch Workflow的主要思想就是在開發每個功能時都應該創建 一個獨立的分支 而不只是使用主分支。由于每個分支是獨立且互不影響,這就意味著主分支不會包含broken code,對持續集成環境是很有幫助的。
如何工作

Feature Branch Workflow
- 仍然使用遠程倉庫(central repository)和主分支(master branch)仍記錄官方工程的歷史
- 開發者每次開發新功能時都創建一個新分支 --- git checkout -b
- Feature branches應該推送到遠程倉庫(central repository) --- git push
- 發送pull request來請求管理員能否合并到主分支(master branch)
- 發布新功能到遠程倉庫(central repository)
Pull Request
Pull request是一種當開發者完成一個新功能后向其他團隊成員發送通知的機制。它的使用過程如下:
- 開發者可以通過Github或Bitbucket發送pull request

Pull request on Github
- 其他的團隊成員審查、討論和修改代碼
- 項目維護者合并新增功能分支到主分支(master branch),然后關閉pull request
Gitflow Workflow
Feature Branch Workflow是一種非常靈活的開發方式。對于一些規模比較大的團隊,最好就是給特定的分支賦予不同的角色。除了 功能分支(feature branch) ,Gitflow Workflow還使用獨立的分支來 準備發布(preparing) , 維護(maintaining) , 和 記錄版本(recording releases) 。下面我會逐個介紹這個幾個分支:Historical Branches、Feature Branches、Release Branches和Maintenance Branches。
Historical Branches

Historical Branches
- master分支 保存官方發布歷史
- develop分支 衍生出各個feature分支
Feature Branches

Feature Branches
- feature分支 使用develop分支作為它們的父類分支
- 當其中一個feature分支完成后,它會合并會develop分支
- feature分支應該從不與master分支直接交互
Release Branches

Release Branches
- release分支 主要用來清理釋放、測試和更新文檔
- 一旦develop分支獲得足夠的功能來發布時,你可以從develop衍生出一個release分支
- 一旦準備好上架,release合并到master分支并且標記一個版本號
- 另外,還需要合并回develop分支
Maintenance Branches

Maintenance Branches.png
- maintenance分支 用來快速給已發布產品修復bug或微調功能
- 它從master分支直接衍生出來
- 一旦完成修復bug,它應該合并回master分支和develop分支
- master應該被標記一個新的版本號
標記Tags
使用兩個命令來給master分支標記版本號:
- git tag -a 0.1 -m "Initial public release" master
- git push origin master --tags
Forking Workflow
Forking Workflow與以上討論的工作流很不同,一個很重要的 區別 就是它不只是多個開發共享一個遠程倉庫(central repository),而是每個開發者都擁有一個獨立的服務端倉庫。也就是說每個contributor都有兩個倉庫:本地私有的倉庫和遠程共享的倉庫。

Forking Workflow
Forking Workflow這種工作流主要好處就是每個開發者都擁有自己的遠程倉庫,可以將提交的commits推送到自己的遠程倉庫,但只有工程維護者才有權限push提交的commits到官方的倉庫,其他開發者在沒有授權的情況下不能push。Github很多 開源項目 都是采用Forking Workflow工作流。
如何工作
- 在服務器上有一個官方公共的倉庫
-
開發者fork官方倉庫來創建它的拷貝,然后存放在服務器上
Fork official repository.png
- 當開發者準備好發布本地的commit時,他們push commit到他們自己的公共倉庫
- 在自己的公共倉庫發送一個pull request到官方倉庫
- 維護者pull貢獻者的commit到他自己的本地倉庫
- 審查代碼確保它不會破壞工程,合并它到本地倉庫的master分支
- push master分支到服務器上的官方倉庫
- 其他開發者應該同步官方倉庫。