Git本身是一個命令行的工具,因此,掌握Git命令成為我們使用Git版本控制的第一道障礙。好在常用的Git命令只有幾個,並且參數都比較簡單,因此,我們會很容易地跨越這個障礙。而剛開始就直接使用GUI工具並不是我們推薦的方式,因為使用GUI不僅效率慢,還會使得你根本不了解Git本身的工作機制,一旦出現問題你將不能手動進行解決。因此,要使用GUI也要建立在能夠熟悉Git基本命令的前提下。
1、進行版本控制的第一步—Git init使用Git進行版本控制的第一步就是通過在你的項目根目錄執行Git init命令,該命令會在你的根目錄下創建了一個隱藏的.Git目錄,該目錄中包含了該項目在Git中的相關配置和信息,Git就是根據裡面的數據對你的項目進行版本控制。例如,我們在git-project根目錄運行git init命令,然後再查看根目錄下的文件,結果如圖8-6所示。
▲圖8-6 初始化項目
2、常用的版本控制命令—Git status在初始化了需要版本控制的項目之後,我們就可以繼續進行後續的工作。在我們使用Git進行版本控制的過程中,Git status命令是我們最為常用的命令之一,它用於檢查本地項目的狀態。現在我們就來學習該命令,首先我們在git-project項目中創建一個新的文件,我們命令為SayHello.java,它的功能就是輸出Hello字符串。然後執行Git status命令,如圖8-7所示。
▲圖8-7 查看項目狀態
此時我們看到在命令行中給出了一些提示信息,比較顯眼的就是紅色區域(運行中可看到)的SayHello.java文件。咋一看會覺得不知所措,下一步到底要做什麼呢?但是仔細看上面的提示我們會發現一些關鍵的信息,在SayHello.java的上、下一行都含有有用的信息,例如,SayHello.java上一行是use git add <file> … to include in what will be commited。這就是告訴我們下一步可以使用Git add 命令將下面的文件添加到下次要提交的文件列表中。因此,我們下一步要做的就是執行Git add 命令。
3、添加到追蹤列表中—Git addGit add 命令的作用是將一個或者多個文件添加到Git追蹤列表中,只有通過Git add 添加了的文件才會被版本控制管理。從上面的Git status中得知,我們下一步要做的就是Git add命令。Git add命令並不像Git init 、Git status這樣的無參數命令,完整的命令參數複雜,我們只說最常見的兩種用法。一種用法是添加某個文件,另一種是添加某個目錄下的所有文件。示例如下:
git add SayHello.java # 添加SayHello.java這個文件gitadd . # 添加當前目錄下的所有文件
通常由於Android的項目文件比較多,一次性可能會修改多個文件,因此,最為常用的也就是Git add .命令,一次性將所有文件都添加到下次要添加的列表中。執行該命令之後我們再次執行Git status命令查看當前狀態(執行完一些重要命令之後通過Git status查看狀態應該是你使用Git的習慣,這樣避免出現遺漏等問題)。如圖8-8所示。
▲圖8-8 追蹤文件並查看狀態
執行Git add命令之後可以看到當前項目的修改已經被提交,項目狀態變成了前文說的staged(已暫存)狀態,此時SayHello.java會在下次提交時被提交到本地倉庫。需要注意的是,Git add 命令並不是執行一次就可以的,每次修改項目中的內容之後你都需要執行Git add命令進行更新。
假設我們是誤操作將不需要追蹤的文件進行了add操作,那麼如何移除呢?答案還是仔細看Git status給出的提示信息,這也是Git體現人性化的一點,它會在你執行命令時給出下一個你可以要用到的命令,因此,查看Git狀態就變得更為重要。在圖8-8中我們看到一句提示: use 「git rm –cached <file>…」 to unstage 。意思是我們可以通過git rm –cached 命令將文件從追蹤列表中移除,不用擔心,這個命令不會將你的文件從本地目錄刪除,而只會從你的Git追蹤列表中刪除,這樣在提交中就不會包含被移除的文件。
4、提交—Git commit執行Git add 命令之後,你的文件已經添加到追蹤列表。執行這個操作的時間節點應該是你已經完成了一個功能,並且想將這個功能提交到本地倉庫中。此時,還需要Git commit命令將你的改動真正的提交。Git commit命令格式如下:
git commit -m "這裡寫你的提交說明" # 形式1 : 通過-m提交簡短的信息git commit # 形式2 : 通過git commit提交,會跳轉到編輯器
使用形式1相對來說比較方便、快捷,但是,當你的提交信息有一定格式或者需要提交的文字內容較多時,使用形式2會是一個更好的選擇。執行Git commit之後,如圖8-9所示。
▲圖8-9 提交代碼
從圖8-9中可以看到,我們通過git commit -m 將這次修改添加到本地倉庫,提交信息為「add SayHello.java」。成功之後我們再通過git status查看狀態,得到的結果是「nothing to commit, working directory clean「。至此,我們就將這次修改提交到本地倉庫了。
5、查看項目歷史記錄—Git log有的時候我們需要查看某個項目的提交歷史,那麼我們可以通過Git log命令實現。該命令會列出所有的提交記錄,這些信息包括提交人、時間、信息,最重要的就是這次提交對應的信息指紋,也就是該項目的目錄和文件的整體SHA-1值,它代表了這次提交的唯一標識。我們在git-project項目中執行Git log,結果如下:
commit 07408ceedfa52473107efc7daa4d7af6c363e192 # 信息指紋Author: MrSimple <bboyfeiyu@gmail.com> # 提交人Date: Fri Aug 14 12:43:11 2015 +0800 # 時間 add SayHello.java # 提交信息
由於我們的項目就提交了一次,因此,也就是輸出了這次提交的相關信息。
6、下載程序—Git clone有的時候我們並不是自己創建項目,而是想要將別人的託管在網站上的開源庫下載到自己的計算機中,那麼此時我們就需要使用Git clone命令。該命令的作用正是將遠程項目下載到本地,命令的格式為:Git clone 遠程倉庫地址。例如,我們要將一個Android事件總線庫下載到本地,它的地址為git@github.com:bboyfeiyu/AndroidEventBus.git(網址在這裡為http://github.com/bboyfeiyu/ AndroidEventBus),那麼我們可以在命令行下執行如下命令:
git clone git@github.com:bboyfeiyu/AndroidEventBus.git
此時,Git就會從該地址下載這個項目,如圖8-10所示。
▲圖8-10 clone項目到本地
執行完成之後就會在當前目錄下創建一個AndroidEventBus目錄來存放這個開源庫,項目的所有文件都存放在這個目錄中。
7、不同分支—Git branch大家看圖8-8可以看到,在命令行的末尾總是顯示一個「master」,這實際上是我們所在的git-project項目分支名。當你初始化Git之後,默認會創建一個master分支,你的操作也默認會在master分支。不同分支的文件互不影響,因此,當你需要開發一個新的功能時,你可以新建一個新的分支,並且切換到該分支進行開發,當功能完成後你將該分支提交到本地,然後再切換回主分支,並且合併完成新功能開發的分支。例如,我們要創建一個新的類來實現網絡聊天,但是,這個我們沒有太大的把握能夠完成這個功能,為了保險起見,新建了一個net分支進行開發,如果完成了就將net合併到master分支,否則就切換回master分支,並且將net刪除。
首先我們通過Git branch 命名創建net分支,命令為Git branch net。
執行後效果如圖8-11所示。
▲圖8-11 創建net分支
通過Git branch命令可以到當前項目的所有分支,在未執行Git branch net之前我們只有master分之,執行之後我們新增了net分支。注意看master分支之前有一個星號,這代表你當前所處在的分支,目前,我們就處在master分支。那麼現在問題來了,我們是要切換到net分支進行開發,分支切換需要用到Git checkout命令。
8、籤出一個分支—Git checkoutcheckout命令的作用是籤出一個分支或者一個路徑。在開發中常用於分支切換和恢復文件。分支切換命令格式為:
git checkout 分支名
執行命令之後就會切換到指定的分支上,如圖8-12所示。
▲圖8-12 切換分支
從圖8-12中可以看到,此時星號目前在net前面,表明我們順利地切換到了net分支。這樣,我們就可以在net分支進行工作了,我們新建一個Chat.java類實現網絡聊天。此時,git-project的net分支就含有SayHello.java、Chat.java兩個文件。將Chat.java開發完成之後,我們依次執行如下2條命令將這次修改提交到本地倉庫:
gitadd .git commit -m "add Chat.java"
效果如圖8-13所示。
▲圖8-13 在net分支提交代碼
此時,net分支的網絡聊天功能就開發完成了,功能實現在Chat.java中。我們在net分支上的操作不會影響master分支,也就是說master分支目前還是只有SayHello.java一個文件。假設現在經過測試,我們的網絡聊天功能出現了驗證的Bug,並且不能夠被修復,我們只好放棄net分支。那麼此時我們可以先checkout回到master分支,然後使用git branch -d 命令刪除net分支。依次執行兩條命令:
git checkout master git branch -d net
此時master分支還是只有一個SayHello.java文件,net分支的開發對於master沒有產生影響。如圖8-14所示。
▲圖8-14 master分支
checkout的另一個常用的功能是將文件恢復到修改之前的狀態。例如,SayHello.java的源碼在修改之前如下:
public class SayHello { public static void main(String[] args) { System.out.println("Hello"); }}
現在需要加一個複雜的功能,經過一輪Coding之後,SayHello.java的代碼可能已經變得面目全非,而且由於代碼過於混亂,使得原來正確的代碼也變得不可用,以前與今天的工作都白幹了,此時你兩眼早已飽含熱淚。修改後的SayHello.java代碼如下:
public class SayHello { private static void eat() { } public static void main(String[] args) { System.out.println("Hello"); } private static void sleep() { }}
如何才能回滾到SayHello.java修改之前的狀態呢?
還好,Git checkout提供了這樣的功能。我們使用如下命令將SayHello.java恢復到修改之前的狀態:
-- .
此時,SayHello.java就從已修改狀態變為最初的版本了。
9、合併分支—Git merge在上一節中我們切換到net分支開發了網絡聊天功能,假設開發成功了,那麼我們需要將網絡聊天功能合併到master分支,也就是我們要將net分支合併到master分支。需要用到的命令為Git merge。我們在net分支提交代碼之後,切換到master分支,並且執行Git merge net命令,如果沒有衝突,那麼master分支將會和net分支合併。如圖8-15所示。
▲圖8-15 合併net到master分支
此時,Chat.java就被合併到master分支了,master分支也就有了網絡聊天的功能。
10、解決衝突在Git merge中沒有提到,如果沒有衝突才會自動合併,否則將會提出哪些文件產生了衝突。產生衝突的原因是因為有多個開發人員修改了同一個文件的相同地方導致,使得Git系統不知道使用誰的代碼,此時就需要開發人員自己來抉擇,選擇其中一份代碼,並且將其他的代碼刪除。
假設研發-A和研發-B兩位同事同時開發網絡聊天功能,因此,他們同時修改了Chat.java文件的eat函數。研發-A首先提交了代碼到線上的版本控制系統,然後研發-B此時從線上系統更新代碼下來,此時就會產生衝突。當然,在不同分支之間切換開發也可能導致發生衝突,或者說只要是代碼合併的操作都有可能出現衝突,原因也是同時修改了文件中的同一處代碼段。例如Chat.java的原始代碼為:
public class Chat { public static void main(String[] args) { System.out.println("Chat with me"); }}
研發-A在master分支上修改了Chat.java的main函數的第一行代碼,代碼如下:
public class Chat { public static void main(String[] args) { System.out.println("Chat with me, I'm RD-A."); }}
研發-B在net分支也修改了同樣的地方,代碼如下:
public class Chat { public static void main(String[] args) { System.out.println("我和研發-A的代碼不一樣."); }}
此時,研發-B提交代碼到線上系統之後,研發-A將net分支代碼同步到本地,並且將net分支通過Git merge合併到master分支。此時就會引發衝突,如圖8-16所示。
▲圖8-16 產生衝突
從圖8-16中可以看到,圖中指出自動合併失敗,Chat.java產生了衝突。我們看看此時Chat.java文件中的內容是怎樣的:
public class Chat { public static void main(String[] args) {<<<<<<< HEAD System.out.println("Chat with me, I'm RD-A.");======= System.out.println("我和研發-A的代碼不一樣.");>>>>>>> net }}
其實很容易看懂這份衝突的文件,它的意思是,在System.out.println()語句這裡出現了多份代碼,Git不知道如何解決。在我們的示例中,在「<<<<<<< HEAD」與「=======」之間的是研發-A的master分支的代碼,而「=======」與「>>>>>>> net」則是研發-B的net分支中的代碼。這兩份代碼到底要哪一份,這需要你來裁決,因此,給出了衝突提示。假設研發-A的代碼是正確的,那麼需要將「=======」與「>>>>>>> net」之間的代碼刪除,並且將「<<<<<<< HEAD」、「=======」、「>>>>>>> net」這些衝突標識也刪除。最終代碼如下:
public class Chat { public static void main(String[] args) { System.out.println("Chat with me, I'm RD-A."); }}
此時,衝突就已經被處理了。重新Git add和commit提交代碼即可。
11、為版本打一個標籤—Git tag在完成了所有功能、並且經過測試之後,我們通常會為這個版本打一個標籤,這是一個非常重要的功能,建議大家為每個正式發布的版本都創建一個標籤,這樣便於後續的版本檢索與維護。通常一個標籤就代表了一個正式版本,通過Git tag命令就可以列出當前項目的所有標籤。新建一個標籤的常用命令如下形式:
git tag -a v1.0 -m "這裡寫相關信息"
上述命令新建了一個名為v1.0的tag,然後再次運行Git tag命令列出所有標籤,得到的結果如圖8-17所示。
▲圖8-17 新創建tag
我們也可以通過「git tag -d 標籤名」來刪除tag、「git show 標籤名」的形式來查看該分支的具體信息,例如執行git tag v1.0,得到的結果為:
tag v1.0Tagger: MrSimple <bboyfeiyu@gmail.com>Date: Sat Aug 15 08:11:56 2015 +0800版本1.0commit c97418b2a93226296ad0cc4c45b930562ce4261dMerge: 026ca26 1490b54Author: MrSimple <bboyfeiyu@gmail.com>Date: Fri Aug 14 14:40:26 2015 +0800解決了衝突
當我們的項目託管在遠程倉庫(如Github)時,我們可以將標籤通過Git push命令推送到線上,也可以通過Git pull命令將標籤從遠程倉庫上下載下來。這些功能我們將在後面的章節中為大家演示。
12、幫助文檔—Git help本章我們講述的都是常用命令的簡單格式,為了避免引入過多的複雜性命令的其他用法,我們並沒有全部演示出來。在日常開發中,我們也只會運用到那些基本的命令、形式,而當你想詳細了解某個命令時,你可以使用Git help命令來獲取完整的使用說明。例如,查看Git tag命令的使用說明可以執行Git help tag命令,得到的結果如下:
NAMEgit-tag - Create, list, delete or verify a tag object signed with GPGSYNOPSISgit tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]<tagname> [<commit> | <object>]git tag -d <tagname>http://www.worldhello.net/gotgithub/.git tag [-n[<num>]] -l [--contains <commit>] [--points-at <object>] [--column[=<options>] | --no-column] [<pattern>http: [<pattern>http:git tag -v <tagname>http:DESCRIPTION Add a tag reference in refs/tags/, unless -d/-l/-v is given to delete, list or verify tags.OPTIONS
重點我們就看上述4項即可,NAME中描述的是Git tag命令的作用簡介,SYNOPSIS則是該命令的參數簡介,DESCRIPTION是該命令的功能與相關參數的介紹,OPTIONS則是各參數的含義。通常只需要查看這幾項說明就能找到所需的功能。
本文摘自《Android開發進階:從小工到專家》,作者:何紅輝
本書是一本專門介紹Android開發的圖書。書中首先對Android開發的核心知識點進行深入講解,然後介紹單元測試、代碼規範、版本控制、重構、架構等重要的知識,使得讀者在深入掌握技術的同時也幫助他們開闊眼界,且能夠以更專業的方式設計應用軟體,完成從只會實現功能的初級程式設計師到軟體工程師、設計師的轉變。
本書的主要內容為:構成Android系統基石的四大組件、創造出豐富多彩的UI設計的控制項、保證App流暢的多線程開發、必知必會的HTTP網絡請求應用、數據存儲的核心SQLite資料庫、讓程序更優秀的性能優化、讓程序更整潔的代碼規範、管理程序的好幫手Git版本控制,以及需要掌握的高級技術,如單元測試、六大原則與設計模式、重構和綜合實戰等。
本書適合Android開發初學者、程式設計師學習,也適合作為大中專院校相關專業的師生用書和培訓學校的教材。
本來自:異步社區
推薦公眾帳號:人郵IT書坊(ptpressitbooks)
一個專門為程式設計師推薦好書的地方,經常有乾貨分享,贈書福利常常有。