原文地址:http://www.samirchen.com/about-podfile-lock/
發(fā)生了什么
你加入一個 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 所在的目錄枫攀,執(zhí)行 pod install
命令安裝依賴庫偎快,一切都很正常禽笑。
- 先別看我:
- A: (Podfile.lock(A), Manifest.lock(A))
- Server: (Podfile.lock(無), Manifest.lock(無))
- Me: (Podfile.lock(Me), Manifest.lock(Me))
直到你安裝完依賴庫后入录,用 git status
命令看了一下本地 git 倉庫的狀態(tài),發(fā)現提示:
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 commit
小泉、git 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 commit
分预、git pull
兢交,還好,合并正常笼痹。
- 先別看我:
- A: (Podfile.lock(A), Manifest.lock(A))
- Server: (Podfile.lock(A), Manifest.lock(無))
- Me: (Podfile.lock(A), Manifest.lock(Me))
這時候你準備 Build 一下項目配喳,卻發(fā)現 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
文件主要包含三個塊:PODS、DEPENDENCIES救赐、SPEC CHECKSUMS涧团,用來記錄每個pod的版本號、依賴的其他庫和每個庫對應的podspec.json文件的 checksum(SHA-1算法)。通過這些信息可以確保多人協(xié)作的時候泌绣,大家使用的是相同版本的第三方庫钮追。
Podfile.lock 是在第一次運行 pod install
時生成的,Podfile.lock 中會標注項目當前依賴庫的準確版本阿迈,其中包括了項目在 Podfile 中直接標注使用的庫元媚,以及這些庫依賴的其他庫。這樣的好處是當你跟小伙伴協(xié)同開發(fā)時仿滔,你的小伙伴同步了你的 Podfile.lock 文件后惠毁,他執(zhí)行 pod install
會安裝 Podfile.lock 指定版本的依賴庫,這樣就可以防止大家的依賴庫不一致而造成問題崎页。因此鞠绰,CocoaPods 官方強烈推薦把 Podfile.lock 納入版本控制之下。
但是飒焦,Podfile.lock 并不是一成不變的蜈膨,當你修改了 Podfile 文件里使用的依賴庫或者運行 pod update
命令時,就會生成新的 Podfile.lock 文件牺荠。
所以翁巍,協(xié)同開發(fā)時需要注意使用 pod install
和 pod update
的區(qū)別:
- 使用
pod install
,你只會安裝 Podfile 中新改變的東西休雌,并且會:優(yōu)先遵循 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 的規(guī)則更新所有依賴庫,不會理睬現有的 Podfile.lock燕垃,而是根據安裝依賴庫的情況生成新的 Podfile.lock 文件枢劝。
Manifest.lock 又是啥
Manifest.lock 是 Podfile.lock 的副本,每次只要生成 Podfile.lock 時就會生成一個一樣的 Manifest.lock 存儲在 Pods 文件夾下卜壕。在每次項目 Build 的時候您旁,會跑一下腳本檢查一下 Podfile.lock 和 Manifest.lock 是否一致:
[圖片上傳中...(image-161986-1528042688816-0)]
如果不一致,你就會看到第一節(jié)說到的報錯了:
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 目錄并不總是被放到版本控制之下印叁,有了這個檢查機制就能保證開發(fā)團隊的各個小伙伴能在運行項目前更新他們的依賴庫被冒,并保持這些依賴庫的版本一致军掂,從而防止在依賴庫的版本不統(tǒng)一造成程序在一些不明顯的地方編譯失敗或運行崩潰。
到底發(fā)生了什么
說清楚了 Podfile.lock 和 Manifest.lock 到底是什么昨悼,現在我們回頭再看看第一節(jié)到底發(fā)生了什么』茸叮現在你可以看第一節(jié)里的各種類似下面的信息了:
- 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 在不同場景下的版本狀態(tài)终议。
第一個問題:
- 你第一次
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 的狀態(tài)是這樣的:- 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 的狀態(tài)是這樣的:
- 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
安裝依賴庫是在不同的時間點,這兩個時間點的直接依賴庫或間接依賴庫的最新版本可能發(fā)生了變化漾峡,所以你們安裝了不一樣的依賴版本攻旦,那么 Podfile.lock 的記錄就不一樣了。建議可以執(zhí)行pod repo update
更新一下 spec repo生逸,再 pod install牢屋。
除了上面這些問題且预,另外再提醒一下:注意 pod install
和 pod update
的區(qū)別。如果不合理的使用 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.lock
中 checksum 部分的沖突,其實就是由于FBRetainCycleDetector.podspec.json
文件的checksum不一致念搬。
通過對比了有沖突的同事 mac 中生產的FBRetainCycleDetector.podspec.json
文件从藤,發(fā)現主要是repuires_arc 字段中的文件列表順序不同。
在找到問題產生的原因后锁蠕,就著手解決問題:
一開始懷疑是MAC的 locale
不同導致文件的排序不一致夷野,因為之前使用翻譯腳本來做文件排序的時候,也出現過類似的問題荣倾。
但是在設置了 locale
環(huán)境變量之后悯搔,問題還是沒有解決。
前兩天舌仍,在FBRetainCycleDetector的 issues 列表中妒貌,發(fā)現也有人遇到了相同的問題,更加可喜的是铸豁,這個小伙子提了一個 PR 修復了這個問題灌曙,其實只有一行代碼:
問題是如何解決的:
在運行pod install
后,生成FBRetainCycleDetector.podspec.json
文件中节芥, repuires_arc
字段是需要設置-fno-objc-arc
的文件列表在刺,但是不知道某種原因,出現文件路徑排序在不同電腦上不同头镊,從而導致最后FBRetainCycleDetector.podspec.json
的CHECKSUMS(SHA-1)
值不一致蚣驼。
使用 sort
方法后,解決了文件排序問題
怎么對待 Podfile.lock
那么究竟該怎樣對待 Podfile.lock 呢相艇?以下建議可供參考:
-
Podfile.lock
應該加入版本控制颖杏,保證小伙伴們的依賴庫版本一致,防止出現難以發(fā)現的 bug坛芽。另外留储,在初始創(chuàng)建項目的時候就應該加入版本控制翼抠。 -
Podfile
的語法最好能盡量嚴謹,最好指定明確的依賴庫版本获讳。 - 理解
pod install
和pod update
的區(qū)別以及它們對 Podfile.lock 的影響机久,合理使用。一般就是多用pod install
赔嚎,在需要時使用pod update
膘盖。