關于 Podfile.lock 帶來的痛

原文地址:http://www.samirchen.com/about-podfile-lock/

發生了什么

你加入一個 iOS 項目,根據小伙伴給你的 git 倉庫地址把代碼 clone 下來,在項目目錄下 ls -al 看一下:

1.  `$ ls -al`
2.  `.`
3.  `..`
4.  `.DS_Store`
5.  `.git`
6.  `.gitignore`
7.  `Podfile`
8.  `TestProject`
9.  `TestProject.xcodeproj`
10.  `TestProject.xcworkspace`

項目用了 CocoaPods 來管理依賴庫,于是你找到 Podfile 所在的目錄,執行 pod install 命令安裝依賴庫,一切都很正常。

  • 先別看我:
  • A: (Podfile.lock(A), Manifest.lock(A))
  • Server: (Podfile.lock(無), Manifest.lock(無))
  • Me: (Podfile.lock(Me), Manifest.lock(Me))

直到你安裝完依賴庫后,用 git status 命令看了一下本地 git 倉庫的狀態,發現提示:


1.  `$ git status`
2.  `(use  "git add <file>..." to update what will be committed)`
3.  `(use  "git checkout -- <file>..." to discard changes in working directory)`

5.  `modified:  Podfile.lock`

7.  `no changes added to commit (use  "git add"  and/or  "git commit -a")`

你開始疑惑:我就安裝了一下依賴庫,啥都沒干呢,Podfile.lock 是什么鬼?算了,不管了,先 Run 一下項目再說,嗯,沒啥嘛,一切正常,項目成功跑起來了。上網搜了下 Podfile.lock,原來是用來鎖定項目依賴庫版本的文件。趕緊 git commitgit push 把 Podfile.lock 加入 git 管理,并提交到公共庫。

  • 先別看我:
  • A: (Podfile.lock(A), Manifest.lock(A))
  • Server: (Podfile.lock(Me), Manifest.lock(無))
  • Me: (Podfile.lock(Me), Manifest.lock(Me))

寫了兩天代碼,小伙伴告訴你項目代碼更新了需要同步一下,于是你 git commitgit pull,還好,合并正常。

  • 先別看我:
  • A: (Podfile.lock(A), Manifest.lock(A))
  • Server: (Podfile.lock(A), Manifest.lock(無))
  • Me: (Podfile.lock(A), Manifest.lock(Me))

這時候你準備 Build 一下項目,卻發現 Xcode 在報錯:

1.  `PhaseScriptExecution  Check  Pods  Manifest.lock...`
2.  `...`
3.  `error:  The sandbox is  not  in sync with the Podfile.lock.  Run  'pod install'  or update your CocoaPods installation.`

又是 Podfile.lock 這鬼?等等,還有 Manifest.lock 又是啥?

Podfile.lock 是啥

Podfile.lock 文件主要包含三個塊:PODSDEPENDENCIESSPEC CHECKSUMS,用來記錄每個pod的版本號、依賴的其他庫和每個庫對應的podspec.json文件的 checksum(SHA-1算法)。通過這些信息可以確保多人協作的時候,大家使用的是相同版本的第三方庫。

Podfile.lock 是在第一次運行 pod install 時生成的,Podfile.lock 中會標注項目當前依賴庫的準確版本,其中包括了項目在 Podfile 中直接標注使用的庫,以及這些庫依賴的其他庫。這樣的好處是當你跟小伙伴協同開發時,你的小伙伴同步了你的 Podfile.lock 文件后,他執行 pod install 會安裝 Podfile.lock 指定版本的依賴庫,這樣就可以防止大家的依賴庫不一致而造成問題。因此,CocoaPods 官方強烈推薦把 Podfile.lock 納入版本控制之下。

但是,Podfile.lock 并不是一成不變的,當你修改了 Podfile 文件里使用的依賴庫或者運行 pod update 命令時,就會生成新的 Podfile.lock 文件。

