好幾年前我曾經寫過一篇讓 Xcode 專案易於版本控制的方法,它非常的好用,我也在多個專案裡頭使用這樣的配置用了好多年,都沒有出過什麼問題。
直到最近遇到了 SwiftUI 的 Preview 功能。
猜測可能是因為原先的設定是在 Build phase 去執行排序的 script,導致它破壞了 SwiftUI Preview 的一些機制,我想到了幾個解法,像是
- 不要放在 Build phase,放到 Run phase 去執行。
- 改用 XcodeGen 之類的工具產生 project file。
- 使用 git hook 的 pre-commit 來執行排序。
- 不要用,等真的遇到 merge conflict 了再說 lol
最後我選擇了 pre-commit 的做法。
如同在讓 Xcode 專案易於版本控制的方法這篇提到的,我的腳本都放在專案根目錄底下的 Scripts
目錄裡頭。
1.
首先建立一個 pre-commit.sh
放在 Scripts
目錄裡,它會檢查修改的檔案有沒有 project.pbxproj
檔,有的話就排序它然後把它加回 git 版控,這樣我們就不用再手動加一次。檔案內容如下:
#!/bin/sh
#
# Following script is to sort Xcode project files, and add them back to version control.
# The reason to sort project file is that it can reduce project.pbxproj file merging conflict possibility.
#
echo 'Sorting Xcode project files'
GIT_ROOT=$(git rev-parse --show-toplevel)
script_name="$GIT_ROOT/Scripts/sort-Xcode-project-file"
modifiedProjectFiles=( $(git diff --name-only --cached | grep "project.pbxproj") )
for filePath in ${modifiedProjectFiles[@]}; do
fullFilePath="$GIT_ROOT/$filePath"
perl $script_name $fullFilePath
git add $fullFilePath
done
echo 'Done sorting Xcode project files'
exit 0
2.
我把這個檔案放在 Scripts
目錄裡而不是直接去修改 .git/hooks/pre-commit
檔的原因是因為這樣才可以把它加入版本控管,讓團隊其他成員也可以用。所以現在我們需要一個方法讓 pre-commit
執行這個檔案,我在 Scripts
目錄底下新增了一個 install-git-hooks.sh
並 chmod +x
讓它可以被執行,內容如下:
#!/bin/bash
GIT_ROOT=$(git rev-parse --show-toplevel)
HOOKS_PATH=$(git rev-parse --git-dir)/hooks
if [ ! -d "$HOOKS_PATH" ]; then
mkdir "$HOOKS_PATH"
fi
ln -s -f "$GIT_ROOT/Scripts/pre-commit.sh" "$HOOKS_PATH/pre-commit"
chmod +x "$HOOKS_PATH/pre-commit"
echo "git hooks installed!"
這樣就可以建立 symbolic link 了。因為目前只有一個 pre-commit.sh
,所以這個安裝腳本寫得很簡單,日後如果要安裝的 hook 變多了再來調整就好。