本文翻譯自Understanding Git Source Control in Xcode (譯者myShire)歡迎您加入我們的翻譯小組。
在應(yīng)用程序開發(fā)過程中,很重要的一部分工作就是如何進(jìn)行源碼的版本控制。當(dāng)代碼出現(xiàn)問題時(shí),我們就需要將代碼恢復(fù)到原先正常的版本。如果是多個(gè)人共同開發(fā)一個(gè)項(xiàng)目,那么代碼的控制就會非常復(fù)雜。幸運(yùn)的是,開發(fā)者不需要自己控制這些,因?yàn)橛袑iT的軟件來負(fù)責(zé),叫做版本控制系統(tǒng)。
版本控制系統(tǒng),或者說修改控制系統(tǒng),實(shí)際上是一種檢測源文件的改變并將其保存留作以后參考使用的機(jī)制(軟件)。此外,它還能記錄其他有用信息,比如是哪個(gè)開發(fā)者修改了代碼,何時(shí)修改的,修改了哪一部分,以及其他歷史信息。版本控制系統(tǒng)可以比較不同版本代碼的不同,有必要時(shí)能恢復(fù)整個(gè)項(xiàng)目到以前的版本,追蹤有害代碼從而減少產(chǎn)品的錯(cuò)誤。
通過版本控制系統(tǒng),開發(fā)者可以在一個(gè)項(xiàng)目的不同分支上工作,當(dāng)項(xiàng)目的各個(gè)部分開發(fā)完備時(shí),將它們放到一起形成最終的版本,這個(gè)過程被稱為合并。事實(shí)上,這種做法再團(tuán)隊(duì)和軟件公司中相當(dāng)常見:每個(gè)人負(fù)責(zé)項(xiàng)目的一部分,最終所有部分被整合到一起形成最終產(chǎn)品。
對于個(gè)人開發(fā)者來說,版本控制系統(tǒng)并不是必需的,但是我們?nèi)匀粡?qiáng)烈推薦開發(fā)者使用它,因?yàn)樗梢允勾a方便的在有錯(cuò)誤的版本和可以工作的版本之間轉(zhuǎn)換。事實(shí)上,很多開發(fā)者從來不使用類似的工具,他們會在項(xiàng)目添加新的功能時(shí)手動(dòng)保存原先的項(xiàng)目。這其實(shí)是一個(gè)很不好的習(xí)慣,因?yàn)榘姹究刂栖浖梢愿酶咝У赝瓿蛇@項(xiàng)任務(wù)。
Git是一個(gè)常見的版本控制系統(tǒng),它最開始是由Liunx之父Linus Torvalds開發(fā)的,Git使用虛擬目錄,又稱為repositories,來管理一切事物。Git可以通過命令行調(diào)用,也有專門為它設(shè)計(jì)的桌面應(yīng)用軟件。如果Git對你來說很陌生,我建議你在網(wǎng)上查看一些它的相關(guān)信息。關(guān)于Git更深層次的內(nèi)容都不在本文的討論范圍之內(nèi)。
從Xcode5開始引入了使用git的一些新特性。它將git的各項(xiàng)功能整合到一個(gè)菜單中,并提供子菜單來進(jìn)行軟件合并的控制。在接下來的閱讀中你會發(fā)現(xiàn),使用git來進(jìn)行版本控制相當(dāng)?shù)暮唵慰旖荨?/p>
我們接下來的任務(wù)就是學(xué)習(xí)如何在Xcode中使用git,以及Xcode是如何整合Git的各項(xiàng)功能。如果你覺得對這些很陌生,我建議你先上網(wǎng)搜索一下相關(guān)的內(nèi)容。在接下來的教程中,我會假定你已經(jīng)了解了版本控制系統(tǒng)和git是什么,并將注意力集中在Xcode如何管理它上。
GIT Demo概述(GIT Demo Overview)
與其他教程中的demo app不同,這次我們不會去實(shí)現(xiàn)一個(gè)應(yīng)用來演示某一項(xiàng)iOS SDK特性,最終我們也不會產(chǎn)生一個(gè)示例產(chǎn)品。實(shí)際上,我們會新建一個(gè)demo工程,寫幾行代碼,然后利用這個(gè)工程來演示Xcode提供的版本管理功能。換句話說,我們會集中注意里于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)用,那么你無法體會到這些改變。
好了,廢話不多說了,讓我們仔細(xì)看看使用Xcode進(jìn)行版本控制的要點(diǎn)吧。
創(chuàng)建一個(gè)Git源(Creating a Git repository)
每次在Xcode中創(chuàng)建新工程的時(shí)候,都會提示開發(fā)者是否將項(xiàng)目作為一個(gè)本地的git源。在創(chuàng)建工程的最后一步Xcode會有一個(gè)復(fù)選框,如果選擇了它,git源就會被添加到工程目錄中。通常這個(gè)選項(xiàng)會被忽視,或是被認(rèn)為是Xcode的另外一個(gè)沒用的功能,尤其是從未用過git的開發(fā)者,或是編程新手。
打開Xcode,創(chuàng)建一個(gè)新的工程。選擇iOS區(qū)的“Application”,在應(yīng)用模板頁選擇“Single View Application”。
選擇下一步,在項(xiàng)目名中輸入GitDemo,確保下面的Devices菜單選擇iPhone,無需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)目之后,打開Finder,找到項(xiàng)目存儲的目錄,在目錄中,有一個(gè).git的子目錄,時(shí)Xcode為存儲git源相關(guān)數(shù)據(jù)自動(dòng)創(chuàng)建的。
如果你看不到.git目錄,你需要讓隱藏的文件可見。具體做法就是打開一個(gè)Terminal窗口,輸入以下命令:
對于OS X Mavericks 10.9:
defaults write com.apple.finder AppleShowAllFiles TRUE
對于以前的OS X版本,
efaults write com.apple.Finder AppleShowAllFiles TRUE
為了重啟Finder應(yīng)用,輸入
killall Finder
這就是本項(xiàng)目在本地git源保存的位置。實(shí)際上,如果你選上了相應(yīng)的選項(xiàng),這個(gè)目錄就會被創(chuàng)建。相應(yīng)地,在你創(chuàng)建新應(yīng)用時(shí),.git子目錄也會一同被創(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ā)生,我還是會告訴你該怎么做。
如果你愿意的話,你可以直接跳到本教程的下一部分。我建議你接著讀下去,因?yàn)榻酉聛磉@些信息還是很有用的。
在進(jìn)行演示前,你需要首先通過Xcode下載Command Line Tools,因?yàn)槲覀円赥erminal下操作,并且需要一些額外的工具。如果你還沒有下載,那就去Xcode>Preferences…菜單,選擇Download選項(xiàng)卡,展開Components區(qū),點(diǎn)擊Commond Line Tools右邊下載按鈕。下載完成后,一個(gè)對勾符號會取代下載按鈕。
現(xiàn)在,為這個(gè)例子再創(chuàng)建一個(gè)工程,完事后可以刪了它。在創(chuàng)建時(shí)取消那個(gè)創(chuàng)建git源的選項(xiàng)。這次我們不想讓Xcode為我們準(zhǔn)備一個(gè)源。把這個(gè)工程命名為NoGitExample,保存到桌面,然后你可以跟我接下來輸入的命令一樣。
一切準(zhǔn)備妥當(dāng)后,打開Terminal窗口(如果你之前打開了一個(gè),那就先關(guān)掉它再重啟,從而使我們安裝的命令行工具生效)。下面切換到新項(xiàng)目的目錄:
cd /Users/YOUR-USERNAME/Desktop/NoGitExample
別忘了在上邊命令中設(shè)置Mac的用戶名,接下來,輸入:
git init
這會初始化一個(gè)空的源,如果你在Finder里面查看或是輸入ls命令,你會看到.git子目錄已經(jīng)被創(chuàng)建,很好,接下來輸入:
git add .
這樣,當(dāng)前目錄所有的內(nèi)容就被添加到源里面去了,最后,輸入以下命令:
git commit -m 'Initial commit'
接下來會出現(xiàn)一個(gè)本地git源所執(zhí)行的改變列表,如下圖所示:
現(xiàn)在git源就建好了,但是如果你回到Xcode,打開Source Control菜單,你會發(fā)現(xiàn)一切仍然是被禁用。
這是因?yàn)楫?dāng)我們使用命令行工具創(chuàng)建git源時(shí),Xcode并未被通知,下面點(diǎn)擊Xcode>Quit Xcode,然后重新啟動(dòng)它,在NoGitExample項(xiàng)目中,如果你再次打開Source Control菜單,你會發(fā)現(xiàn)所有的選項(xiàng)已經(jīng)被使能了,就像一開始勾選上創(chuàng)建git源一樣。
現(xiàn)在這個(gè)項(xiàng)目的使命已經(jīng)結(jié)束,你可以在桌面上刪除它。
現(xiàn)在你知道如何為你所有的項(xiàng)目添加git源了,即使你在創(chuàng)建時(shí)沒有添加,你也可以在以后任何時(shí)候?yàn)樗謩?dòng)添加源。
提交更改(Committing Changes)提交更改指的是儲存一個(gè)包含所有更改的新版本。一般來說,當(dāng)我們做了一些有意義的工作,并且項(xiàng)目處于某一個(gè)穩(wěn)定狀態(tài)時(shí),就可以提交一次更改。然而具體什么時(shí)候提交更改并沒有硬性的規(guī)定。我的建議是:從上次提交更改之后,如果你怕花費(fèi)大量時(shí)間和精力做的新工作被誤刪很難恢復(fù),你就需要提交更改了。
默認(rèn)情況下,Xcode在項(xiàng)目創(chuàng)建之初會提交一次更改,這是為了保存項(xiàng)目初始狀態(tài)。這項(xiàng)工作會在后臺完成,不會打擾你或者要求你進(jìn)行確認(rèn)。如果你在項(xiàng)目創(chuàng)建時(shí)沒有添加git源,但是之后你手動(dòng)添加了,你可以通過我們先前使用過的命令來進(jìn)行提交:git commit -m ‘Initial commit’
實(shí)際上,你如果去Source Control>History…菜單,你就會看到初次提交更改的記錄,以后每次提交更改,都會在這里有所記錄。
接下來讓我們小幅修改一下我們的工程,在ViewController.m文件中,添加以下屬性聲明:
@interface ViewController ()
@property (nonatomic) int sum;
@end
接下來,像下面這樣修改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面板,你會發(fā)現(xiàn)在ViewController.m文件旁邊,添加了一個(gè)M字母,像下面這樣:
這意味著那個(gè)文件已經(jīng)被修改,相比上一次提交更改,文件有所改變。一般來說,你每次改變文件,都會出現(xiàn)這個(gè)M字母,提醒你有未提交的更改。
下面看看如何提交更改,其實(shí)非常簡單,只需要打開Source Control>Commit菜單,下面窗口就會出現(xiàn):
讓我們一步步看看它告訴我們了什么。在左邊(標(biāo)1的區(qū)域),列出了所有被更改的文件,在這個(gè)例子中,只有ViewController.m這個(gè)文件被改變,因此列表中只有它被顯示。如果你仔細(xì)觀察,你會發(fā)現(xiàn)文件左邊有一個(gè)選擇框,默認(rèn)情況下是被選中的,如果你取消它,這個(gè)文件的更改就不會被提交。
在窗口的中間區(qū)域,有兩個(gè)預(yù)覽窗口,左邊那個(gè)是文件當(dāng)前版本,右邊是文件上一次提交更改的版本。因?yàn)槲覀兡壳爸皇莿?chuàng)建時(shí)提交過一次更改,因此右邊顯示的是文件的初始狀態(tài)。
左邊窗口藍(lán)色區(qū)域標(biāo)出的就是更改的內(nèi)容,這樣的表示讓我們可以清楚地看出所有的修改。如果你仔細(xì)看,會發(fā)現(xiàn)在兩個(gè)窗口之間還有一個(gè)帶數(shù)字的小標(biāo)簽,這個(gè)數(shù)字一一表示了各項(xiàng)更改。在數(shù)字旁邊,默認(rèn)情況下有一個(gè)小對勾,表示本更改會被提交,如果你點(diǎn)擊右邊的小箭頭,會彈出一個(gè)選項(xiàng)菜單,你可以選擇不提交這個(gè)更改或是忽略它。
如果你選擇了Don’t Commit這個(gè)選項(xiàng),小對勾就會被一個(gè)停止標(biāo)志取代,這項(xiàng)更改就不會被保存到源中。
如果你選擇了Discard Change這個(gè)選項(xiàng),會彈出一個(gè)確認(rèn)窗口,提示你所做的更改會被恢復(fù),并且無法取消這個(gè)操作。
如果你點(diǎn)擊了OK按鈕,所選區(qū)域的改變就會消失,就像他們從未出現(xiàn)過一樣。
如果你仔細(xì)觀察上面這個(gè)提交窗口,你會看到你所做的所有修改都會被Xcode看做改變,即使是一個(gè)空行。實(shí)際上空行相當(dāng)于回車,在屏幕上是不可見的,因此作為改變也是理所當(dāng)然的。
在本例子中,你不用忽略任何修改,而是允許提交所有更改,因此所有的改變標(biāo)簽旁邊必須都是小對勾。
在兩個(gè)窗口下面是一個(gè)空白的區(qū)域,中間顯示了提交更改的信息。這個(gè)地方可以添加一些關(guān)于此次更改的簡短描述,點(diǎn)擊它,加入如下內(nèi)容:
書寫有意義的提交信息非常有用,尤其是當(dāng)你頻繁提交的時(shí)候。因此,把它當(dāng)做一個(gè)必要的步驟。
現(xiàn)在這個(gè)窗口的基本信息看的差不多了,是時(shí)候做我們第一次的提交了。在這個(gè)窗口的右下腳,有一個(gè)按鈕上面寫著:Commit 1 file。
這個(gè)按鈕會顯示需要提交的文件總數(shù)。點(diǎn)擊它之后你的第一次提交就完成了!打開Source control > History,你會發(fā)現(xiàn)它會被顯示在列表中。
從上圖中可以看出,我們編寫的信息以及更改的文件數(shù)量會被顯示出來。Xcode執(zhí)行初始提交,所有文件都會被提交一下,而這次只有我們修改的那個(gè)文件被提交。
另外,關(guān)閉歷史窗口,看一下Project Navigator,你會發(fā)現(xiàn)ViewController.m旁邊的M符號已經(jīng)消失了。
現(xiàn)在,讓我們準(zhǔn)備下一次提交。這次,我們給工程添加一些新的文件。添加文件最好的方式就是創(chuàng)建個(gè)新類,因此,按下Command+N組合鍵,添加一個(gè)Objective-C類。讓這個(gè)類繼承NSObject類,取名叫TestClass,然后添加到工程中。
完成之后,注意一下Project Navigator,你會發(fā)現(xiàn)兩個(gè)新的類文件旁邊有個(gè)A的字母標(biāo)識,這意味著這些文件已經(jīng)被添加到項(xiàng)目中,當(dāng)然,他們還沒有被提交。
打開ViewController.h文件,導(dǎo)入我們的新類:
import "TestClass.h"
下一步,打開ViewController.m文件,像下面一樣聲明一個(gè)私有屬性:
@interface ViewController ()
@property (nonatomic) int sum;
@property (nonatomic, strong) TestClass *testClass;
@end
看一下項(xiàng)目導(dǎo)航欄,這次有四個(gè)文件有待提交。讓我們打開Source Control > Commit菜單,將它們提交。
需要提交的一共有5個(gè)文件。除了之前修改的四個(gè)之外,還有一個(gè)項(xiàng)目配置文件。Xcode會在新類被添加到項(xiàng)目中之后自動(dòng)修改這個(gè)文件。如果你你打開TestClass.h或TestClass.m文件,左邊的窗口沒有任何顯示,如下圖所示。
這是因?yàn)樵谶@個(gè)文件在之前沒有被提交的記錄,因此沒有一個(gè)可以比較的版本,在右邊只顯示了File was added。
在消息區(qū)寫上這樣一個(gè)描述:TestClass was added to project.. 之后點(diǎn)擊Commit 5 files按鈕即可。
這樣第二次手動(dòng)提交就成功了。你可以到Source Control > History 菜單查看提交的記錄。
版本之間的比較(Comparing Versions)當(dāng)你提交了同一工程的不同版本之后,在他們之間比較,追蹤修改信息就會非常方便。當(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)擊之后,編輯器會分為兩欄。最初,兩欄會顯示相同的內(nèi)容,點(diǎn)擊編輯器下面的那個(gè)小時(shí)鐘圖標(biāo),可以選擇之前已經(jīng)提交的版本進(jìn)行比較。
點(diǎn)擊之后,兩個(gè)版本的區(qū)別會在編輯器中顯示出來。通常,左邊顯示的是當(dāng)前版本的文件,右邊顯示的是之前的版本。藍(lán)色高亮的區(qū)域顯示了被更改的代碼,因此比較代碼的變化非常容易。繼續(xù)選擇任何此前的版本,并觀察兩欄的區(qū)別。
你可能會注意到,在兩個(gè)編輯器中間,還有在提交窗口看到的小標(biāo)簽。點(diǎn)擊向下的按鈕可以跳出讓你忽略更改的選項(xiàng)。如果你點(diǎn)擊了忽略更改,Xcode會提示你是否同意。如果你同意忽略,這些被忽略的代碼將會永遠(yuǎn)消失,無法再找回來。所以要注意不要無意中忽略任何代碼。
除了上面說到的方法,還有一種你回到之前版本的方法。如果你仔細(xì)觀察兩個(gè)編輯器下面的工具欄,在中間有個(gè)帶箭頭的時(shí)鐘圖標(biāo):
點(diǎn)擊它之后,兩個(gè)面板之間的縱列內(nèi)容就發(fā)生了改變,變成了一系列表示之前更改的時(shí)間戳。注意并不是所有的都代表實(shí)際提交。代表先前版本的圓角矩形的數(shù)量取決于提交的次數(shù)。在這個(gè)例子中,只有兩個(gè)這樣的圖形,代表了兩次提交。
在這一列的下面,有兩個(gè)箭頭。左邊的那個(gè)屬于左邊的面板,右邊的箭頭屬于右邊的面板。將箭頭移動(dòng)到任意之前的版本,你會看到在相應(yīng)面板中的改變。如果你想比較當(dāng)前版本和之前任意版本的區(qū)別,讓一個(gè)箭頭指向local行,然后移動(dòng)第二個(gè)箭頭。時(shí)間戳從底部到頂部代表了從新到舊的代碼。在base行,你會看到上一次提交的內(nèi)容。繼續(xù)向上移動(dòng),你會看到最初的提交,如下圖所示:
現(xiàn)在你知道如何比較版本之間的區(qū)別了。再繼續(xù)深入之前,把前面學(xué)習(xí)的練習(xí)一下玩玩吧。
究竟是誰的錯(cuò)?(Who’s Got the Blame)除了比較文件的版本外,Xcode還可以讓你追蹤文件的提交者,以及是誰改變了哪一部分代碼。在一個(gè)多人的團(tuán)隊(duì)中,這非常有用。要使用這個(gè)功能,點(diǎn)擊View > Version Editor > Show Blame View菜單?;蚴侵v鼠標(biāo)放在工具欄的Version editor 按鈕上,選擇Blame選項(xiàng)。一個(gè)與上面類似的窗口將會出現(xiàn):
正如你看到的,當(dāng)前文件依據(jù)不同的提交被水平線分成幾段,每個(gè)代碼段的作者,以及提交信息和其他信息顯示在窗口右邊的一個(gè)特殊面板中。
如果你還沒有做過,那自己動(dòng)手打開這個(gè)blame視圖,注意一下Xcode展現(xiàn)代碼段作者的方式。在這個(gè)視圖中,可以方便地找到某一代碼在何時(shí)被誰提交以及其他你想要的信息。將鼠標(biāo)放在blame面板上,將會顯示修改的一些其他信息。當(dāng)指針停在提交段上時(shí),一個(gè)帶圖片的小按鈕就會出現(xiàn)在它的右邊。點(diǎn)擊選中該段代碼,就會彈出一個(gè)附帶提交信息窗口。在這個(gè)窗口中,你還可以跳轉(zhuǎn)到比較窗口(indication #1),以及特定提交的修改文件(indication #2)。
除了比較視圖和blame試圖,其實(shí)還有一個(gè)日志視圖(Log view)。你可以通過View > Version Editor > Show Log View來打開它。或者如果你在這里就不在詳細(xì)說它了。你可以自己去看看,畢竟這個(gè)用起來也沒那么復(fù)雜。
分支(Branches)試想一下,你現(xiàn)在的工程有一個(gè)即將發(fā)布的版本,或是已經(jīng)發(fā)布的版本,你突然想添加一些新的特性,如何防止這些新添加的代碼讓整個(gè)項(xiàng)目陷入癱瘓呢?答案很簡單:你需要使用分支。
如何簡單的理解分支呢?你可以把你的項(xiàng)目想象成一棵樹,穩(wěn)定版本就是樹的主干。任何添加新功能的版本都必須是樹干的一部分。分支,就像是樹的枝干,它從樹干生長出來,向不同的方向生長。在git中,你可以通過創(chuàng)建分支來為你的代碼設(shè)置一個(gè)新的路徑來實(shí)現(xiàn)新特性,而不用擔(dān)心在開發(fā)中破壞主干。
實(shí)際上,在git中默認(rèn)都會有一個(gè)分支,叫做master。Xcode自動(dòng)執(zhí)行的第一次提交中就發(fā)生在這個(gè)分支中。通常,單獨(dú)的開發(fā)者只在master這個(gè)分支開發(fā),這其實(shí)不是一個(gè)好習(xí)慣。無論你是單打獨(dú)斗還是組團(tuán)合作,我認(rèn)為在對項(xiàng)目作出重大改變或添加重大功能時(shí),使用分支是十分重要的,它會為你避免很多麻煩。當(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)你開始一個(gè)新分支時(shí),你實(shí)際上是以當(dāng)前工作狀態(tài)作為起點(diǎn),即使你有任何未提交的更改。從這個(gè)時(shí)候起,所有的改變都會只體現(xiàn)在分支中。
現(xiàn)在讓我們回到Xcode,要?jiǎng)?chuàng)建一個(gè)分支,點(diǎn)擊Source Control > GitDemo-master > New Brance…這個(gè)菜單,然后會彈出如下菜單:
為這個(gè)分支起一個(gè)名字,我就把它起名為AnotherBranch好了?,F(xiàn)在你怎么給它起名其實(shí)都無所謂。點(diǎn)擊OK按鈕,等一下新的分支就會被創(chuàng)建,而當(dāng)前的代碼也會復(fù)制到新分支中去。
打開Source Control菜單,你就可以輕松地找出活動(dòng)分支是哪一個(gè):它就在項(xiàng)目名字的旁邊。
現(xiàn)在,讓我們做一次新的分支的提交。在這之前,讓我們添加一些新的代碼。打開類文件,在私有屬性區(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菜單,版本比較窗口將會出現(xiàn),你會看到只有一個(gè)被修改過的文件--ViewController.m文件,新添加的部分會被高亮顯示。
輸入下一個(gè)提交信息:First commit to a new branch,然后點(diǎn)擊commit 1 file按鈕?,F(xiàn)在AnotherBrance分支的改變就會被提交了。
打開Version Editor(menu View > Version Editor > Show Version Editor),找到右邊編輯面板下面的工具欄,你會看到被選中的分支是AnotherBranch,點(diǎn)擊它,你會看到這個(gè)分支和master分支同時(shí)出現(xiàn),從master分支中選擇任意版本,Xcode都會高亮顯示兩者之間的區(qū)別。通過這樣,你可以方便地跟蹤所有分支間代碼的改變。
最后,切換到另一個(gè)分支,或是master分支,你可以點(diǎn)擊Source Control > GitDemo –AnotherBranch > Switch to Branch…菜單。
從這個(gè)窗口你可以選擇想要跳轉(zhuǎn)的分支,在這里讓我們跳回master分支:
選擇它并點(diǎn)擊Switch按鈕,master分支就會成為當(dāng)然活動(dòng)分支。你會發(fā)現(xiàn)在AnotherBranch中做出的改變并沒有出現(xiàn)在master分支。很好,我們在管理工程推進(jìn)的同時(shí),卻沒有修改穩(wěn)定版本。
合并分支(Merging Branches)在分支中進(jìn)行開發(fā)是一種好習(xí)慣,然而,如果代碼改變要體現(xiàn)在發(fā)行版中,那么分支就必須被合并到master分支中。這一節(jié)我們將會告訴你怎樣合并它們。在Xcode里,將兩個(gè)分支合并成一個(gè)非常簡單。
讓我們做一個(gè)小實(shí)驗(yàn)來看看合并是怎樣工作的。首先,確保master分支是現(xiàn)在的活動(dòng)分支。如果不是,趕緊改過來:Source Control > GitDemo – AnotherBranch > Switch To Branch… menu,并從展示窗口選擇master分支。
下一步,創(chuàng)建一個(gè)新的分支:Source Control > GitDemo – master > New Branch… menu,命名為LastBranch
先讓Xcode飛一會,然后,到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菜單來執(zhí)行提交。
終于還是來到這一步,關(guān)于把兩個(gè)不同的分支合并成一個(gè),你有兩種選擇“1. 從分支合并:與你選擇的分支相關(guān)的任何改變都會被合并到現(xiàn)在活動(dòng)分支中。2. 合并到分支:當(dāng)前活動(dòng)分支的任何改變都會被合并到你選擇的分支中。
這兩種方式你都可以在Source Control > GitDemo 菜單中找到。注意當(dāng)你的活動(dòng)分支是master分支時(shí),第二個(gè)選項(xiàng)是不可選的。
假設(shè)一個(gè)開發(fā)者在Anotherbranch分支實(shí)現(xiàn)一個(gè)sayHello方法,另外一個(gè)開發(fā)者在LastBranch中創(chuàng)建實(shí)現(xiàn)了sayByeBye方法,現(xiàn)在你需要將兩個(gè)人的工作合并到下一個(gè)穩(wěn)定版本中,想一想你需要怎么做?很簡單,按以下方法將改變從兩個(gè)分支中合并進(jìn)來:
首先,確保當(dāng)前活躍分支是master分支。
然后,打開Source Control > GitDemo – master > Merge From Branch…菜單,選擇AnotherBranch然后點(diǎn)擊Merge按鈕。
接下來會出現(xiàn)一個(gè)比較窗口,在里面你會看到合并之后代碼的更改,看一眼,感覺差不多了就再點(diǎn)擊Merge按鈕。
Xcode會詢問你是否保存項(xiàng)目的快照,點(diǎn)擊Enable按鈕。讓Xcode飛一會,然后就好啦。AnotherBranch里面添加的內(nèi)容已經(jīng)合并到master分支中。
使用同樣的方法來合并LastBranch。你會發(fā)現(xiàn)如果你不提交更改,Xcode不會讓你再次合并。于是,我們只好先提交一下。在比較窗口你會發(fā)現(xiàn)一個(gè)紅色的區(qū)域顯示合并之后的更改,而不是之前的藍(lán)色。這意味著分支中的代碼將會替換原先活動(dòng)分支中的代碼。
你可以輕松地避免這種現(xiàn)象的發(fā)生。在編輯面板的下面有幾個(gè)小按鈕,你可以試試他們都有什么作用,我選了第一個(gè),它的意思是master分支的代碼會被放在上面,另一個(gè)分支的代碼會跟在它后面。
處理接下來所有需要更改的代碼,不要有遺漏。完事后就點(diǎn)擊Merge按鈕。
恭喜你!你已經(jīng)成功的學(xué)會從多個(gè)分支合并了代碼,類似的情形你也應(yīng)該會了。
忽略更改(Discarding Changes)放棄不想要的代碼更改功能非常有用,只需輕輕一點(diǎn),自從上一次提交之后的更改都會被放棄。當(dāng)你在開發(fā)過程中發(fā)現(xiàn)出了大亂子,你想從上一個(gè)穩(wěn)定狀態(tài)重新開始時(shí),這個(gè)功能就派上用場啦。注意放棄更改這個(gè)功能沒有回頭路,點(diǎn)完之后你就沒有辦法再撤銷這個(gè)操作,所以,要小心使用??!
之前,當(dāng)我們在討論版本比較時(shí),我們學(xué)會了如何忽略某一部分更改的方法,下面,我們要學(xué)一下如何一下忽略自從上一次提交之后的所有更改。
為了測試這個(gè)功能,首先寫一些代碼打開ViewController.h ,添加一個(gè)公共方法聲明:
@interface ViewController : UIViewController
-(void)aVeryCoolMethod;
@end
現(xiàn)在,讓我們在ViewController.m中添加一個(gè)這個(gè)方法的實(shí)現(xiàn),簡單點(diǎn)就行:
-(void)aVeryCoolMethod{
NSLog("I'm feeling that you'll discard me... Really?");
}
如果你注意到Project Navigator,我們剛剛更改的文件旁邊有了一個(gè)M標(biāo)識,很好,我們想看看如果忽略這些更改,這些文件是否會回到更改之前的狀態(tài)。
這里有一個(gè)重要的細(xì)節(jié):你可以選擇忽略所有文件的更改,也可以選擇忽略單個(gè)文件的更改,這完全取決于你。如果你想忽略一個(gè)文件的更改,首先選定這個(gè)文件。在這個(gè)例子里,如果你只選擇ViewController.m文件然后打開Source Control菜單,你會在ViewController.m中發(fā)現(xiàn)Didcard Changes這個(gè)選項(xiàng)。類似的,如果你只選擇ViewController.h也是一個(gè)道理。然而,如果你想忽視這兩個(gè)文件的更改(這里假定有兩個(gè)以上的更改),就在Project Navigator中選中它們,然后再打開Source Control菜單。相應(yīng)的位置就會顯示Discard Changes in 2 Files,像下面這樣:
然而,這次我們不會使用這個(gè)按鈕,我們要用Discard All Changes。點(diǎn)擊它之后,一個(gè)確定提示框就會出現(xiàn),這是這部分Xcode防止你誤刪代碼的唯一措施。
點(diǎn)擊Discard All Changes, 那你剛才寫的那個(gè)公共方法就永遠(yuǎn)屬于過去了。看到了吧,只需幾步就可以讓你從當(dāng)前工作狀態(tài)恢復(fù)到之前的提交,所以我再一次提醒你要在使用Source Control 中小心點(diǎn),別誤點(diǎn)了這個(gè)按鈕。
總結(jié)通過這篇教程,我盡力詳述了在Xcode中進(jìn)行版本控制的方法。其實(shí)在幕后,真正起作用的是git----地球上應(yīng)用最多的版本控制系統(tǒng)。你可能注意到我在教程中并沒有過多的提到GitHub或者任何Xcode的一些功能----其實(shí)我是故意這樣的。我想把注意力集中在使用Xcode進(jìn)行g(shù)it管理的內(nèi)容上。只有當(dāng)你懂得了如何進(jìn)行版本控制之后,才能真正的使用GitHub。我想再重申一下,如果你是一個(gè)團(tuán)隊(duì)在工作,使用版本控制工具是必須的!如果你是單打獨(dú)斗,使用版本控制工具也是很有必要的,它可以為你花大量時(shí)間和精力所做的工作提供保障,并且在你添加新功能時(shí)可簡單地進(jìn)行擴(kuò)展。這個(gè)工具就像有些人說的那樣,一旦用了,就再也回不去了!最后,我希望這個(gè)教程會對你有用。