所以,協同開發時需要注意使用 pod installpod update 的區別:

  • 使用 pod install,你只會安裝 Podfile 中新改變的東西,并且會:優先遵循 Podfile 里指定的版本信息;其次遵循 Podfile.lock 里指定的版本信息來安裝對應的依賴庫。比如:下面在 Podfile 里沒指定 iRate 的版本,但是 Podfile.lock 里指定了 iRate 的版本是 1.11.1,那么即使現在有最新的 1.11.4,最終也會安裝 1.11.1。但是如果 Podfile 里指定了 iRate 版本是 1.11.3,那么則會安裝 1.11.3,并更新 Podfile.lock 里的信息。
> 
> 1.  `// Podfile`
> 2.  `pod 'iRate'`
> 
> 4.  `// Podfile.lock`
> 5.  `PODS:`
> 6.  `- iRate (1.11.1)`
> 
> 8.  `DEPENDENCIES:`
> 9.  `- iRate`
> 
> 11.  `SPEC CHECKSUMS:`
> 12.  `iRate:  178e61bf5610493c363e2819056cf1a186b9ebd9`
> 
> 14.  `COCOAPODS:  0.35.0`
> 
  • 使用 pod update,你會根據 Podfile 的規則更新所有依賴庫,不會理睬現有的 Podfile.lock,而是根據安裝依賴庫的情況生成新的 Podfile.lock 文件。

Manifest.lock 又是啥

Manifest.lock 是 Podfile.lock 的副本,每次只要生成 Podfile.lock 時就會生成一個一樣的 Manifest.lock 存儲在 Pods 文件夾下。在每次項目 Build 的時候,會跑一下腳本檢查一下 Podfile.lock 和 Manifest.lock 是否一致:

[圖片上傳中...(image-161986-1528042688816-0)]

如果不一致,你就會看到第一節說到的報錯了:

1.  `PhaseScriptExecution  Check  Pods  Manifest.lock...`
2.  `...`
3.  `error:  The sandbox is  not  in sync with the Podfile.lock.  Run  'pod install'  or update your CocoaPods installation.`

這樣做的原因是 Pods 目錄并不總是被放到版本控制之下,有了這個檢查機制就能保證開發團隊的各個小伙伴能在運行項目前更新他們的依賴庫,并保持這些依賴庫的版本一致,從而防止在依賴庫的版本不統一造成程序在一些不明顯的地方編譯失敗或運行崩潰。

到底發生了什么

說清楚了 Podfile.lock 和 Manifest.lock 到底是什么,現在我們回頭再看看第一節到底發生了什么。現在你可以看第一節里的各種類似下面的信息了:

  • A: (Podfile.lock(A), Manifest.lock(A))
  • Server: (Podfile.lock(無), Manifest.lock(無))
  • Me: (Podfile.lock(Me), Manifest.lock(Me))

這些記錄是小伙伴 A、代碼服務器 Server 和自己本地 Me 這三個地方的 Podfile.lock、Manifest.lock 在不同場景下的版本狀態。

第一個問題:

  • 你第一次 git clone 項目下來后,pod install 安裝依賴庫,為什么 git status 會提示說你修改了 Podfile.lock 文件?
  • 這是因為你的小伙伴并沒有把 Podfile.lock 納入版本控制,你 clone 下來的代碼一開始就沒有 Podfile.lock,所以你 pod install 的時候,會生成一份 Podfile.lock,并在 Pods 文件夾下生成它的副本 Manifest.lock。 Pods 文件夾這時候一般被 .gitignore 忽略了,但是 Podfile.lock 文件卻沒被忽略,文件夾下出現了新增的 Podfile.lock 文件,所以 git 會提醒你那些信息。這時候三個地方的 Podfile.lock、Manifest.lock 的狀態是這樣的:
    • A: (Podfile.lock(A), Manifest.lock(A))
    • Server: (Podfile.lock(無), Manifest.lock(無))
    • Me: (Podfile.lock(Me), Manifest.lock(Me))

