前言
在現代化程式專案開發中版本控制成了工作中不可缺少的一部分,無論使用哪種語言、框架,以及無論開發什麼專案,都需要版本控制。
版本控制(Version Control System)主要有以下幾個作用:
名稱 |
模型 |
併發模式 |
歷史模式 |
變更範圍 |
網路協議 |
原子提交性 |
---|---|---|---|---|---|---|
CVS | Client-server | Merge | Changeset | File | Pserver,ssh | No |
SVN | Client-server | 3-way merge,recursive merge,octopus merge | Changset and Snapshot | Tree | custion(svn),custom(svn) over ssh,HTTP and SSL (usingWebDAV) | Yes |
Git | Distributed | Merge or lock | Snapshot | Tree | custion,custom over ssh,rsync,HTTP/HTTPS,email,bundles | Yes |
- 版本庫模型(Repository model)
描述了多個原始碼版本庫副本間的關係,有客戶端/伺服器和分散式兩種模式。在客戶端/伺服器模式下,每一使用者通過客戶端訪問位於伺服器的主版本庫,每一客戶機只需儲存它所關注的檔案副本,對當前工作副本(working copy)的更改只有在提交到伺服器之後,其它使用者才能看到對應檔案的修改。而在分散式模式下,這些原始碼版本庫副本間是對等的實體,使用者的機器出了儲存他們的工作副本外,還擁有本地版本庫的歷史資訊。
- 併發模式(Concurrency model)
描述了當同時對同一工作副本/檔案進行更改或編輯時,如何管理這種衝突以避免產生無意義的資料,有排它鎖和合並模式。在排它鎖模式下,只有發出請求並獲得當前檔案排它鎖的使用者才能對對該檔案進行更改。而在合併模式下,使用者可以隨意編輯或更改檔案,但可能隨時會被通知存在衝突(兩個或多個使用者同時編輯同一檔案),於是版本控制工具或使用者需要合併更改以解決這種衝突。因此,幾乎所有的分散式版本控制軟體採用合併方式解決併發衝突。
- 歷史模式(History model)
描述瞭如何在版本庫中存貯檔案的更改資訊,有快照和改變集兩種模式。在快照模式下,版本庫會分別儲存更改發生前後的工作副本;而在改變集模式下,版本庫除了儲存更改發生前的工作副本外,只儲存更改發生後的改變資訊。
- 變更範圍(Scope of change)
描述了版本編號是針對單個檔案還是整個目錄樹。
- 網路協議(Network protocols)
描述了多個版本庫間進行同步時採用的網路協議。
- 原子提交性(Atomic commit)
描述了在提交更改時,能否保證所有更改要麼全部提交或合併,要麼不會發生任何改變。
SVN
SVN 是 Subversion 的簡稱,目前是 Apache 專案底下的一個開放原始碼的版本控制系統,它的設計目標就是取代 CVS。
優點:
- 集中式管理,管理方式在服務端配置好,客戶端只需要同步提交即可,使用方便,操作簡單,很容易就可以上手。
- 在服務端統一控制好訪問許可權,利用程式碼的安全管理。
- 所有的程式碼已服務端為準,程式碼一致性高。
缺點:
- 所有操作都需要通過服務端進行同步,這會導致伺服器效能要求比較高。如果伺服器當機了就無法提交程式碼了。
- 分支管理不靈活,SVN 分支是一個完整的目錄,且這個目錄擁有完整的實際檔案,這些操作都是在服務端進行同步的,不是本地化操作,如果要刪除分之,也是需要將遠端的分支進行刪除,這會導致大家都得同步。
- 需要聯網。如果無法連線到 SVN 伺服器,就無法提交自己的程式碼,更別說還原、對比等操作了。如果在內網還好,網速比較穩定,同步相對比較快,如果是通過外網同步,有可能就需要同步很久。
GIT
GIT 是 Linus Trovalds 的作品,是一個開放原始碼的版本控制軟體。與SVN最大的區別,就是分散式的管理。
優點:
- 分散式開發時,可以 Git clone 克隆一個本地版本,然後在本地進行操作提交,本地可以完成一個完整的版本控制。在釋出的時候,使用Git push來推送到遠端即可。
Git 分支的本質是一個指向提交快照的指標,速度快、靈活,分支之間可以任意切換。都可以在本地進行操作可以不同步到遠端。
衝突解決,多人開發很容易就會出現衝突,可以先 Pull 遠端到本地,然後在本地合併一下分支,解決好衝突,在 Push 到遠端即可。
離線工作,如果 Git 伺服器出現問題,也可以在本地進行切換分支的操作,等聯網後再提交、合併等操作。
缺點:
- Git 沒有嚴格的許可權控制,一般是通過系統設定檔案的讀寫許可權來做許可權控制。
- 工作目錄只能是整個目錄,而 Svn 可以單獨 Checkout 某個有許可權的目錄。
GIT vs SVN
git:
- 要配合 Hub,可以避免分散式損壞。
- 適合純程式碼。
svn
- 有許可權控制,避免全被 Clone 走。
- 綜合性文件管理,結合起來就完美。顯然最大的不同在於 Git 是分散式的。
建議
- 如果對訪問控制、許可權分配和程式碼安全性等要求比較高的,建議使用 Svn。
- 如果是分散式,多人開發,版本迭代比較快的專案,建議使用 Git。
Git 組成結構
- 工作區:用來儲存專案的後設資料和物件資料庫的地方。這是 Git 中最重要的部分,從其它計算機克隆倉庫是,拷貝的就是這裡的資料。
- 暫存區:儲存了下次將提交的檔案列表資訊,一般在 Git 倉庫目錄中。有時候也被稱作“索引”,不過一般說法還是叫暫存區域。
- 版本庫:也叫本地版本庫,之所以說 Git 快,大部分提交都是對本地倉庫而言的,不依賴網路,最後一次會推送到遠端倉庫。
- 遠端倉庫:可以看作是 GitHub,它是一個遠端倉庫。
檔案的狀態
新建檔案狀態為 *Untracked*,`add` 命令執行後狀態變為 *staged*,已存在的檔案狀態為 *Unmodified*,修改檔案內容,檔案狀態變為 *modified*,`commit` 提交,檔案狀態變成 *Unmodified*。
Git 常用命令
建立版本庫
$ git clone <url> # 克隆遠端版本庫
$ git init # 初始化本地版本庫
修改 & 提交
$ git status # 檢視狀態
$ git diff # 檢視變更內容
$ git add . # 跟蹤所有改動過的檔案
$ git add <file> # 跟蹤指定的檔案
$ git mv <old> <new> # 檔案改名
$ git rm <file> # 刪除檔案
$ git rm --cached <file> # 停止跟蹤檔案但不刪除
$ git commit -m "commit message" # 提交所有更新過的檔案
$ git commit --amend # 修改最後一次提交
檢視提交歷史
$ git log # 檢視提交歷史
$ git log -p <file> # 檢視指定檔案的提交歷史
$ git blame <file> # 以列表方式檢視指定檔案的提交歷史
撤銷
$ git reset --hard HEAD # 撤銷工作目錄中所有未提交檔案的修改內容
$ git checkout HEAD <file> # 撤銷指定的未提交檔案的修改內容
$ git revert <commit> # 撤銷指定的提交
分支與標籤
$ git branch # 顯示所有本地分支
$ git check out <branch/tag> # 切換到指定分支或標籤
$ git branch <new-branch> # 建立新分支
$ git branch -d <branch> # 刪除本地分支
$ git tag # 列出所有本地標籤
$ git tag <tagname> # 基於最新提交建立標籤
$ git tag -d <tagname> # 刪除標籤
合併 & 衍合
$ git merge <branch> # 合併指定分支到當前分支
$ git rebase <branch> # 衍合指定分支到當前分支
遠端操作
$ git remote -v # 檢視遠端版本庫資訊
$ git remote show <remote> # 檢視指定遠端版本庫資訊
$ git remote add <remote> <url> # 新增遠端版本庫
$ git fetch <remote> # 從遠端庫獲取程式碼
$ git pull <remote> <branch> # 下載程式碼及快速合併
$ git push <remote> <branch> # 上傳程式碼及快速合併
$ git push <remote> :<branch/tag-name> #刪除遠端分支或標籤
$ git push --tags # 上傳所有標籤
配置身份資訊
首先得有個 GitHub 賬號,然後配置:
$ git config --global user.name "Galois"
$ git config --global user.name "Galois.Alex@Gmaill.com"
提交檔案時,就知道這個檔案是誰提交的,出了問題,就知道是誰幹的!
檢視配置資訊
$ git config --list
建立本地倉庫
$ cd ~/Code/ && mkdir myProject
進入倉庫後初始化倉庫
$ cd ./myProject
$ git init
初始化倉庫後,此倉庫目錄下多了一個 .git 的目錄,這個目錄是 Git 來跟蹤管理版本庫的,如果對這個目錄做一些操作意味著把 Git 倉庫給破壞了。在 Mac 環境下,在 Finder 目錄環境介面裡可以使用快捷鍵
commond
+shift
+.
來顯示或者隱藏檔名和資料夾名為 “.” 開頭的檔案和資料夾。(檔名或資料夾名以“.”開頭的都為隱藏檔案或隱藏資料夾)
Git 本地工作流
- 克隆倉庫
- 在工作目錄中新增、修改、刪除檔案
- 暫存檔案,將檔案的快照放入暫存區
- 提交更新,把暫存區的內容提交到 Git 倉庫中
$ touch file.txt
$ git add file.txt # 暫存單個檔案
$ git add ./* # 批量暫存當前目錄下所有內容
$ git status # 檢視檔案狀態
$ git commit -m "test" # 提交
$ git status
$ git log # 檢視提交記錄
$ vim file.txt # 隨便編輯點檔案內容
$ git diff file.txt # 和倉庫中已經提交的 file.txt 比較
Add 和 Commit 的區別
本作品採用《CC 協議》,轉載必須註明作者和本文連結