本篇主要講Git 的一些基礎(chǔ)和一些在開發(fā)中比較常用的命令。比較適合初學(xué)和快速了解Git。

Git文件分類
Git中的文件分為三類:已追蹤的(Tracked)、被忽略的(Ignored)、未追蹤的(Untracked)。
已追蹤的(Tracked):是對(duì)文件進(jìn)行過git add xxx 操作的文件。
被忽略的(Ignored):在版本庫中聲明為不可見或者被忽略的文件??梢杂脕碇付ê雎宰粉櫮骋惶囟ㄎ募蚝雎阅骋活愇募?。Git允許在版本庫中任何目錄下有.gitignore文件,每個(gè)文件都只影響該目錄及所有其子目錄。配置忽略文件:
$ cd my_package
$ cat .gitignore
*.o
這樣Git會(huì)忽略所有版本庫中所有的.o文件。但有時(shí)需要追蹤被忽略中特定的文件,可以這樣進(jìn)行配置:
$ cd my_package/vendor_files
$ cat .gitignore
!driver.o
這樣vendor_files子目錄下的driver.o文件就會(huì)被追蹤了。
未追蹤的(Untracked):不是已追蹤的和被忽略的就是未追蹤的。可以將Git工作目錄所有文件看成一個(gè)集合,去除已追蹤的和被忽略的,那就剩下未追蹤的了。
Git add
git add 將一個(gè)未追蹤的文件轉(zhuǎn)成已追蹤狀態(tài),如果是git add作用文件夾,那文件夾下的所有文件都會(huì)被追蹤。使用git add時(shí)可以先用git status 查看文件狀態(tài)。
Git rm
與git add 命令相反,從工作目錄和索引中刪除一個(gè)文件,并不會(huì)刪除該文件在版本中的歷史記錄。
Git commit
git commit 把文件從stage提交到branch;git commit -a 把修改的文件先提交到stage,然后再從stage提交到branch。使用git commit -a 包括提交自動(dòng)暫存的文件和新增未追蹤的文件 還有從工作副本中刪除已追蹤的文件。
Git log
提交完成后,可以使用git log 查看提交歷史記錄,每次提交都會(huì)有唯一的40位16進(jìn)制SHAI提交ID(顯示引用),無論提交處于版本庫歷史中的任何位置,哈希ID都對(duì)應(yīng)相同的提交。
Git bisect
git bisect 命令是一個(gè)強(qiáng)大的錯(cuò)誤查找工具,基于任意搜索條件查找特定的錯(cuò)誤提交。當(dāng)發(fā)現(xiàn)版本庫中有問題,而之前是好的,就可以使用git bisect 命令了。其實(shí)就是當(dāng)測(cè)試說程序這里發(fā)現(xiàn)bug了,WT? 但之前明明是好的啊。這種情況就可以用git bisect 來檢查了。
git bisect 原理是通過二分法來查找產(chǎn)生問題的提交。使用之前你需要確定代碼在哪次提交前是沒問題的,和代碼哪次提交已經(jīng)出現(xiàn)問題了(一般就是當(dāng)前的HEAD)。即確定一個(gè)good點(diǎn) 和一個(gè)bad點(diǎn),然后重復(fù)回答這個(gè)版本是否能未出現(xiàn)問題,直到確定問題所在的提交為止。流程演示:
1、進(jìn)入git工作區(qū)間

2、使用git log 查看所有歷史提交

在上面這個(gè)版本庫中現(xiàn)在假如在最后一次提交時(shí)出現(xiàn)問題了,但是我確定在 “create project” 之前是沒問題的。
現(xiàn)在來確定出現(xiàn)問題的commit。
3、按順序執(zhí)行下面命令
// 開始使用bisect
git bisect start
// 設(shè)置目前的版本是壞的,已經(jīng)出現(xiàn)問題
git bisect bad
// 設(shè)置“HEAD~5” 提交之前是好的
git bisect good HEAD~5

HEAD~5 是怎么獲取到的呢?在輸入git bisect good 時(shí)按tab鍵會(huì)有提示,里面HEAD~5對(duì)應(yīng)的就是create project提交。HEAD~5其實(shí)表示的是提交范圍(相當(dāng)于游標(biāo))。
4、開始查找出錯(cuò)提交
輸完上面命令后如下:

現(xiàn)在只要一直輸入 git bisect good/bad 確定出現(xiàn)提交的“好” “壞”。我上面的是“修改ViewController.h” 這次提交,提交這次后是沒有問題的,所以輸入git bisect good

命令行會(huì)再出現(xiàn)某一次的提交供你判斷?!靶薷腁PPDelegate.h” 這次提交也是沒有問題的。繼續(xù)輸入git bisect good。

5、確定出先問題提交
出現(xiàn)上面的信息就可以知道使用git bisect 已經(jīng)確定了出問題的提交了。“修改info.plist” 這次提交出現(xiàn)問題,修改人員和時(shí)間信息都有。
使用git bisect 其實(shí)是在一個(gè)新的分支上進(jìn)行的,不用擔(dān)心對(duì)當(dāng)前版本有干擾,輸入git branch 查看當(dāng)前分支。

