如何在 Xcode 中正确使用 Git?

Posted

技术标签:

【中文标题】如何在 Xcode 中正确使用 Git?【英文标题】:How to use Git properly with Xcode? 【发布时间】:2011-02-06 14:33:56 【问题描述】:

我从事 iphone 开发人员已经有一段时间了,最​​近我在工作流程中加入了 git。到目前为止,我已将 http://shanesbrain.net/2008/7/9/using-xcode-with-git 上的 git 设置用于我的工作流程。

这些设置告诉 git 从合并中排除 *.pbxproj?这样做有真正的理由吗?例如,当我将文件添加到项目并推送到源时,我的开发人员在拉取时不会将该文件添加到他们的 xcode 项目中。然后,如果他们中的一个人构建了一个版本,这个文件可能不包括在内。我不应该让 git 处理项目文件的合并吗?为什么或为什么不应该合并此文件以及如何正确处理将文件添加到项目中的情况?

【问题讨论】:

我不使用 XCode,但是如果 *.pbxproj 文件类似于 Visual Studio 的 *.csproj 文件(有点像文件列表),那么这个设置对我来说似乎相当愚蠢。当两个人将文件添加到项目中并认为最好的解决方案是将所有内容都搞砸时,听起来有人厌倦了合并冲突...... XCode 的问题(不确定 Visual Studio)是 .pbxproj 文件几乎不可读,因此手动解决冲突没有意义。 *.pbxproj 文件实际上结构很好,你只是在块结束段和开始段之间有很长的延伸。可取之处在于该文件具有非常好的换行符,因此仅修改行就很难将其弄乱,并且自动合并通常效果很好。这也意味着合并块通常很容易理解 - 您可以看到一侧添加了几组文件,另一侧添加了不同的文件集。 【参考方案1】:

自 SDK 发布以来,我一直在全职开发 iPhone 应用程序,其中大部分时间都花在与多个开发人员的团队中。

事实是,禁止合并该 .pbxproj 文件比它有用的方式更有害。正如您所说,当您添加文件时,除非其他人获得该文件,否则他们还必须将其添加到他们的项目中 - 在任何大小的应用程序中,这很糟糕,而且它还带走了源代码控制的巨大好处,因为您仅通过 git 无法真正恢复到完整的早期项目状态。

.pbxproj 文件只是一个属性列表(类似于 XML)。根据经验,您遇到的唯一合并冲突是两个人同时添加文件。 99% 的合并冲突情况的解决方案是保留合并的两边,这对于 git 至少简单地涉及删除任何 >>>>、

#!/bin/sh

    projectfile=`find -d . -name 'project.pbxproj'`
    projectdir=`echo *.xcodeproj`
    projectfile="$projectdir/project.pbxproj"
    tempfile="$projectdir/project.pbxproj.out"
    savefile="$projectdir/project.pbxproj.mergesave"

    cat $projectfile | grep -v "<<<<<<< HEAD" | grep -v "=======" | grep -v "^>>>>>>> " > $tempfile
    cp $projectfile $savefile
    mv $tempfile $projectfile

最坏的情况是如果它失败(你要求 XCode 加载项目并且它加载失败),你只需删除 .pbxproj 文件,从 git 中签出 master,然后重新添加你的文件。但在使用这个脚本的许多个月里,我从未遇到过这种情况,我再次与其他几位开发人员一起全职开发 iPhone 应用程序。

您可以尝试使用替代脚本的另一个选项(在下面的 cmets 中指出)是将此行添加到 .gitattributes 文件中:

*.pbxproj text -crlf -diff -merge=union

然后 git 将始终对 .pbxproject 文件进行合并的双方,与我提供的脚本具有相同的效果,而无需任何额外工作。

最后,这是我完整的 .gitignore 文件,显示了我将它设置为忽略的内容,因为有一些你不想要的东西 - 在我的情况下,实际上只是 emacs 残余和整个构建目录:

