1. 程式人生 > >CocoaPods 版本管理衝突 解決

CocoaPods 版本管理衝突 解決

近期在專案中首次使用了CocoaPods。從軟體工程的角度來看,我對目前常見的CocoaPods使用方法有些意見,建議做一些改進。先說一下我建議的最佳實踐,後面再分析為什麼要這樣做。並且希望大家根據自己公司的情況,討論一下這幾項建議是否合理,一起搞出一份真正的“最佳實踐”。 CocoaPods的常見使用方法參見唐巧的文章《用CocoaPods做iOS程式的依賴管理》。在他的基礎上,我提出幾條補充。 1. CocoaPods生成的Pods目錄*不*加入.gitignore,也就是說,第三方庫的原始碼或binary要和產品程式碼一起,提交到公司內部的版本控制系統上。每次修改Podfile並執行pod update後,把Podfile、Podfile.lock、Pods目錄下的改動一併簽入。 2. 保證在任何時候只簽出一次程式碼就能直接編譯執行,不需要執行pod命令,甚至可以不裝CocoaPods就能參與開發。 3. Podfile裡所有的庫使用精確版本號,不使用任何’~> 1.0', ‘>= 1.0'之類的版本號語法,只使用精確的版本號如'1.3.2'。 4. 在專案開發過程中,可以每隔一段時間使用pod outdated命令手動檢查各第三方庫是否有更新。如果發現某個庫有新版本,去第三方庫主頁檢視更新記錄,並對版本變動做評估。如果確認有必要更新到最新版本,則修改Podfile裡的版本號到最新版本,執行pod update。 5. 如果兩個人同時修改了Podfile,第二個人git pull後發現有conflict,resolve順序是:不動其他檔案,先手動resolve Podfile的衝突;然後執行pod update;如果仍有衝突,可以用git reset把Podfile.lock和Pods目錄恢復原狀,再次執行pod update。此時應該沒有pod相關的衝突了。 ------------------------------------ 以下分析常見CocoaPods用法的問題,首先看CocoaPods官網上的示例Podfile。 source 'https://github.com/CocoaPods/Specs.git' pod 'AFNetworking', '~> 1.0' 這兩行的含義是,使用github上的pods spec,安裝AFNetworking 1.x系列最新的那個版本;如果AFNetworking還依賴於其他庫,自動安裝合適的版本。 假設現在我們的專案中要用到第三方庫XYZ,開發流程大致如下: 1. 專案建立者張三在自己機器上安裝好CocoaPods。 2. 張三執行pod init,在Podfile裡新增程式碼 pod 'XYZ', '~> 1.0'。執行pod install,把Podfile和Podfile.lock簽入程式碼管理,Pods目錄新增到.gitignore。 3. 專案開發人員李四安裝好CocoaPods。 4. 李四簽出程式碼,編譯,發現pod報錯。於是執行pod install後,重新編譯通過。 這樣的CocoaPods使用方法可能引發很多異常情況。考慮第一類場景: 1. Github突然被盾了(曾經發生過)、或公司的外網出口掛了,李四無法成功執行pod install,因此只能眼巴巴的看著專案程式碼,無法編譯。此時張三說,把我本地的Pods目錄都拷給你一份吧,雖然這樣拷來拷去容易出錯,但暫時先這樣臨時解決吧。 2. Github突然被盾了,公司的持續整合伺服器上無法執行pod install,也沒法給伺服器拷一份Pods目錄。於是連續多天無法用持續整合。 3. XYZ開發者在修改程式碼時,從git上刪除了最新版本的tag,並重新加tag到另一次commit上。於是張三和李四得到的XYZ程式碼是不同的。(雖然AFNetworking開發者很有經驗,不太可能出這種錯,但其他小的第三方庫就不一定了。)
4. 五年後,早就沒人使用古老的iOS 7了。XYZ開發者認為該庫是針對iOS 7的,技術已經太陳舊,於是從Github上刪除了該專案。(還好我們三年前就不再用這個庫了。)但某一天公司有個新專案,想參考以前的程式碼。當開啟程式碼執行pod install時,發現Github上已經沒有XYZ庫了。 以上情況可以歸結為:你的程式碼是否可用嚴重依賴於別人。你從公司的版本控制系統上獲取的程式碼不能直接編譯,還依賴於世界各地很多其他人是否正確配置了他們的程式碼,還依賴於Github等git服務商是否可用,等等。在極端情況下,會有災難性後果。 再看第二類場景: 5. 在我們專案的開發過程中,XYZ最新版本是1.4。一年後,我們重新開啟舊的專案程式碼,執行pod install,獲取到XYZ 1.x系列的最新版本1.7版。在XYZ 1.4到1.7版本之間,改變了一些介面和實現,我們的專案程式碼很有可能無法編譯,或無法正確執行。 這裡的問題是:常見的版本號寫法'~> 1.0’會在pod install或pod update時檢查版本更新,隨時將第三方庫升級到1.x系列的最新版本。對正在開發的專案來說,經常升級第三方庫是可以的。但對已經發布的產品程式碼,這個變動是不可接受的。已釋出的版本必須要有一份固定不變的程式碼,否則配置管理就失去了意義。 還有第三類場景: 6. 張三的CocoaPods安裝的很早,和李四機器上的不是同一版本。這兩個版本的CocoaPods對依賴規則的resolve演算法不同,因此李四pod install失敗,無法下載到和張三相同的第三方庫程式碼。這是真事,兩週前我們剛剛遇到了,後來解決方法是所有人都強制安裝某個舊版本的CocoaPods。 這裡的問題是:CocoaPods作為開發工具鏈中重要的一環,它的質量是否有保證?CocoaPods不是蘋果官方的工具,也不是像git那樣由極富經驗的人組織設計開發,我們能否信任它的版本相容性?具體來說,即不管用什麼版本的CocoaPods,pod install後得到基本相同的第三方庫。我們看到最近已經出了一個bug,如果時間再長點,三年後的CocoaPods會不會跟今天有較大差異? 對這個問題的一個解決方法是要求所有專案成員安裝相同版本的CocoaPods,甚至安裝相同版本的Ruby。但一個人需要同時參與多個專案的怎麼辦?問題的根源還是沒變。 ------------------------------------ 基於以上分析,我提議的“最佳實踐”解決了以下問題。 * Pods目錄簽入到版本控制系統,使產品程式碼沒有外部依賴,不管什麼時候都能從公司內網獲取一份可直接執行的程式碼。 * 已釋出版本的產品程式碼永久固定,不會隨時間而變化,方便追蹤問題和存檔。 * 不要求專案成員裝同樣版本的CocoaPods,甚至可以不裝CocoaPods。降低測試、設計人員使用程式碼的難度,也避免了CocoaPods本身相容性引起的問題。 歡迎討論。