2013年1月2日 星期三

Git : 動手做看看 - Xcode 裡的 Git

繼上篇我們了解檔案在 Git 管理的資料夾裡面的角色之後,來看一下 Xcode 是如何和 git 互動的。
首先開啟一個 Xcode project 選擇 Single View Application 如下圖。命名為 GitPractice 

選擇下一步,記得不要存在任何 git init 過的資料夾底下,要存在其他的資料夾,然後會有一個 source control 可以勾選。如下圖

接下來就會出現 Xcode 編輯的主畫面。如下 
看起來沒什麼特別的,我們用 Terminal 來檢視一下這個資料夾。
用 Terminal 移到這個 Xcode Project 的根目錄。
然後輸入
ls -al
會看到如下
total 16
drwxr-xr-x   6 chronoer  staff   204  1  2 19:20 .
drwx------+ 78 chronoer  staff  2652  1  2 19:18 ..
-rw-r--r--@  1 chronoer  staff  6148  1  2 19:20 .DS_Store
drwxr-xr-x  13 chronoer  staff   442  1  2 19:20 .git
drwxr-xr-x  13 chronoer  staff   442  1  2 19:17 GitPractice
drwxr-xr-x   5 chronoer  staff   170  1  2 19:17 GitPractice.xcodeproj
Xcode 自動對這個資料夾做了 git init 的動作了。我們再用
git log
來看看 Xcode 做了什麼事,會得到
commit 823888353b2d6d19426b56658b90db86f2f2ab8a
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 19:17:17 2013 +0800
    Initial Commit 
Xcode 己經幫我們把 Single View Application 的檔案都加入給 git 管理並 commit 目前狀態為歷史的節點了。
接下來我們要看一下git 的狀態用
git status
會得到如下的結果

# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# GitPractice.xcodeproj/project.xcworkspace/
# GitPractice.xcodeproj/xcuserdata/
nothing added to commit but untracked files present (use "git add" to track)
原來 Xcode 預設沒有把這兩個資料夾加入 git 管理。那到底我們需不需要這兩個資料夾裡面的東西加入呢?當然是不需要,這些都是 Xcode 的衍生物和源始碼沒有太大的關係。好,那就這樣放著不管嗎? untracked files,如果之後有新增的 file 是想要加入 git 管理,又忘了加入,這樣就會和這兩個資料夾被列在 git status 的結果,一旦檔案多了,就會把真的想要加入和不想加入的搞混了,好像不怎麼好。git 有沒有方式可以設定,不想要 git 管理又不要出現在 untracked files 這邊的方法?有。要新增一個檔案名為 .gitignore。
所以我們新增 .gitignore 和 .git 同一個目錄下。內容如下

*.xcworkspace/
xcuserdata/
對應到上方紅色的兩個目錄。接著我們要把新增的 .gitignore 加入 git 管理然後 commit 做一個歷史記錄如下輸入
git add .gitignore
然後 commit
git commit .gitignore -m "add ignore file"
這樣一來,再做一次
git status
就會看到
# On branch master
nothing to commit (working directory clean)
這樣 git 穩定的狀態
除了這兩個資料夾,還有沒有要忽略的?有的。
那是哪些?其實我也是從 github 裡找到比較有名的幾個 project 來參考的。如下列出來給大家參考

.DS_Store
.localized
# Build directory
build/
# XCode user specific files
xcuserdata/
*.xcworkspace/
*.mode1v3
*.mode2v3
*.perspectivev3
*.pbxuser
output
可以當成一個 Xcode project 用 Git 要忽略的範本了。請加到 .gitignore 。然後再一次 git add ,git commit。
加了 ignore 之後,我們來看Xcode 如何處理 modified file 。首先在 AppDelegate.m 的 application:didFinishLaunchingWithOptions: 新增程式碼。如下

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    NSLog(@"first line");
    return YES;
}
我們新增一行 code 在上面綠色之處。存好檔之後會在 Xcode 左邊 project navigator 欄看到在 AppDelegate.m 旁邊有一個小 m 的符號。如下圖。
代表這個 AppDelegate.m 有被修改過。此時,我們在 Terminal 輸入以下指令
git status
會看到

# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified:   GitPractice/AppDelegate.m
#
no changes added to commit (use "git add" and/or "git commit -a")
和之前用 Terminal 改變 file 的一樣情況。AppDelegate.m 變成了 unstaged file。所以我們要怎麼做?git add or 直接 git commit 是吧?那是在 Terminal 的情況下,如果用了 Xcode 這種比較方便的 IDE 都會整合起來,比如在現在的情況下,只要在 AppDelegate.m 按下右鍵然後選 source control -> commit selected files 如下圖
然後就會跳出另一個視窗讓我們輸入此次歷史節點的註解。如下圖。
主要分幾個部分,最左邊是有修改過的檔案,中間是目前修改過的程式碼,右邊是之前最後一次的 commit 記錄。還可以往下拉看看有什麼其他的地方不一樣的。藍色的框框是小紅槓,標示著目前和最近 commit 兩個檔案不同之處,底下的紅色框框,就是寫註解的地方。如果按下右下 commit 1 file 這個按鈕,就會看到 Xcode 裡 AppDelegate.m 這個旁的小m 不見了,代表是己經 commit 的穩定狀態。如下圖
再把鏡頭轉到 Terminal,目前為止我們利用 Xcode 很方便的工具做了 git commit 的動作,用 Terminal 檢視一下,輸入
git log
出現

commit 47454d43e92257d81a3a26ed1e8c69a5b4cbafbcAuthor: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:53:58 2013 +0800
    add first line
commit 00544060eb268857bda27c13f392feaeb3d9ed09
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:12:51 2013 +0800
    add ignore file
commit 823888353b2d6d19426b56658b90db86f2f2ab8a
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 19:17:17 2013 +0800
    Initial Commit
最上方就是最新的,也就是剛剛用 Xcode commit 的結果。
如果修改了很多個檔案才 commit ,比如我們在 AppDelegate.m 和 ViewController.m 都加一些程式碼如下,我們看到有兩個小m。


commit 的時候可以選擇多個檔案之後,再用剛剛的做法,或是在 menu 上面 File -> Source Control -> Commit 也可以一次把所有有修改的檔案列出來。如下圖
然後會出現寫註解的畫面,最左邊也會列出有多少個 File 需要被 commit 如下圖。


可以勾選,也可以一一檢查改變的地方。Commit 之後我們用 Terminal 來檢查狀態如下輸入。
git log
會看到

commit e5f66ee471d2944f6faabfaac8256e748c5df3b9
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 22:07:06 2013 +0800
    add code in appDelegate.m and ViewController.m
commit 47454d43e92257d81a3a26ed1e8c69a5b4cbafbc
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:53:58 2013 +0800
    add first line
commit 00544060eb268857bda27c13f392feaeb3d9ed09
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:12:51 2013 +0800
    add ignore file
commit 823888353b2d6d19426b56658b90db86f2f2ab8a
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 19:17:17 2013 +0800
    Initial Commit
然後再輸入
git status
會看到

# On branch master
nothing to commit (working directory clean)
這樣又回到常態了。
在編輯程式碼的時候隨時都可以和之前 commit 過的版本做個比較,要用到 Xcode 右上的按鈕,如下圖
比如我們選定 AppDelegate.m 然後按下上面的按鈕就會看到如下畫面

中間編輯區有兩大塊,左邊就是目前的狀態,右邊就是最近 commit 的狀態,因為剛剛 commit 完沒有修改所以兩邊看起來一樣,而且還可以比較目前的和之前 commit 的狀態,可以按下上圖紅色地方,會長出一條黑黑的有很多間格。如下

然後可以變動圖中右邊的白色三角形,上圖紅色處,就可以看到之前 commit 版本和現在不一樣,移動到如下圖
如紅色所框左邊的 line 17 是和之前不一樣的地方。
還記得我們曾用 Terminal 利用
git checkout <commit id> <file name>
回到之前 commit 的版本吧?目前 Xcode 4 還沒支援直接 checkout 到舊的版本,不過可以從上圖看到某個版本的一些資訊包含 commit id ,然後再回到 Terminal 來 checkout 到舊的版本。
如下圖,mouse 移到中間白色橫槓,就會變大,然後出現資訊。
這就是 Xcode 的 Git 對檔案的基本操作,目前為止我們把所有檔案版存在 .git 檔裡,之後會再討論怎麼和 Server 溝通。我們下次見。