本文翻譯自Understanding Git Source Control in Xcode (譯者myShire)歡迎您加入我們的翻譯小組缸濒。
在應(yīng)用程序開(kāi)發(fā)過(guò)程中妇拯,很重要的一部分工作就是如何進(jìn)行源碼的版本控制。當(dāng)代碼出現(xiàn)問(wèn)題時(shí)脓钾,我們就需要將代碼恢復(fù)到原先正常的版本售睹。如果是多個(gè)人共同開(kāi)發(fā)一個(gè)項(xiàng)目,那么代碼的控制就會(huì)非常復(fù)雜可训。幸運(yùn)的是昌妹,開(kāi)發(fā)者不需要自己控制這些,因?yàn)橛袑iT(mén)的軟件來(lái)負(fù)責(zé)握截,叫做版本控制系統(tǒng)飞崖。
版本控制系統(tǒng),或者說(shuō)修改控制系統(tǒng)谨胞,實(shí)際上是一種檢測(cè)源文件的改變并將其保存留作以后參考使用的機(jī)制(軟件)固歪。此外,它還能記錄其他有用信息胯努,比如是哪個(gè)開(kāi)發(fā)者修改了代碼牢裳,何時(shí)修改的术瓮,修改了哪一部分,以及其他歷史信息贰健。版本控制系統(tǒng)可以比較不同版本代碼的不同胞四,有必要時(shí)能恢復(fù)整個(gè)項(xiàng)目到以前的版本,追蹤有害代碼從而減少產(chǎn)品的錯(cuò)誤伶椿。
通過(guò)版本控制系統(tǒng)辜伟,開(kāi)發(fā)者可以在一個(gè)項(xiàng)目的不同分支上工作,當(dāng)項(xiàng)目的各個(gè)部分開(kāi)發(fā)完備時(shí)脊另,將它們放到一起形成最終的版本导狡,這個(gè)過(guò)程被稱為合并。事實(shí)上偎痛,這種做法再團(tuán)隊(duì)和軟件公司中相當(dāng)常見(jiàn):每個(gè)人負(fù)責(zé)項(xiàng)目的一部分旱捧,最終所有部分被整合到一起形成最終產(chǎn)品。
對(duì)于個(gè)人開(kāi)發(fā)者來(lái)說(shuō)踩麦,版本控制系統(tǒng)并不是必需的枚赡,但是我們?nèi)匀粡?qiáng)烈推薦開(kāi)發(fā)者使用它,因?yàn)樗梢允勾a方便的在有錯(cuò)誤的版本和可以工作的版本之間轉(zhuǎn)換谓谦。事實(shí)上贫橙,很多開(kāi)發(fā)者從來(lái)不使用類似的工具,他們會(huì)在項(xiàng)目添加新的功能時(shí)手動(dòng)保存原先的項(xiàng)目反粥。這其實(shí)是一個(gè)很不好的習(xí)慣卢肃,因?yàn)榘姹究刂栖浖梢愿酶咝У赝瓿蛇@項(xiàng)任務(wù)。
Git是一個(gè)常見(jiàn)的版本控制系統(tǒng)才顿,它最開(kāi)始是由Liunx之父Linus Torvalds開(kāi)發(fā)的莫湘,Git使用虛擬目錄,又稱為repositories郑气,來(lái)管理一切事物幅垮。Git可以通過(guò)命令行調(diào)用,也有專門(mén)為它設(shè)計(jì)的桌面應(yīng)用軟件竣贪。如果Git對(duì)你來(lái)說(shuō)很陌生军洼,我建議你在網(wǎng)上查看一些它的相關(guān)信息巩螃。關(guān)于Git更深層次的內(nèi)容都不在本文的討論范圍之內(nèi)演怎。
從Xcode5開(kāi)始引入了使用git的一些新特性。它將git的各項(xiàng)功能整合到一個(gè)菜單中避乏,并提供子菜單來(lái)進(jìn)行軟件合并的控制爷耀。在接下來(lái)的閱讀中你會(huì)發(fā)現(xiàn),使用git來(lái)進(jìn)行版本控制相當(dāng)?shù)暮?jiǎn)單快捷拍皮。
我們接下來(lái)的任務(wù)就是學(xué)習(xí)如何在Xcode中使用git歹叮,以及Xcode是如何整合Git的各項(xiàng)功能跑杭。如果你覺(jué)得對(duì)這些很陌生,我建議你先上網(wǎng)搜索一下相關(guān)的內(nèi)容咆耿。在接下來(lái)的教程中德谅,我會(huì)假定你已經(jīng)了解了版本控制系統(tǒng)和git是什么,并將注意力集中在Xcode如何管理它上萨螺。
GIT Demo概述(GIT Demo Overview)
與其他教程中的demo app不同窄做,這次我們不會(huì)去實(shí)現(xiàn)一個(gè)應(yīng)用來(lái)演示某一項(xiàng)iOS SDK特性,最終我們也不會(huì)產(chǎn)生一個(gè)示例產(chǎn)品慰技。實(shí)際上椭盏,我們會(huì)新建一個(gè)demo工程,寫(xiě)幾行代碼吻商,然后利用這個(gè)工程來(lái)演示Xcode提供的版本管理功能掏颊。換句話說(shuō),我們會(huì)集中注意里于IDE上艾帐,而不是iOS本身乌叶。
我建議你跟著我一起一步一步實(shí)現(xiàn)這個(gè)實(shí)例項(xiàng)目,在相應(yīng)的地方手動(dòng)添加代碼柒爸,不用擔(dān)心枉昏,代碼量不是很多。跟著教程的步驟揍鸟,我們將執(zhí)行多種重復(fù)的版本控制相關(guān)的操作兄裂,并且我們必須實(shí)時(shí)看到結(jié)果。如果我只是提供了一個(gè)具備所有操作的的應(yīng)用阳藻,那么你無(wú)法體會(huì)到這些改變晰奖。
好了,廢話不多說(shuō)了腥泥,讓我們仔細(xì)看看使用Xcode進(jìn)行版本控制的要點(diǎn)吧匾南。
創(chuàng)建一個(gè)Git源(Creating a Git repository)
每次在Xcode中創(chuàng)建新工程的時(shí)候,都會(huì)提示開(kāi)發(fā)者是否將項(xiàng)目作為一個(gè)本地的git源蛔外。在創(chuàng)建工程的最后一步Xcode會(huì)有一個(gè)復(fù)選框蛆楞,如果選擇了它,git源就會(huì)被添加到工程目錄中夹厌。通常這個(gè)選項(xiàng)會(huì)被忽視豹爹,或是被認(rèn)為是Xcode的另外一個(gè)沒(méi)用的功能,尤其是從未用過(guò)git的開(kāi)發(fā)者矛纹,或是編程新手臂聋。
打開(kāi)Xcode,創(chuàng)建一個(gè)新的工程。選擇iOS區(qū)的“Application”孩等,在應(yīng)用模板頁(yè)選擇“Single View Application”艾君。
選擇下一步,在項(xiàng)目名中輸入GitDemo肄方,確保下面的Devices菜單選擇iPhone冰垄,無(wú)需iPad或者universal app。
點(diǎn)擊下一步权她,也就是最后一個(gè)步驟播演,在這里先選擇一個(gè)要保持工程的目錄,然后在窗口底部選上Create git repository on (My Mac ):
默認(rèn)情況下伴奥,這個(gè)選項(xiàng)是被選上的写烤,如果你不想使用git,你可以取消它拾徙,但是我不建議這么做洲炊。本教程中,你需要將它勾選上尼啡,然后點(diǎn)擊創(chuàng)建按鈕暂衡。
創(chuàng)建完項(xiàng)目之后,打開(kāi)Finder崖瞭,找到項(xiàng)目存儲(chǔ)的目錄狂巢,在目錄中,有一個(gè).git的子目錄书聚,時(shí)Xcode為存儲(chǔ)git源相關(guān)數(shù)據(jù)自動(dòng)創(chuàng)建的唧领。
如果你看不到.git目錄,你需要讓隱藏的文件可見(jiàn)雌续。具體做法就是打開(kāi)一個(gè)Terminal窗口斩个,輸入以下命令:
對(duì)于OS X Mavericks 10.9:
defaults write com.apple.finder AppleShowAllFiles TRUE
對(duì)于以前的OS X版本,
efaults write com.apple.Finder AppleShowAllFiles TRUE
為了重啟Finder應(yīng)用驯杜,輸入
killall Finder
這就是本項(xiàng)目在本地git源保存的位置受啥。實(shí)際上,如果你選上了相應(yīng)的選項(xiàng)鸽心,這個(gè)目錄就會(huì)被創(chuàng)建滚局。相應(yīng)地,在你創(chuàng)建新應(yīng)用時(shí)顽频,.git子目錄也會(huì)一同被創(chuàng)建藤肢。
顯然使用Xcode創(chuàng)建一個(gè)git源毫不費(fèi)力,然而冲九,如果你在項(xiàng)目創(chuàng)建時(shí)未創(chuàng)建git源谤草,之后又想加上這個(gè)功能怎么辦呢?好吧莺奸,其實(shí)你可以在任何時(shí)候?yàn)槟愕捻?xiàng)目創(chuàng)建源丑孩,但是不是使用Xcode。盡管這種情況很少發(fā)生灭贷,我還是會(huì)告訴你該怎么做温学。
如果你愿意的話,你可以直接跳到本教程的下一部分甚疟。我建議你接著讀下去仗岖,因?yàn)榻酉聛?lái)這些信息還是很有用的。
在進(jìn)行演示前览妖,你需要首先通過(guò)Xcode下載Command Line Tools轧拄,因?yàn)槲覀円赥erminal下操作,并且需要一些額外的工具讽膏。如果你還沒(méi)有下載檩电,那就去Xcode>Preferences…菜單,選擇Download選項(xiàng)卡府树,展開(kāi)Components區(qū)俐末,點(diǎn)擊Commond Line Tools右邊下載按鈕。下載完成后奄侠,一個(gè)對(duì)勾符號(hào)會(huì)取代下載按鈕卓箫。
現(xiàn)在,為這個(gè)例子再創(chuàng)建一個(gè)工程垄潮,完事后可以刪了它烹卒。在創(chuàng)建時(shí)取消那個(gè)創(chuàng)建git源的選項(xiàng)。這次我們不想讓Xcode為我們準(zhǔn)備一個(gè)源弯洗。把這個(gè)工程命名為NoGitExample甫题,保存到桌面,然后你可以跟我接下來(lái)輸入的命令一樣涂召。
一切準(zhǔn)備妥當(dāng)后坠非,打開(kāi)Terminal窗口(如果你之前打開(kāi)了一個(gè),那就先關(guān)掉它再重啟果正,從而使我們安裝的命令行工具生效)炎码。下面切換到新項(xiàng)目的目錄:
cd /Users/YOUR-USERNAME/Desktop/NoGitExample
別忘了在上邊命令中設(shè)置Mac的用戶名,接下來(lái)秋泳,輸入:
git init
這會(huì)初始化一個(gè)空的源潦闲,如果你在Finder里面查看或是輸入ls命令,你會(huì)看到.git子目錄已經(jīng)被創(chuàng)建迫皱,很好歉闰,接下來(lái)輸入:
git add .
這樣辖众,當(dāng)前目錄所有的內(nèi)容就被添加到源里面去了,最后和敬,輸入以下命令:
git commit -m 'Initial commit'
接下來(lái)會(huì)出現(xiàn)一個(gè)本地git源所執(zhí)行的改變列表凹炸,如下圖所示:
現(xiàn)在git源就建好了,但是如果你回到Xcode昼弟,打開(kāi)Source Control菜單啤它,你會(huì)發(fā)現(xiàn)一切仍然是被禁用。
這是因?yàn)楫?dāng)我們使用命令行工具創(chuàng)建git源時(shí)舱痘,Xcode并未被通知变骡,下面點(diǎn)擊Xcode>Quit Xcode,然后重新啟動(dòng)它芭逝,在NoGitExample項(xiàng)目中塌碌,如果你再次打開(kāi)Source Control菜單,你會(huì)發(fā)現(xiàn)所有的選項(xiàng)已經(jīng)被使能了旬盯,就像一開(kāi)始勾選上創(chuàng)建git源一樣誊爹。
現(xiàn)在這個(gè)項(xiàng)目的使命已經(jīng)結(jié)束,你可以在桌面上刪除它瓢捉。
現(xiàn)在你知道如何為你所有的項(xiàng)目添加git源了频丘,即使你在創(chuàng)建時(shí)沒(méi)有添加,你也可以在以后任何時(shí)候?yàn)樗謩?dòng)添加源泡态。
提交更改(Committing Changes)提交更改指的是儲(chǔ)存一個(gè)包含所有更改的新版本搂漠。一般來(lái)說(shuō),當(dāng)我們做了一些有意義的工作某弦,并且項(xiàng)目處于某一個(gè)穩(wěn)定狀態(tài)時(shí)桐汤,就可以提交一次更改。然而具體什么時(shí)候提交更改并沒(méi)有硬性的規(guī)定靶壮。我的建議是:從上次提交更改之后怔毛,如果你怕花費(fèi)大量時(shí)間和精力做的新工作被誤刪很難恢復(fù),你就需要提交更改了腾降。
默認(rèn)情況下拣度,Xcode在項(xiàng)目創(chuàng)建之初會(huì)提交一次更改,這是為了保存項(xiàng)目初始狀態(tài)螃壤。這項(xiàng)工作會(huì)在后臺(tái)完成抗果,不會(huì)打擾你或者要求你進(jìn)行確認(rèn)。如果你在項(xiàng)目創(chuàng)建時(shí)沒(méi)有添加git源奸晴,但是之后你手動(dòng)添加了冤馏,你可以通過(guò)我們先前使用過(guò)的命令來(lái)進(jìn)行提交:git commit -m ‘Initial commit’
實(shí)際上,你如果去Source Control>History…菜單寄啼,你就會(huì)看到初次提交更改的記錄逮光,以后每次提交更改代箭,都會(huì)在這里有所記錄。
接下來(lái)讓我們小幅修改一下我們的工程涕刚,在ViewController.m文件中嗡综,添加以下屬性聲明:
@interface ViewController ()
@property (nonatomic) int sum;
@end
接下來(lái),像下面這樣修改viewDidLoad方法:
-
(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.int a = 5;
int b = 10;self.sum = a + b;
NSLog("The result is: %d", self.sum);
}
看一下Project navigator面板副女,你會(huì)發(fā)現(xiàn)在ViewController.m文件旁邊蛤高,添加了一個(gè)M字母蚣旱,像下面這樣:
這意味著那個(gè)文件已經(jīng)被修改碑幅,相比上一次提交更改,文件有所改變塞绿。一般來(lái)說(shuō)沟涨,你每次改變文件,都會(huì)出現(xiàn)這個(gè)M字母异吻,提醒你有未提交的更改裹赴。
下面看看如何提交更改,其實(shí)非常簡(jiǎn)單诀浪,只需要打開(kāi)Source Control>Commit菜單棋返,下面窗口就會(huì)出現(xiàn):
讓我們一步步看看它告訴我們了什么。在左邊(標(biāo)1的區(qū)域)雷猪,列出了所有被更改的文件睛竣,在這個(gè)例子中,只有ViewController.m這個(gè)文件被改變求摇,因此列表中只有它被顯示射沟。如果你仔細(xì)觀察,你會(huì)發(fā)現(xiàn)文件左邊有一個(gè)選擇框与境,默認(rèn)情況下是被選中的验夯,如果你取消它,這個(gè)文件的更改就不會(huì)被提交摔刁。
在窗口的中間區(qū)域挥转,有兩個(gè)預(yù)覽窗口,左邊那個(gè)是文件當(dāng)前版本共屈,右邊是文件上一次提交更改的版本扁位。因?yàn)槲覀兡壳爸皇莿?chuàng)建時(shí)提交過(guò)一次更改,因此右邊顯示的是文件的初始狀態(tài)趁俊。
左邊窗口藍(lán)色區(qū)域標(biāo)出的就是更改的內(nèi)容域仇,這樣的表示讓我們可以清楚地看出所有的修改。如果你仔細(xì)看寺擂,會(huì)發(fā)現(xiàn)在兩個(gè)窗口之間還有一個(gè)帶數(shù)字的小標(biāo)簽暇务,這個(gè)數(shù)字一一表示了各項(xiàng)更改泼掠。在數(shù)字旁邊,默認(rèn)情況下有一個(gè)小對(duì)勾垦细,表示本更改會(huì)被提交择镇,如果你點(diǎn)擊右邊的小箭頭,會(huì)彈出一個(gè)選項(xiàng)菜單括改,你可以選擇不提交這個(gè)更改或是忽略它腻豌。
如果你選擇了Don’t Commit這個(gè)選項(xiàng),小對(duì)勾就會(huì)被一個(gè)停止標(biāo)志取代嘱能,這項(xiàng)更改就不會(huì)被保存到源中吝梅。
如果你選擇了Discard Change這個(gè)選項(xiàng),會(huì)彈出一個(gè)確認(rèn)窗口惹骂,提示你所做的更改會(huì)被恢復(fù)苏携,并且無(wú)法取消這個(gè)操作。
如果你點(diǎn)擊了OK按鈕对粪,所選區(qū)域的改變就會(huì)消失右冻,就像他們從未出現(xiàn)過(guò)一樣。
如果你仔細(xì)觀察上面這個(gè)提交窗口著拭,你會(huì)看到你所做的所有修改都會(huì)被Xcode看做改變纱扭,即使是一個(gè)空行。實(shí)際上空行相當(dāng)于回車儡遮,在屏幕上是不可見(jiàn)的乳蛾,因此作為改變也是理所當(dāng)然的。
在本例子中峦萎,你不用忽略任何修改屡久,而是允許提交所有更改,因此所有的改變標(biāo)簽旁邊必須都是小對(duì)勾爱榔。
在兩個(gè)窗口下面是一個(gè)空白的區(qū)域被环,中間顯示了提交更改的信息。這個(gè)地方可以添加一些關(guān)于此次更改的簡(jiǎn)短描述详幽,點(diǎn)擊它筛欢,加入如下內(nèi)容:
書(shū)寫(xiě)有意義的提交信息非常有用,尤其是當(dāng)你頻繁提交的時(shí)候唇聘。因此版姑,把它當(dāng)做一個(gè)必要的步驟。
現(xiàn)在這個(gè)窗口的基本信息看的差不多了迟郎,是時(shí)候做我們第一次的提交了剥险。在這個(gè)窗口的右下腳,有一個(gè)按鈕上面寫(xiě)著:Commit 1 file宪肖。
這個(gè)按鈕會(huì)顯示需要提交的文件總數(shù)表制。點(diǎn)擊它之后你的第一次提交就完成了健爬!打開(kāi)Source control > History,你會(huì)發(fā)現(xiàn)它會(huì)被顯示在列表中么介。
從上圖中可以看出娜遵,我們編寫(xiě)的信息以及更改的文件數(shù)量會(huì)被顯示出來(lái)。Xcode執(zhí)行初始提交壤短,所有文件都會(huì)被提交一下设拟,而這次只有我們修改的那個(gè)文件被提交。
另外久脯,關(guān)閉歷史窗口纳胧,看一下Project Navigator,你會(huì)發(fā)現(xiàn)ViewController.m旁邊的M符號(hào)已經(jīng)消失了桶现。
現(xiàn)在躲雅,讓我們準(zhǔn)備下一次提交鼎姊。這次骡和,我們給工程添加一些新的文件。添加文件最好的方式就是創(chuàng)建個(gè)新類相寇,因此慰于,按下Command+N組合鍵,添加一個(gè)Objective-C類唤衫。讓這個(gè)類繼承NSObject類婆赠,取名叫TestClass,然后添加到工程中佳励。
完成之后休里,注意一下Project Navigator旁蔼,你會(huì)發(fā)現(xiàn)兩個(gè)新的類文件旁邊有個(gè)A的字母標(biāo)識(shí)骄崩,這意味著這些文件已經(jīng)被添加到項(xiàng)目中吭练,當(dāng)然攘滩,他們還沒(méi)有被提交作喘。
打開(kāi)ViewController.h文件蹂喻,導(dǎo)入我們的新類:
import "TestClass.h"
下一步惕医,打開(kāi)ViewController.m文件浮入,像下面一樣聲明一個(gè)私有屬性:
@interface ViewController ()
@property (nonatomic) int sum;
@property (nonatomic, strong) TestClass *testClass;
@end
看一下項(xiàng)目導(dǎo)航欄抓于,這次有四個(gè)文件有待提交做粤。讓我們打開(kāi)Source Control > Commit菜單,將它們提交捉撮。
需要提交的一共有5個(gè)文件怕品。除了之前修改的四個(gè)之外,還有一個(gè)項(xiàng)目配置文件巾遭。Xcode會(huì)在新類被添加到項(xiàng)目中之后自動(dòng)修改這個(gè)文件肉康。如果你你打開(kāi)TestClass.h或TestClass.m文件修己,左邊的窗口沒(méi)有任何顯示,如下圖所示迎罗。
這是因?yàn)樵谶@個(gè)文件在之前沒(méi)有被提交的記錄睬愤,因此沒(méi)有一個(gè)可以比較的版本,在右邊只顯示了File was added纹安。
在消息區(qū)寫(xiě)上這樣一個(gè)描述:TestClass was added to project.. 之后點(diǎn)擊Commit 5 files按鈕即可尤辱。
這樣第二次手動(dòng)提交就成功了。你可以到Source Control > History 菜單查看提交的記錄厢岂。
版本之間的比較(Comparing Versions)當(dāng)你提交了同一工程的不同版本之后光督,在他們之間比較,追蹤修改信息就會(huì)非常方便塔粒。當(dāng)新添加的代碼不能運(yùn)行時(shí)结借,這時(shí)與之間版本進(jìn)行比較就非常重要了,你可以看出新版本相比上個(gè)穩(wěn)定版有了哪些更改卒茬。
要比較同一個(gè)文件的兩個(gè)版本船老,你可以使用View>Version Editor>Show version editor,或是點(diǎn)擊工具欄上的Version Editor按鈕:
點(diǎn)擊之后圃酵,編輯器會(huì)分為兩欄柳畔。最初,兩欄會(huì)顯示相同的內(nèi)容郭赐,點(diǎn)擊編輯器下面的那個(gè)小時(shí)鐘圖標(biāo)薪韩,可以選擇之前已經(jīng)提交的版本進(jìn)行比較。
點(diǎn)擊之后捌锭,兩個(gè)版本的區(qū)別會(huì)在編輯器中顯示出來(lái)俘陷。通常,左邊顯示的是當(dāng)前版本的文件观谦,右邊顯示的是之前的版本拉盾。藍(lán)色高亮的區(qū)域顯示了被更改的代碼,因此比較代碼的變化非常容易坎匿。繼續(xù)選擇任何此前的版本盾剩,并觀察兩欄的區(qū)別。
你可能會(huì)注意到替蔬,在兩個(gè)編輯器中間告私,還有在提交窗口看到的小標(biāo)簽。點(diǎn)擊向下的按鈕可以跳出讓你忽略更改的選項(xiàng)承桥。如果你點(diǎn)擊了忽略更改驻粟,Xcode會(huì)提示你是否同意。如果你同意忽略,這些被忽略的代碼將會(huì)永遠(yuǎn)消失蜀撑,無(wú)法再找回來(lái)挤巡。所以要注意不要無(wú)意中忽略任何代碼。
除了上面說(shuō)到的方法酷麦,還有一種你回到之前版本的方法矿卑。如果你仔細(xì)觀察兩個(gè)編輯器下面的工具欄,在中間有個(gè)帶箭頭的時(shí)鐘圖標(biāo):
點(diǎn)擊它之后沃饶,兩個(gè)面板之間的縱列內(nèi)容就發(fā)生了改變母廷,變成了一系列表示之前更改的時(shí)間戳。注意并不是所有的都代表實(shí)際提交糊肤。代表先前版本的圓角矩形的數(shù)量取決于提交的次數(shù)琴昆。在這個(gè)例子中,只有兩個(gè)這樣的圖形馆揉,代表了兩次提交业舍。
在這一列的下面,有兩個(gè)箭頭升酣。左邊的那個(gè)屬于左邊的面板舷暮,右邊的箭頭屬于右邊的面板。將箭頭移動(dòng)到任意之前的版本拗踢,你會(huì)看到在相應(yīng)面板中的改變脚牍。如果你想比較當(dāng)前版本和之前任意版本的區(qū)別向臀,讓一個(gè)箭頭指向local行巢墅,然后移動(dòng)第二個(gè)箭頭。時(shí)間戳從底部到頂部代表了從新到舊的代碼券膀。在base行君纫,你會(huì)看到上一次提交的內(nèi)容。繼續(xù)向上移動(dòng)芹彬,你會(huì)看到最初的提交蓄髓,如下圖所示:
現(xiàn)在你知道如何比較版本之間的區(qū)別了。再繼續(xù)深入之前舒帮,把前面學(xué)習(xí)的練習(xí)一下玩玩吧会喝。
究竟是誰(shuí)的錯(cuò)?(Who’s Got the Blame)除了比較文件的版本外玩郊,Xcode還可以讓你追蹤文件的提交者肢执,以及是誰(shuí)改變了哪一部分代碼。在一個(gè)多人的團(tuán)隊(duì)中译红,這非常有用预茄。要使用這個(gè)功能,點(diǎn)擊View > Version Editor > Show Blame View菜單侦厚〕苌拢或是講鼠標(biāo)放在工具欄的Version editor 按鈕上拙徽,選擇Blame選項(xiàng)。一個(gè)與上面類似的窗口將會(huì)出現(xiàn):
正如你看到的诗宣,當(dāng)前文件依據(jù)不同的提交被水平線分成幾段膘怕,每個(gè)代碼段的作者,以及提交信息和其他信息顯示在窗口右邊的一個(gè)特殊面板中召庞。
如果你還沒(méi)有做過(guò)淳蔼,那自己動(dòng)手打開(kāi)這個(gè)blame視圖,注意一下Xcode展現(xiàn)代碼段作者的方式裁眯。在這個(gè)視圖中鹉梨,可以方便地找到某一代碼在何時(shí)被誰(shuí)提交以及其他你想要的信息。將鼠標(biāo)放在blame面板上穿稳,將會(huì)顯示修改的一些其他信息存皂。當(dāng)指針停在提交段上時(shí),一個(gè)帶圖片的小按鈕就會(huì)出現(xiàn)在它的右邊逢艘。點(diǎn)擊選中該段代碼旦袋,就會(huì)彈出一個(gè)附帶提交信息窗口。在這個(gè)窗口中它改,你還可以跳轉(zhuǎn)到比較窗口(indication #1)疤孕,以及特定提交的修改文件(indication #2)。
除了比較視圖和blame試圖央拖,其實(shí)還有一個(gè)日志視圖(Log view)祭阀。你可以通過(guò)View > Version Editor > Show Log View來(lái)打開(kāi)它∠式洌或者如果你在這里就不在詳細(xì)說(shuō)它了专控。你可以自己去看看,畢竟這個(gè)用起來(lái)也沒(méi)那么復(fù)雜遏餐。
分支(Branches)試想一下伦腐,你現(xiàn)在的工程有一個(gè)即將發(fā)布的版本,或是已經(jīng)發(fā)布的版本失都,你突然想添加一些新的特性柏蘑,如何防止這些新添加的代碼讓整個(gè)項(xiàng)目陷入癱瘓呢?答案很簡(jiǎn)單:你需要使用分支粹庞。
如何簡(jiǎn)單的理解分支呢咳焚?你可以把你的項(xiàng)目想象成一棵樹(shù),穩(wěn)定版本就是樹(shù)的主干信粮。任何添加新功能的版本都必須是樹(shù)干的一部分。分支,就像是樹(shù)的枝干督惰,它從樹(shù)干生長(zhǎng)出來(lái)不傅,向不同的方向生長(zhǎng)。在git中赏胚,你可以通過(guò)創(chuàng)建分支來(lái)為你的代碼設(shè)置一個(gè)新的路徑來(lái)實(shí)現(xiàn)新特性访娶,而不用擔(dān)心在開(kāi)發(fā)中破壞主干。
實(shí)際上觉阅,在git中默認(rèn)都會(huì)有一個(gè)分支崖疤,叫做master。Xcode自動(dòng)執(zhí)行的第一次提交中就發(fā)生在這個(gè)分支中典勇。通常劫哼,單獨(dú)的開(kāi)發(fā)者只在master這個(gè)分支開(kāi)發(fā),這其實(shí)不是一個(gè)好習(xí)慣割笙。無(wú)論你是單打獨(dú)斗還是組團(tuán)合作权烧,我認(rèn)為在對(duì)項(xiàng)目作出重大改變或添加重大功能時(shí),使用分支是十分重要的伤溉,它會(huì)為你避免很多麻煩般码。當(dāng)然,在團(tuán)隊(duì)項(xiàng)目中乱顾,為你自己負(fù)責(zé)部分的代碼搞一個(gè)分支幾乎是必須的板祝。
關(guān)于分支,你必須記住以下兩點(diǎn):1. 提交到App Store或客戶的最終產(chǎn)品必須是項(xiàng)目中的master分支項(xiàng)目走净。2. 任何在第二分支中實(shí)現(xiàn)的代碼或者功能最終都必須合并到master分支券时,這樣正式發(fā)布的應(yīng)用程序才是完整的。(以后再講這一點(diǎn))
當(dāng)你開(kāi)始一個(gè)新分支時(shí)温技,你實(shí)際上是以當(dāng)前工作狀態(tài)作為起點(diǎn)革为,即使你有任何未提交的更改。從這個(gè)時(shí)候起舵鳞,所有的改變都會(huì)只體現(xiàn)在分支中。
現(xiàn)在讓我們回到Xcode琢蛤,要?jiǎng)?chuàng)建一個(gè)分支蜓堕,點(diǎn)擊Source Control > GitDemo-master > New Brance…這個(gè)菜單,然后會(huì)彈出如下菜單:
為這個(gè)分支起一個(gè)名字博其,我就把它起名為AnotherBranch好了√撞牛現(xiàn)在你怎么給它起名其實(shí)都無(wú)所謂。點(diǎn)擊OK按鈕慕淡,等一下新的分支就會(huì)被創(chuàng)建背伴,而當(dāng)前的代碼也會(huì)復(fù)制到新分支中去。
打開(kāi)Source Control菜單,你就可以輕松地找出活動(dòng)分支是哪一個(gè):它就在項(xiàng)目名字的旁邊傻寂。
現(xiàn)在息尺,讓我們做一次新的分支的提交。在這之前疾掰,讓我們添加一些新的代碼搂誉。打開(kāi)類文件,在私有屬性區(qū)添加以下方法聲明:
@interface ViewController ()
...
-(void)sayHello;
@end
然后實(shí)現(xiàn)它:
-(void)sayHello{
NSLog("Hello");
}
最后静檬,在viewDidLoad中調(diào)用它:
-
(void)didReceiveMemoryWarning
{
...[self sayHello];
}
現(xiàn)在炭懊,點(diǎn)擊Source Control > Commit菜單,版本比較窗口將會(huì)出現(xiàn)拂檩,你會(huì)看到只有一個(gè)被修改過(guò)的文件--ViewController.m文件侮腹,新添加的部分會(huì)被高亮顯示。
輸入下一個(gè)提交信息:First commit to a new branch稻励,然后點(diǎn)擊commit 1 file按鈕】現(xiàn)在AnotherBrance分支的改變就會(huì)被提交了。
打開(kāi)Version Editor(menu View > Version Editor > Show Version Editor)钉迷,找到右邊編輯面板下面的工具欄至非,你會(huì)看到被選中的分支是AnotherBranch,點(diǎn)擊它糠聪,你會(huì)看到這個(gè)分支和master分支同時(shí)出現(xiàn)荒椭,從master分支中選擇任意版本,Xcode都會(huì)高亮顯示兩者之間的區(qū)別舰蟆。通過(guò)這樣趣惠,你可以方便地跟蹤所有分支間代碼的改變。
最后身害,切換到另一個(gè)分支味悄,或是master分支,你可以點(diǎn)擊Source Control > GitDemo –AnotherBranch > Switch to Branch…菜單塌鸯。
從這個(gè)窗口你可以選擇想要跳轉(zhuǎn)的分支侍瑟,在這里讓我們跳回master分支:
選擇它并點(diǎn)擊Switch按鈕,master分支就會(huì)成為當(dāng)然活動(dòng)分支丙猬。你會(huì)發(fā)現(xiàn)在AnotherBranch中做出的改變并沒(méi)有出現(xiàn)在master分支涨颜。很好,我們?cè)诠芾砉こ掏七M(jìn)的同時(shí)茧球,卻沒(méi)有修改穩(wěn)定版本庭瑰。
合并分支(Merging Branches)在分支中進(jìn)行開(kāi)發(fā)是一種好習(xí)慣,然而抢埋,如果代碼改變要體現(xiàn)在發(fā)行版中弹灭,那么分支就必須被合并到master分支中督暂。這一節(jié)我們將會(huì)告訴你怎樣合并它們。在Xcode里穷吮,將兩個(gè)分支合并成一個(gè)非常簡(jiǎn)單逻翁。
讓我們做一個(gè)小實(shí)驗(yàn)來(lái)看看合并是怎樣工作的。首先酒来,確保master分支是現(xiàn)在的活動(dòng)分支卢未。如果不是,趕緊改過(guò)來(lái):Source Control > GitDemo – AnotherBranch > Switch To Branch… menu堰汉,并從展示窗口選擇master分支辽社。
下一步,創(chuàng)建一個(gè)新的分支:Source Control > GitDemo – master > New Branch… menu翘鸭,命名為L(zhǎng)astBranch
先讓Xcode飛一會(huì)滴铅,然后,到ViewController.m文件中就乓,再創(chuàng)建一個(gè)私有方法汉匙,首先聲明它:
@interface ViewController ()
...
-(void)sayByeBye;
@end
然后實(shí)現(xiàn)它:
-(void)sayByeBye{
NSLog("Bye - Bye");
}
最后,在ViewDidLoad方法中調(diào)用它:
-
(void)viewDidLoad
{
...[self sayByeBye];
}
在合并之前生蚁,先提交這些更改噩翠。使用Source Control > Commit菜單來(lái)執(zhí)行提交。
終于還是來(lái)到這一步邦投,關(guān)于把兩個(gè)不同的分支合并成一個(gè)伤锚,你有兩種選擇“1. 從分支合并:與你選擇的分支相關(guān)的任何改變都會(huì)被合并到現(xiàn)在活動(dòng)分支中。2. 合并到分支:當(dāng)前活動(dòng)分支的任何改變都會(huì)被合并到你選擇的分支中志衣。
這兩種方式你都可以在Source Control > GitDemo 菜單中找到屯援。注意當(dāng)你的活動(dòng)分支是master分支時(shí),第二個(gè)選項(xiàng)是不可選的念脯。
假設(shè)一個(gè)開(kāi)發(fā)者在Anotherbranch分支實(shí)現(xiàn)一個(gè)sayHello方法狞洋,另外一個(gè)開(kāi)發(fā)者在LastBranch中創(chuàng)建實(shí)現(xiàn)了sayByeBye方法,現(xiàn)在你需要將兩個(gè)人的工作合并到下一個(gè)穩(wěn)定版本中绿店,想一想你需要怎么做吉懊?很簡(jiǎn)單,按以下方法將改變從兩個(gè)分支中合并進(jìn)來(lái):
首先惯吕,確保當(dāng)前活躍分支是master分支惕它。
然后,打開(kāi)Source Control > GitDemo – master > Merge From Branch…菜單废登,選擇AnotherBranch然后點(diǎn)擊Merge按鈕。
接下來(lái)會(huì)出現(xiàn)一個(gè)比較窗口郁惜,在里面你會(huì)看到合并之后代碼的更改堡距,看一眼甲锡,感覺(jué)差不多了就再點(diǎn)擊Merge按鈕。
Xcode會(huì)詢問(wèn)你是否保存項(xiàng)目的快照羽戒,點(diǎn)擊Enable按鈕缤沦。讓Xcode飛一會(huì),然后就好啦易稠。AnotherBranch里面添加的內(nèi)容已經(jīng)合并到master分支中缸废。
使用同樣的方法來(lái)合并LastBranch。你會(huì)發(fā)現(xiàn)如果你不提交更改驶社,Xcode不會(huì)讓你再次合并企量。于是,我們只好先提交一下亡电。在比較窗口你會(huì)發(fā)現(xiàn)一個(gè)紅色的區(qū)域顯示合并之后的更改届巩,而不是之前的藍(lán)色。這意味著分支中的代碼將會(huì)替換原先活動(dòng)分支中的代碼份乒。
你可以輕松地避免這種現(xiàn)象的發(fā)生恕汇。在編輯面板的下面有幾個(gè)小按鈕,你可以試試他們都有什么作用或辖,我選了第一個(gè)瘾英,它的意思是master分支的代碼會(huì)被放在上面,另一個(gè)分支的代碼會(huì)跟在它后面颂暇。
處理接下來(lái)所有需要更改的代碼缺谴,不要有遺漏。完事后就點(diǎn)擊Merge按鈕蟀架。
恭喜你瓣赂!你已經(jīng)成功的學(xué)會(huì)從多個(gè)分支合并了代碼,類似的情形你也應(yīng)該會(huì)了片拍。
忽略更改(Discarding Changes)放棄不想要的代碼更改功能非常有用煌集,只需輕輕一點(diǎn),自從上一次提交之后的更改都會(huì)被放棄捌省。當(dāng)你在開(kāi)發(fā)過(guò)程中發(fā)現(xiàn)出了大亂子苫纤,你想從上一個(gè)穩(wěn)定狀態(tài)重新開(kāi)始時(shí),這個(gè)功能就派上用場(chǎng)啦纲缓。注意放棄更改這個(gè)功能沒(méi)有回頭路卷拘,點(diǎn)完之后你就沒(méi)有辦法再撤銷這個(gè)操作,所以祝高,要小心使用袄醯堋!
之前工闺,當(dāng)我們?cè)谟懻摪姹颈容^時(shí)乍赫,我們學(xué)會(huì)了如何忽略某一部分更改的方法瓣蛀,下面,我們要學(xué)一下如何一下忽略自從上一次提交之后的所有更改雷厂。
為了測(cè)試這個(gè)功能惋增,首先寫(xiě)一些代碼打開(kāi)ViewController.h ,添加一個(gè)公共方法聲明:
@interface ViewController : UIViewController
-(void)aVeryCoolMethod;
@end
現(xiàn)在改鲫,讓我們?cè)赩iewController.m中添加一個(gè)這個(gè)方法的實(shí)現(xiàn)诈皿,簡(jiǎn)單點(diǎn)就行:
-(void)aVeryCoolMethod{
NSLog("I'm feeling that you'll discard me... Really?");
}
如果你注意到Project Navigator,我們剛剛更改的文件旁邊有了一個(gè)M標(biāo)識(shí)像棘,很好稽亏,我們想看看如果忽略這些更改,這些文件是否會(huì)回到更改之前的狀態(tài)讲弄。
這里有一個(gè)重要的細(xì)節(jié):你可以選擇忽略所有文件的更改措左,也可以選擇忽略單個(gè)文件的更改,這完全取決于你避除。如果你想忽略一個(gè)文件的更改怎披,首先選定這個(gè)文件。在這個(gè)例子里瓶摆,如果你只選擇ViewController.m文件然后打開(kāi)Source Control菜單凉逛,你會(huì)在ViewController.m中發(fā)現(xiàn)Didcard Changes這個(gè)選項(xiàng)。類似的群井,如果你只選擇ViewController.h也是一個(gè)道理状飞。然而,如果你想忽視這兩個(gè)文件的更改(這里假定有兩個(gè)以上的更改)书斜,就在Project Navigator中選中它們诬辈,然后再打開(kāi)Source Control菜單。相應(yīng)的位置就會(huì)顯示Discard Changes in 2 Files荐吉,像下面這樣:
然而焙糟,這次我們不會(huì)使用這個(gè)按鈕,我們要用Discard All Changes样屠。點(diǎn)擊它之后穿撮,一個(gè)確定提示框就會(huì)出現(xiàn),這是這部分Xcode防止你誤刪代碼的唯一措施痪欲。
點(diǎn)擊Discard All Changes, 那你剛才寫(xiě)的那個(gè)公共方法就永遠(yuǎn)屬于過(guò)去了悦穿。看到了吧业踢,只需幾步就可以讓你從當(dāng)前工作狀態(tài)恢復(fù)到之前的提交栗柒,所以我再一次提醒你要在使用Source Control 中小心點(diǎn),別誤點(diǎn)了這個(gè)按鈕知举。
總結(jié)通過(guò)這篇教程傍衡,我盡力詳述了在Xcode中進(jìn)行版本控制的方法深员。其實(shí)在幕后负蠕,真正起作用的是git----地球上應(yīng)用最多的版本控制系統(tǒng)蛙埂。你可能注意到我在教程中并沒(méi)有過(guò)多的提到GitHub或者任何Xcode的一些功能----其實(shí)我是故意這樣的。我想把注意力集中在使用Xcode進(jìn)行g(shù)it管理的內(nèi)容上遮糖。只有當(dāng)你懂得了如何進(jìn)行版本控制之后绣的,才能真正的使用GitHub。我想再重申一下欲账,如果你是一個(gè)團(tuán)隊(duì)在工作屡江,使用版本控制工具是必須的!如果你是單打獨(dú)斗赛不,使用版本控制工具也是很有必要的惩嘉,它可以為你花大量時(shí)間和精力所做的工作提供保障,并且在你添加新功能時(shí)可簡(jiǎn)單地進(jìn)行擴(kuò)展踢故。這個(gè)工具就像有些人說(shuō)的那樣文黎,一旦用了,就再也回不去了殿较!最后耸峭,我希望這個(gè)教程會(huì)對(duì)你有用。