第二個問題:

  • 你寫了幾天代碼后,同步了小伙伴線上的代碼后為什么會 Build 報錯?
  • 這是因為你把 Podfile.lock 文件加入了版本控制,然后你的小伙伴提交代碼時就會提交他本地的 Podfile.lock 文件到代碼服務器。你同步后你們的 Podfile.lock、Manifest.lock 的狀態是這樣的:
    • A: (Podfile.lock(A), Manifest.lock(A))
    • Server: (Podfile.lock(A), Manifest.lock(無))
    • Me: (Podfile.lock(A), Manifest.lock(Me))
  • 這時你的 Podfile.lock 文件更新了,但是本地的 Manifest.lock 卻沒有,二者不一致所以報錯了。
  • 這里就引出了一個新問題,你們的 Podfile 是同步一致的呀,那為什么你們倆的 Podfile.lock 會不一樣呢?
  • 造成這種情況的一個可能性是你們的 Podfile 里的一些 pod 語法并沒有指定明確的依賴版本,或者你直接使用的依賴庫在它們更深層的依賴關系鏈中沒有指定明確的版本。而你們倆 pod install 安裝依賴庫是在不同的時間點,這兩個時間點的直接依賴庫或間接依賴庫的最新版本可能發生了變化,所以你們安裝了不一樣的依賴版本,那么 Podfile.lock 的記錄就不一樣了。建議可以執行 pod repo update 更新一下 spec repo,再 pod install。

除了上面這些問題,另外再提醒一下:注意 pod installpod update 的區別。如果不合理的使用 pod update 也可能會給你帶來一些困惑。

Podfile.lock 沖突問題

之前公司項目中使用了FBRetainCycleDetector這個第三方庫來檢查內存泄露,在升級到某一個版本后,出現部分同事的 podfile.lock中FBRetainCycleDetector的checksum 值不一致,每次都需要運行 pod install 來更新 podfile.lock,然后git push 到倉庫。其他的同事又出現 podfile.lock 沖突,需要運行 pod install 更新,然后push到 git 倉庫。

喜劇上演多次后,我們采取少數服從多數的原則,讓出現沖突的同事git push 的時候手動去掉 podfile.lock。

項目中遇到的是 podfile.lockchecksum 部分的沖突,其實就是由于FBRetainCycleDetector.podspec.json文件的checksum不一致。

通過對比了有沖突的同事 mac 中生產的FBRetainCycleDetector.podspec.json文件,發現主要是repuires_arc 字段中的文件列表順序不同。

在找到問題產生的原因后,就著手解決問題:

一開始懷疑是MAC的 locale 不同導致文件的排序不一致,因為之前使用翻譯腳本來做文件排序的時候,也出現過類似的問題。

但是在設置了 locale環境變量之后,問題還是沒有解決。

前兩天,在FBRetainCycleDetector的 issues 列表中,發現也有人遇到了相同的問題,更加可喜的是,這個小伙子提了一個 PR 修復了這個問題,其實只有一行代碼:

image.png

問題是如何解決的:

在運行pod install后,生成FBRetainCycleDetector.podspec.json文件中, repuires_arc字段是需要設置-fno-objc-arc的文件列表,但是不知道某種原因,出現文件路徑排序在不同電腦上不同,從而導致最后FBRetainCycleDetector.podspec.jsonCHECKSUMS(SHA-1)值不一致。

使用 sort 方法后,解決了文件排序問題

怎么對待 Podfile.lock

那么究竟該怎樣對待 Podfile.lock 呢?以下建議可供參考:

  • Podfile.lock 應該加入版本控制,保證小伙伴們的依賴庫版本一致,防止出現難以發現的 bug。另外,在初始創建項目的時候就應該加入版本控制。
  • Podfile 的語法最好能盡量嚴謹,最好指定明確的依賴庫版本。
  • 理解 pod installpod update 的區別以及它們對 Podfile.lock 的影響,合理使用。一般就是多用 pod install,在需要時使用 pod update

參考:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容