3

我正在启动一个新项目,该项目将有多个开发人员使用 Git 在 Xcode 中工作。我想设置自动递增的内部版本号,并且我找到了一些关于如何做到这一点的好答案,但我担心的是多个开发人员和 Git。

我知道在 Xcode 中有一些文件,比如项目文件,非常敏感且难以合并。我见过的自动递增内部版本号的最佳技术很容易受到相同的多个 Git 合并问题的影响。

这里有没有关于如何使用自动增量构建技术并且仍然将合并问题保持在最低限度的指导?也许答案是没有好的答案,但我想了解其他人在做什么。

4

3 回答 3

4

所以首先感谢 harald 的回答和评论,这帮助我更好地思考我真正想要完成的事情。

让我总结一下我的想法,我意识到我想做什么,以及我是如何做到的。

我想要一种以自动方式填充内部版本号(CFBundleVersion)的方法。该值存储在源代码控制的主项目 -Info.plist 文件中。我担心遵循指南通过“构建阶段”脚本自动执行此操作,因为它会为可能的多个开发人员修改此文件,并导致需要不断合并的情况。

我想要这个的原因是我可以很容易地跟踪特定构建的代码。虽然当然可以通过标记和适当的文档手动执行此操作,但我想要一种更自动化和更灵活的方式,因为我认为我将对 TestFlight 进行大量构建。

我最初的想法是为这个值使用一个简单的增量内部版本号,但这确实会给合并带来麻烦。Harald 关于在 Git repo 上使用提交 SHA 的建议引发了我更好的思路。

所以我的解决方案的第一部分是使用提交 SHA 的前 9 个字符(SHA 太长)。我使用前 9 个字符,因为我正在运行 GitLab HQ(顺便说一下,这是一个很棒的开源项目),并且他们在显示提交的运行流时使用了前 9 个字符。得到我的命令如下:

/usr/bin/git rev-parse --short=9 HEAD

为了避免出现 Git 合并问题,我想到了首先更改项目 -Info.plist 文件中的构建号 (CFBundleVersion) 值,允许构建运行,然后在最后一步将值更改回默认值1 这样它就不会在源代码管理中出现更改。我尝试了使用“运行脚本”在“构建阶段”流程中执行此操作的所有方法,但似乎即使在最后一步中放入代码以恢复值,它也会影响正在运行的应用程序。

在深入挖掘之后,我发现了模式以及前置动作和后置动作。这似乎是我的路线。

因此,在架构中,对于“构建”计划,我创建了一个前置操作,将 CFBundleVersion 值设置为我当前的提交 ID(9 个字符),并且在后置操作中我会将这个值恢复为默认值(1)。这似乎可以按我的需要工作。

这是我的预操作代码:

buildPlist="$SRCROOT/$INFOPLIST_FILE"
echo "The build plist file $buildPlist"

CFBundleVersion="$(cd $SRCROOT;/usr/bin/git rev-parse --short=9 HEAD)"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CFBundleVersion" $buildPlist

这是我的事后代码:

buildPlist=$"$SRCROOT/$INFOPLIST_FILE"
CFBundleVersion=1
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CFBundleVersion" $buildPlist

这段代码与我在“构建阶段”脚本中使用的代码不同,需要注意的是需要使用 $SRCROOT 来设置目录。最初我的印象是您会获得与“构建阶段”中相同的构建设置,但您似乎没有。“运行脚本”窗口中有一个名为“从:提供构建设置”的选项,它允许您选择一个目标。也许这是正确的,无论给定预先操作,您都必须设置完整的目录路径。我花了一点时间才弄清楚这一点,所以我想我会提到它。


总之,我很欣赏我收到的信息,它帮助我思考我想要做什么并最终达到我想要的目标。

于 2012-11-12T01:03:57.093 回答
1

虽然我并没有真正看到线性递增构建编号试图跟踪像 git 这样的非线性开发模型的意义,但有一些方法可以实现它。这取决于你所追求的。如果您只想要“官方”构建的构建号,您可以在构建时通过构建脚本简单地生成它。然后让构建脚本标记使用生成的编号构建的提交。像这样的东西:

git checkout build-branch
generate_build_num > buildnum.txt
make
git tag `cat buildnum.txt`

生成唯一的、递增的内部版本号的责任在于generate_build_num脚本,您始终可以通过使用标签找到相应的提交。

另一方面,如果您希望 git 树中的每个提交都对应一个线性内部版本号,那么您需要做更多的工作。

在我看来,与直接使用 sha1 相比,这并没有什么好处。

于 2012-11-10T16:25:42.480 回答
-1

我使用稍微不同的方法来避免与在每个构建中触摸 Info.plist 相关的合并冲突。它类似于 magnusMTB 临时设置(然后重置)内部版本号的策略,但我没有使用前置和后置操作,而是在项目的 Info.plist 中留下一个占位符值,然后添加一个“运行脚本”构建阶段只修改产品的内部版本号而不触及 Xcode 项目的副本。

脚本如下所示:

# Grab some environment variables from Xcode
BUILD_NUMBER_FILE="${SOURCE_ROOT}/BuildNumber"
PLIST_FILE="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Info.plist"

# Create a build string
# Anything goes, but this uses my employer's App_vX_YYMMDD.HHMM format
majorVersion=`/usr/libexec/PlistBuddy -c "PRINT:CFBundleShortVersionString" "$PLIST_FILE"`
dateTime=`date "+%y%m%d.%H%M"`
buildNumber=App\_v$majorVersion\_$dateTime

# Write the build string to a local file under version control
echo $buildNumber > $BUILD_NUMBER_FILE

# Set the build number in the product's plist (Not the Xcode project's plist)
echo Writing generated build number \"$buildNumber\" to \"$PLIST_FILE\"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$PLIST_FILE"

这样,版本控制下的 Info.plist 保持不变,但用于测试或部署的应用程序内部的内部版本号是“正确的”动态生成的值。内部版本号通过与 Info.plist 分开的单个干净合并文件保留在版本控制中。

警告:我不确定内部版本号是否被烘焙到 Info.plist 之外的二进制文件中。这可能会产生问题。但是,对于它的价值,我正在测试的应用程序会从其捆绑包中的 Info.plist 中自我报告正确的(脚本生成的)内部版本号。

于 2013-09-09T15:35:37.957 回答