其實(shí)在命令行中 紫色git 后面的括號(hào)中就是當(dāng)前分支(因?yàn)槲沂怯昧?a href="http://m.itdecent.cn/p/9ea9123aa9bb" target="_blank">Oh My Zsh 命令行擴(kuò)展工具)。
Git 分支
分支是軟件項(xiàng)目中啟動(dòng)一條單獨(dú)開發(fā)線程的基本方法。
分支主要的應(yīng)用情景:
1、項(xiàng)目需要開始一個(gè)新版本,假如為1.1,但需要保留1.0的版本,開新分支作為一個(gè)新的1.1版本。
2、封裝開發(fā)階段。項(xiàng)目要發(fā)布時(shí)進(jìn)行測(cè)試、維護(hù),可以新開一個(gè)分支作為測(cè)試或維護(hù)版本。
3、在研究復(fù)雜的功能或者復(fù)雜的bug時(shí),可以開一個(gè)分支,來完成一個(gè)孤立任務(wù),完成后合并即可。
git init 初始化的時(shí)候默認(rèn)會(huì)有一個(gè)主分支master ,在取分支名時(shí)需要注意一些規(guī)則。分支名不能以“/”斜線結(jié)尾,不能以“-”減號(hào)開頭,分支名不能包含“..”兩個(gè)連續(xù)的點(diǎn),不能有空格,不能含有特殊含義的字符(包括 ~ ^ : ? * [ ) 。
分支使用:
查看分支(獲取分支列表): git branch ? 也可以使用 git show-branch查看更詳細(xì)的輸出。

* 星號(hào)后面就是當(dāng)前分支,因?yàn)楫?dāng)前版本庫中就只有一個(gè)主分支master,所以就列出了一個(gè)maser。
創(chuàng)建分支: git branch branchName(創(chuàng)建的分支名) ,創(chuàng)建完成后可以使用git branch查看。

可以看到新的分支已經(jīng)創(chuàng)建好了。如何檢出(切換)分支呢? 可以使用git checkout branchName切換。檢出完成使用git branch 查看當(dāng)前分支。

在檢出分支時(shí)可能會(huì)遇到有未提交更改的情況,當(dāng)前分支下對(duì)文件做了更改,但未提交,Git不會(huì)刪除和修改這些文件。但是如果一個(gè)文件的本地修改和新分支上的更改不同時(shí)(修改同一文件發(fā)生沖突),Git會(huì)發(fā)出錯(cuò)誤信息,拒絕檢出目標(biāo)分支。
先使用git status 查看當(dāng)前分支的文件更改。

可以看到我對(duì)UserInterfaceState.xcuserstate和ViewController.m做了修改,使用Oh My Zsh直接可以看出,當(dāng)前分支newBranch后有叉就代表有修改未提交的文件,挺好用的。然后進(jìn)行檢出master,再使用git status 查看。

可以看出修改的文件已經(jīng)到我們檢出的master分支下了,然后再根據(jù)需求在提交的分支進(jìn)行提交git commit -a。
合并分支: git merge branchName ?將branchName分支合并到當(dāng)前分支。


多個(gè)分支時(shí),合并分支有時(shí)會(huì)出現(xiàn)合并沖突,可以看下這篇《git 合并沖突處理》。
Git diff
可以比較兩個(gè)項(xiàng)目狀態(tài)的所有不同。git diff 命令進(jìn)行比較時(shí),可以通過提交名、分支名和標(biāo)簽(tag)進(jìn)行比較。SVN和Git在產(chǎn)生diff中就存在差異,diff和patch在Git中是導(dǎo)出的數(shù)據(jù),SNV和CVS中是基本數(shù)據(jù),進(jìn)入.git .svn就可以看出.git中是沒有diff文件的,但是.svn會(huì)有大量的diff文件,有興趣的可以去了解一下。4種基本比較方法:
1、git diff 顯示工作目錄和索引(stage)的差異
2、git diff commit 顯示工作目錄和給定提交間的差異,其中的commit可以用HEAD(提交游標(biāo))或者用分支名代替。
3、git diff --cached commit 顯示索引變更中和給定提交中變更差異。
4、git diff commit1 commit2 指定兩個(gè)提交,會(huì)顯示這兩個(gè)之間的差異。

Git 變更提交
變更提交主要有三種方式:reset ? checkout ?revert,說一下這三種方式的不同和應(yīng)用吧:
git checkout 上面提到過,用來切換不同的分支,切換完成后,當(dāng)前分支和HEAD引用會(huì)變?yōu)榻o定分支的頭。
git revert 重新創(chuàng)建一次新的提交提交 來撤銷某一次提交,作用于全部提交,而不是文件。在使用git revert時(shí),對(duì)提交的歷史是沒有影響的,而是相反往歷史記錄中添加新提交。
git reset 簡(jiǎn)單來說是直接回退到某次提交時(shí)的狀態(tài),具體內(nèi)容比較多,所以單獨(dú)寫了一篇 ? 傳送門
Git tag
git tag tagName // 創(chuàng)建tag
在使用git reset 時(shí),可以用tag代替提交哈希id
git reset --hard tagName ?// 回滾到某一次提交
git show tagName // 查看標(biāo)簽詳細(xì)信息
git tag -d tagName // 刪除標(biāo)簽
給指定提交加標(biāo)簽
git tag -a tagName 提交哈希id
這篇就介紹這么多了,還有一些 比如:補(bǔ)丁、鉤子、git filter-branch、結(jié)合SNV版本庫使用Git,有時(shí)間會(huì)繼續(xù)更新。