Repository git
使用GIT管理一個項目的時候,就須要一個倉庫(repository)用於存放GIT對項目管理所必需要保存的各類文件,使用 git init 命令建立一個新的倉庫。GIT會在當前目錄下建立一個.git文件夾,用做倉庫。而後,當你使用GIT記錄每一次代碼改動的時候,GIT就會把須要的信息都放到這個文件夾下面。
github
Commit 算法
每當你完成一個改動(change)的時候,就能夠commit一下,記錄當前項目的狀況(snapshot)。每個commit包含以下信息:
- commit-id(sha-id):這是一個經過sha-1算法算出來的一個id,它不僅做爲每一個commit的惟一識別碼,也能夠用來驗證保存的代碼是否損壞。因此在GIT在管理代碼的時候,若是發生代碼損壞,能夠頗有效的檢測到。
- author:做者
- date: 日期時間
- log messge:一段做者對代碼改動的文字描述。
- change-id:若是是和repo、gerrit一塊兒使用的話,repo會加上這個信息,以便在整個代碼系統中識別同一個改動的多個版本。
用代碼管理軟件管理代碼的時候,有個理念就是:每次改動提交之後,整個項目都應該是能夠工做的。因此,每次commit最好都能是這樣的的改動,雖然這不是必須的,可是這樣對項目總體質量的提升頗有好處。
在GIT使用中,一個change開發的常見工做流程大概是這樣的:
- 新建一個工做分支(topic branch)
- 做一些代碼改動
- 查看當前狀態(很經常使用!):git status 查看當前branch以及那些文件有改動;git diff 查看目前爲止的詳細的改動狀況。
- git add xxx 將這些改動暫時歸檔。在不少時候,一個change包含的東西並很多,咱們在作到一半的時候一般也須要暫時保存一些東西。使用git add會將指定的文件的現有改動暫時保存下來(這個暫時歸檔的地方,GIT稱它爲staging area,能夠認爲是一個臨時的snapshot。順便說一下HEAD,在GIT中,HEAD老是指向項目當前狀態最近的一次正式的snapshot。)。git add . 會將全部改動暫時歸檔。
- git reset xxx 將某個文件從staging area中移出來。git reset 不帶參數的時候,就是將staging area中全部的文件移出。
- 查看staging area中的詳細改動:git diff --cached
- 繼續寫代碼,git add xxx 將新的改動歸檔。
- 當你發現你的改動很是不合理,想要取消這些改動的時候:git checkout xxx 將某個文件恢復到修改以前(最後一次snapshot)。git checkout . 會恢復全部的文件到修改以前的狀態,很方便的功能,但使用的時候必定注意,不要讓本身的心血付諸流水。
- 重複上面的步驟,直到你認爲你的改動已經能夠做爲一個有效的change,那你就能夠執行 git commit 來將當前的改動真正的保存下來。記得在commit message裏面寫上適當的描述信息,這樣在查看代碼歷史的時候,就能方便的知道每一個change都幹了些什麼。
- 有時候,你commit之後,你還發現還有須要修改的地方(特別是讓別人review的話,commit以後須要屢次改動也是很常見的事情),那麼你就重複上面的步驟,不過在最後commit的時候加上 --amend 參數,這樣,它就會將目前的修改內容添加到最近的一次commit。若是忘記/誤用了 --amend 參數的時候怎麼辦呢?只要在編輯commit message的時候把內容所有清空,保存退出,GIT就會放棄此次commit。
- 根據狀況,將這個改動合併(merge)回原來的主分支
Tag
在git中,每個commit都是一個項目當時的snapshot,tag的做用就是給commit打上標籤。好比你當項目進行到某一點,你以爲能夠發佈(release)一下,那你就能夠在這個位置作一個標記,打一個tag,一個發佈點就被明確的標示出來了,這樣能夠方便的對項目的狀況進行管理。我一般把它理解爲某個commit的別名。GIT對項目的版本管理一般就是在這裏體現的。因爲tag一般是用於項目發佈管理的,因此一般是項目管理人員來使用它。
查看tag狀況:git tag
新建一個tag:git tag <tagname> <commitid>
刪除一個tag:git tag -d <tagname>
查看幫助:git tag -h 服務器
Branch
GIT最方便的莫過於本地分支(branch)的使用了。就開發來說,你須要嘗試你的各類想法,就發佈項目來講,不一樣的
branch可讓你有效的管理各個版本軟件的發佈以及維護。這裏只說說開發。
查看
branch:
git branch命令就能夠查看本地當前的全部
branch。經常使用的參數有:
-r 查看遠程(remote)的branch
-a 查看(本地+遠程)全部branch
-v 查看
branch的時候顯示每一個
branch的最後一個commit信息
跳轉到一個
branch:
你任什麼時候候只能在某一個branch上面,或者某一個特定的snapshot。
git checkout branchname 跳轉到某一個branch
git checkout sha1/tag 跳轉到某個指定的snapshot,這是你不在任何一個branch上面。
新建一個
branch:
git branch newbranch 從項目當前所在的commit建立一個branch
git checkout sha1/tag -b newbranch 從某一個指定的snapshot建立一個新的branch,並跳轉到新建的branch
git checkout remote_branch -b newbranch 以某個遠程branch最新的一個snapshot爲基礎建立一個新的branch,注意這不會影響遠程
branch,由於他的實質和上面實際上是同樣的。
那麼咱們該如何使用
branch呢?首先,你要知道GIT是個分佈式的代碼管理工具,在你沒有和遠程代碼倉庫交流的時候,你的任何改動都是本地的,不用擔憂影響到遠程代碼倉庫。而你只要不刻意去破壞你本地的倉庫,那麼,就大膽的使用
branch吧,作各類嘗試。任什麼時候候你有一個新的想法,在本地建一個
branch盡情的去嘗試,很快你就會喜歡上這東西的。
若是是個多人協做項目的話,一般你的工做並不僅是改動一個地方,那麼當你完成了某一個change正在等待review的時候,你就能夠新起一個branch,接着就開始你的另外一個change了。
Merge
有了分支你就能夠盡情的作各類嘗試,爲所欲爲的寫代碼。但咱們一般是有一個主幹分支,而後咱們把每一個成熟的改動的合併(merge)到咱們的主幹,這樣,項目才真正有效的在前進。這個工做流程就完美的解決了多人協做開發項目的問題:由於每一個人都是在本身的本地工做區進行修改,互不影響,在完成後將本身的成果放進主倉庫(某個remote repository)就能夠了,最壞的狀況就是可能會有些代碼衝突,但代碼衝突一般並非什麼很難解決的問題:畢竟在分配任務的時候就會有大體進行安排,因此通常是不會有什麼沒法解決的衝突。
說到merge的話,不少時候有人就會和rebase搞混。雖然兩個命令的功能都是把兩個branch合併起來,可是仍是有很大差異的。
rebase主要用於以下情形:在多人協做的項目中,當你完成了一個改動之後,你發現別人已經在遠端主代碼倉庫添加了不少改動了,這時候極可能會有代碼衝突,或者已經有代碼衝突,那這時候,你就須要把你當前的工做branch更新到最新的狀態,而後解決代碼衝突,而後再提交你的change。這時候,你就:
- 從遠端獲取最新的代碼
- git rebase xxx 更新你當前的branch到最新狀態,而後把你的代碼改動放在最上面
- 向遠端提交代碼
而merge的話,就只是簡單的將兩個branch合併,若是出現GIT沒法處理的衝突的時候,那麼就先採起上面的步驟,而後在merge。在Android的工做環境中,咱們一般是不須要使用merge這個操做的,這個操做是在gerrit裏面完成review之後,點merge按鈕來完成的。
查看歷史
最經常使用的查看項目歷史(其實是某個分支的歷史)的命令就是git log,常見用法以下:
- git log 查看項目從當前位置(最近一個snapshot)以前的歷史記錄。能夠這麼來理解:當你在某個branch上面的時候,這個snapshot就是當前分支的最新的一個comit,當你不在一個branch上面的時候,就是當前狀況下最新的那個commit。
- git log shaid/tag 同上,不過指定了snapshot的位置
- git log file_name 同上上,不過查看的是特定文件相關的改動記錄
- git log branch 查看特定branch的歷史記錄
- git log branch file_name 同上,不過查看的是特定文件相關的改動記錄
- git log --no-merges 因爲GIT在進行merge的時候,會自動生成一個merge的commit,但其實這個commit自己是沒有內容的,--no-merges這個參數的做用就是在查看log的時候忽略這種commit。
這個命令能夠知足大部分須要查詢歷史記錄的狀況,但有時候,你須要一個更強大的工具,那就是GITK。在當前branch下面,使用gitk命令,就可使用gitk查看當前項目狀態以前的歷史記錄。它是一個有界面的工具,基本上是一目瞭然的,因此我也不過多的介紹,花幾分鐘去試試它吧。
Remote
GIT既然是分佈式代碼管理工具,那麼就必然涉及到遠程的交互了。GIT和遠端的交互能夠經過常見的HTTP、HTTPS,在比較正式的項目中,一般是基於SSH的GIT協議。
以github.com爲例,上面支持3種方式:
在Android系統的管理中,因爲和服務器的交互都是封裝在repo這個工具裏面,因此,一般是不須要用到remote操做的。因此只簡單說一下:
git remote 查看當前已添加的遠程服務器
git remote -v 同上,不過顯示更詳細的信息
git remote -h 查看幫助
其餘
.gitignore
在開發一個項目的時候,有時候總會有些項目無關的文件,好比bin文件夾下面的內容,通常是不須要用GIT管理起來的。這時候,你就把這些文件的信息寫到.gitignore裏面,而後,把.gitignore的改動使用GIT管理起來,這樣,GIT在查詢狀態的時候,就會忽略在.gitignore裏面提到的文件。
color & alias
GIT能夠給各個命令的輸出結果加上適當的顏色以提升視覺識別度,只須要簡單的配置便可。若是你嫌有些GIT命令太長,每次打完太麻煩,不要緊,有辦法,添加別名。
所以我一般會在個人/etc/gitconfig文件中加入以下的內容:
[color]
ui = auto
[alias]
st = status
cm = commit
cma = commit --amend
br = branch -v
cp = cherry-pick
co = checkout
df = diff
dfc = diff --cached
如何使用alias:以第一個爲例,當我想用git status的時候,我打git st就能夠了。
小結
GIT的功能很豐富,上面說的這些不過是一些經常使用的功能而已,要想把每一個細節都說清楚的話,還遠遠不夠。想要用好GIT,還須要在實際運用中進行實踐和進一步學習。