# xcode noise
build/*
*.pbxuser
*.mode1v3
*~

# old skool
.svn

# osx noise
.DS_Store
profile

【讨论】:

您的 xcode 项目是否使用 .gitattributes 文件?并感谢您的洞察力。我认为将来尝试合并 pbxproj 文件会容易得多。 迄今为止我们还没有,虽然其中某些方面看起来很有趣 - 但与我共事的人不是高级 git 用户,因此对高级功能的倡导并不强烈。 “.pbxproj 文件只是 JSON(类似于 XML)。”实际上,它是一个 OpenStep 格式的属性列表。与 JSON 的基本思想相同,但语法在一些地方有所不同。 另一件事要尝试 - set merge=union: ***.com/questions/2729109/… 我同意 @KendallHelmstetterGelner 的观点,而不是运行您的脚本,这会删除那些特殊行,您可以使用 union 开关更新您的 .gitattribute:*.pbxproj text/plain -crlf -diff -merge union【参考方案2】:

这适用于我在 Xcode 4.6 和 Git 1.7.5 中。

添加并提交 .gitattributes 文件:

*.pbxproj binary merge=union

我已经和其他团队成员一起测试过,效果很好。

取自: http://robots.thoughtbot.com/post/33796217972/xcode-and-git-bridging-the-gap

【讨论】:

Merge=union 很好,但 mergepbx 工具应该是公认的答案。【参考方案3】:

坦率地说,现有的答案具有误导性。

如果你从不删除或重命名文件,那么使用merge=union 策略,直接结合不同提交的差异,是一个好主意。

但是,在现实世界中,我们有时确实需要删除或重命名文件。在没有任何修改的情况下合并差异会在这些情况下产生很多问题,这些问题通常会导致“工作区完整性 - 无法加载项目”问题,这让你甚至无法运行项目。

迄今为止我得到的最佳解决方案:

1) 设计好项目并在开头添加所有需要的文件,因此您很少需要更改project.pbxproj

2) 使您的特征变得微小。不要在一个分支中做太多事情。

3) 出于任何原因,如果您需要修改文件结构并在project.pbxproj 中遇到冲突,请使用您喜欢的文本编辑器手动解决它们。当您将任务缩小时,冲突可能很容易解决。

【讨论】:

【参考方案4】:

简短的回答是,即使您没有在.gitattributes 中包含该行,您也可能无法轻松合并 .pbxproj 的两个修改版本。 git 最好将其视为二进制文件。

详情请看这里:Git and pbxproj

更新:即使 git book still agrees 有这个答案,我也不再这样做了。我对.pbxproj 进行版本控制,就像任何其他非二进制源文件一样。

【讨论】:

听起来您可以设置一个提交过滤器以通过simplejson 或其他更简洁的方式将文件发送到索引。但仍不能保证它可以正常工作。 它不是 JSON 格式的文件。看起来很相似,但细节上有很多不同。 git book 里说的是它的JSON,但是貌似是错的。 git-scm.com/book/ch7-2.html 好的。 .pbxproj 文件实际上是一个老式的 NeXT/Cocoa PList 文件,它更老,并且比 JSON 更早定义,现在被 Apple 弃用。 (但他们在某些地方仍在使用它)书中提到的文件是完全错误的。我删除了反对票,因为你明确提到了。【参考方案5】:

我确实创建了一个可以处理 XCode 项目文件中的合并冲突的 Python 脚本。

如果你想尝试,可以在这里查看:https://github.com/simonwagner/mergepbx

您必须将其安装为合并驱动程序,因此当您的项目文件中存在合并冲突时,它会自动调用(README.md 将告诉您如何执行此操作)。

它应该比使用merge=union 工作得更好,因为mergepbx 理解您的项目文件的语义,因此可以正确解决冲突。

但是该项目仍处于 alpha 阶段,不要期望它能够理解所有的项目文件。

【讨论】:

以上是关于如何在 Xcode 中正确使用 Git?的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 中 Git 的配置与使用

在 git 文件重命名后使 Xcode 5 跟随历史

如何在 Xcode 中更改 Git 的用户名?

如何将 Xcode 与克隆的 git 存储库一起使用

如何理顺我的 Git 本地存储库(我使用了 XCode 的源代码控制)

如何使用 XCode 将新文件上传到 git 存储库?