git
git介紹與基本原理
git介紹
概述
git的全稱爲Global Information Tracker,是由Linux創始人林納斯-託瓦茲發明的一種分佈式版本工具,最開始用以管理Linux系統版本的控制,現已被很多企業廣泛用以小型、中型、大型項目的版本控制。其主要作用是備份、回溯、共享軟件項目,有着速度快、完全分佈式、允許成千上萬個並行開發的分支、有能力高效管理類似 Linux 內核一樣的超大規模項目等特點。
git分佈式管理
在git分佈式版本控制系統中,客戶端並不只提取最新版本的文件快照,而是把原始的代碼倉庫完整地鏡像下來。這麼一來,任何一處協同工作用的服務器發生故障,事後都可以用任何一個鏡像出來的本地倉庫恢復。這類系統都可以指定和若干不同的遠端代碼倉庫進行交互。因此,你就可以在同一個項目中,分別和不同工作小組的人相互協作。你可以根據需要設定不同的協作流程。其工作方式如下圖:
git與svn
從上圖可以看到,版本控制工具從集中式發展到分佈式,花了將近20年的時間,現如今市面上使用較多的是svn以及git這兩種工具,他們各自的優缺點,可以查看svn與git的比較
git原理
.git重要目錄以及文件介紹
當你在一個新目錄或已有目錄內執行git init時,Git會創建一個.git目錄,其結構大致如下:
drwxr-xr-x 2 mi mi 4096 2月 2 11:38 branches
-rw-rw-r-- 1 mi mi 25 4月 16 20:44 COMMIT_EDITMSG
-rw-r--r-- 1 mi mi 314 2月 17 11:53 config
-rw-r--r-- 1 mi mi 73 2月 2 11:38 description
-rw-r--r-- 1 mi mi 99 4月 2 20:05 FETCH_HEAD
-rw-rw-r-- 1 mi mi 541 2月 20 20:57 gitk.cache
-rw-rw-r-- 1 mi mi 23 3月 24 14:16 HEAD
drwxr-xr-x 2 mi mi 4096 2月 2 11:38 hooks
-rw-rw-r-- 1 mi mi 17954 4月 16 20:44 index
drwxr-xr-x 2 mi mi 4096 2月 2 11:38 info
drwxr-xr-x 3 mi mi 4096 2月 2 11:38 logs
drwxr-xr-x 240 mi mi 4096 4月 16 20:44 objects
-rw-rw-r-- 1 mi mi 41 4月 7 16:05 ORIG_HEAD
-rw-r--r-- 1 mi mi 179 2月 2 11:38 packed-refs
drwxr-xr-x 5 mi mi 4096 4月 7 16:05 refs
其中最重要的幾個結構介紹如下:
- config文件:包含項目特有的配置選項;
- info目錄: 保存了一份不希望在.gitignore文件中管理的忽略模式的全局可執行文件;
- hooks目錄:保存了客戶端與服務器端鉤子腳本;
- HEAD文件:指向當前git分支;
- object目錄:存儲所有數據內容;
- refs目錄:存儲指向數據分支的提交對象的指針;
- index文件:保存了暫存區域信息,快照索引。
git工作區域
從上圖可以清楚的看到,本地使用git時,有3個工作區域:工作目錄、暫存區、本地倉庫。
- 工作目錄:指從本地倉庫取出某版本的所有目錄與文件;
- 暫存區:講修改的文件添加索引(快照)後的狀態,index文件
- 本地倉庫:存有完整代碼的集合,用以管理版本
從而我們可以總結出,基本的git工作流程如下:
- 在工作目錄中修改某些文件;
- 對修改後的文件進行快照,然後保存到暫存區域;
- 提交更新,將保存在暫存區域的文件快照永久轉儲到git目錄中。
除了本地這3個狀態,其實還有一個叫遠程分支,即遠程代碼倉庫,一般存儲着該項目最完整的代碼,再進行本地開發前,一般要同步遠程代碼倉庫中的代碼,以保證代碼的同步。
git快照
傳統的VCS關心的是文件內容的具體差異,而git關係的是文件數據整體是否發生了變化,傳統的VCS工作方式如下圖,其每個版本中記錄着各個文件的具體差異:
git則並不保存這些前後變化的差異數據,git更像是把變化的文件作快照後,記錄在一個微型的文件系統中。每次提交更新時,它會縱覽一遍所有文件的指紋信息並對文件作一快照,然後保存一個指向這次快照的索引。爲提高性能,若文件沒有變化,git不會再次保存,而只對上次保存的快照作一鏈接。其工作方式如下圖:
正是git這種工作方式,使其顛覆了傳統VCS的套路,越來越被推崇。
git完整性
如上圖所示,git使用SHA-1算法計算數據的校驗和,通過對文件的內容或目錄的結構計算出一個SHA-1哈希值,作爲指紋字符串。該字串由40個十六進制字符(0-9及a-f)組成,看起來就像是:
760ca66a1546160113df602a5b1edda24b0bb98a
在保存到git之前,所有數據都要進行內容的校驗和(checksum)計算,並將此結果作爲數據的唯一標識和索引。因此如果文件在傳輸時變得不完整,或者磁盤損壞導致文件數據缺失,git都能立即察覺, 從而保證了git數據的完整性以及安全性。
git對象
git是一套內容尋址文件系統,這種說法的意思是,git從核心上來看不過是簡單地存儲鍵值對(key-value)。它允許插入任意類型的內容,並會返回一個鍵值,通過該鍵值可以在任何時候再取出該內容。git所有內容以tree、blob對象以及commit存儲,其中tree對象對應於Linux中的目錄,blob對象則大致對應於inodes或文件內容,commit爲一個修改的快照。下圖是一個簡單的git項目存儲結構圖:
存儲git對象的目錄就在objects,當git添加一個對象後,可以在objects目錄下看到一個文件。這便是git存儲數據內容的方式──爲每份內容生成一個文件,取得該內容與頭信息的SHA-1校驗和,創建以該校驗和前兩個字符爲名稱的子目錄,並以(校驗和)剩下38個字符爲文件命名(保存至子目錄下)。
進入項目的目錄,在終端輸入以下指令,即可看到git存儲的所有對象。
$ find .git/objects -type f
.git/objects/76/5a5cf64fe3b1a8d3dc1cabf2045a134cdde824
.git/objects/76/0ca66a1546160113df602a5b1edda24b0bb98a
.git/objects/76/1d169fefbe8577272be4a3bf569b48139f62e0
.git/objects/76/2e0211d471f9ffc57b2c8da4d2abc18479eb25
.git/objects/d6/1307ccaa342049d8ba9c7a5e6545edb4a5f622
.git/objects/d6/e8ece936713f55af69eca275459ce6fbd19084
.git/objects/d6/48fcee7a49f0c1676de9eea6eebb575308ae72
.git/objects/68/d5ed6705ca88879118b594256df63f0d5ad68f
.git/objects/21/f9817189ab6b807e78a1b6cd19baf0497c11e9
...
使用以下指令,可以看到對象所存儲的類型:
git cat-file -t 765a5cf64fe3b1a8d3dc1cabf2045a134cdde824
blob
git cat-file -t 761d169fefbe8577272be4a3bf569b48139f62e0
tree
git cat-file -t 760ca66a1546160113df602a5b1edda24b0bb98a
commit
使用以下指令,可以看到對象所存儲的內容:
$ git cat-file -p 760ca66a1546160113df602a5b1edda24b0bb98a
tree cd04844da69b1b5f1bc893b188fcb3bdf07b3917
parent 292dc4eb120cab96eb8eea1fd5c8b6c9834db46e
author KidSea <[email protected]> 1553173451 +0800
committer KidSea <[email protected]> 1553408224 +0800
add basemodelfragment
git cat-file -p 761d169fefbe8577272be4a3bf569b48139f62e0
040000 tree c5d48785dc0218b16f1563609069b442ea8ce922 musicplayer
git cat-file -p c5d48785dc0218b16f1563609069b442ea8ce922
100644 blob e8bfcf05a48f9655a9dcdf51a57e82f6d9717681 MusicApplication.java
040000 tree ac16eb60b1610fe52fda6492a926a16c37b9c78c base
040000 tree 8a751b9740e53f5ef82092bdbf0b1ee8c66de841 ui
040000 tree ce61d25e48e3bc41cc626d74ed44f1ff0ee62f0c utils
040000 tree d6d6195a28d88033043e0a6e8dbde91002e65796 widget
從tree輸出的結果,也可以驗證,前面所說的,其代表項目的目錄結構。
git基本使用
git的使用網上有很多,這裏不在贅述,推薦一本git的基本教程《Pro Git》,之前寫過一篇git教程也可以參考下。
git工作流
推薦一篇好文章深入理解學習Git工作流
repo介紹
repo是谷歌基於python開發的一個管理git倉庫的自動化腳本,它的出現不是爲了代替git而是爲了更好的管理git,關於其原理以及實現,這裏推薦一篇以前同事寫的一篇文章repo介紹
對於應用開發或者系統開發時,當一個項目達到一定程度,不免會創建很多Project或者Module,這時候就可以使用repo來管理項目,能夠提升一定的工作效率。
automerge介紹
AutoMerge概念的提出是基於Android系統多分支,多渠道的情境下,這種時候,產商們往往會維護很多代碼分支,而很多代碼是通用的,實現自動的代碼流,能夠減輕日常開發的工作量,提升工作效率,減少維護成本。
這裏不在贅述其介紹,推薦一篇以前同事寫的文章一種Android多分支的自動合併方案
這個技術可能應用層面使用的概率較少,但是項目達到一定規模後可能也可以嘗試使用該技術。
git開發工具介紹
由於筆者習慣使用Linux系統以及Android Studio(簡稱AS)進行開發,所以下面將對推薦Linux以及AS中好用的git管理工具。
Linux
tig
tig是Linux系統下用以方便查看git commit信息的工具。
安裝:sudo apt-get install tig
使用方式:
打開terminal,進入項目根目錄(.git所在的根目錄),輸入tig
鍵盤上下選擇鍵可以選擇commit信息
長按Enter鍵可以瀏覽commit詳細信息
按q退出
以下爲tig的使用展示。
gitk
gitk是git提供的一個gui工具,可以很清晰地查看搜索提交歷史及git相關操作。
安裝:sudo apt-get install gitk
使用方式:
打開terminal,進入項目根目錄(.git所在的根目錄),輸入gitk
以下爲gitk的使用展示。
通過右鍵我們可以執行一些簡單的操作,包括基於當前提交創建tag,創建分支,reset到當前提交、revert當前提交、對比兩個commit差異等,如下圖。
一般在開發過程中,可以結合這兩個工作使用,簡單的查看commit信息可以使用tig,要進行一些複雜操作或者搜索可以使用gitk。
Android Studio
Version Control
Version Control是AS自帶的類似gitk一樣的版本管理工具,其功能非常強大,這裏只是簡單的介紹其基本使用。
使用方式:
點擊View菜單,選擇Tool Windows中的Version Control,此時AS底下菜單欄會出現Version Control菜單,點擊即可使用
使用效果如下:
- Log頁面
在Log頁面選中一條修改記錄後,右側會顯示出對應修改過的文件,雙擊文件可打開該次提交修改了什麼內容,如下。
- Local Change頁面
其他的就不再介紹了,讀者可以自己體驗下,這裏再介紹下使用Version Control解決代碼衝突的使用。
當有本地提交與外部提交衝突時,點擊Version Control中的Local Changes可以看到如下界面:
點擊自己解決衝突時,會出現如下頁面:
根據代碼情況,修復好衝突後,Version Control會自動將文件加入暫存區,需要自己提交commit即可。Version Control可以極大程度減少衝突帶來的不適感,能夠大大提升解衝突的效率,推薦讀者使用。
Annotate
Annotate用一句話來總結就是,能讓你簡單直接明瞭的看到每一行代碼是由什麼人在什麼時候因爲什麼修改的,而且還能很方便的知道當時修改了哪些文件,而哪些文件已經不存在了。
使用方式:
打開文件, 左側空白處右鍵,打開Annotate,選擇一個commit雙擊查看
效果如下:
左側可以看到包括commit id,作者,日期,commit message和changeId等信息。雙擊後會彈出新的窗口,這個窗口裏顯示出了本次提交修改了那些文件,雙擊一個文件則顯示本次這個文件修改了那些內容。
注:你在不同的log上點擊Annotate的話,得到的是不同的結果,即每次顯示的是那個版本的文件的信息,以及那個文件包括的內容的各行修改歷史。
Local History
Local History是AS中內置的一個版本管理工具,能記錄12h內操作的文件,方便我們追溯一些丟失的代碼。
使用方式:
1. 右鍵自己的項目,點擊Local History下的Show History
2. 選擇具體文件,右鍵點擊Local History下的Show History
使用展示如下:
有了這樣的工具,就可以避免在進行一些git操作或者是文件操作時把辛苦寫好的代碼誤刪除的風險。