How to Avoid Merge Conflicts in Xcode Projects by Alex “Foxycorn” Nekrasov | October, 2022

The Xcode for Git project format can be uncomfortable. The xcodegen tool replaces it with simple YAML files.

Unsplash. Photo by Per Headway

Xcode is a very powerful IDE with a long history and a lot of features. But even after years of complaints from developers and low ratings on the App Store, Apple has yet to fix some of its core issues. One of them is the project file structure. I have already written an article about Xcode problems which you can see here.

Even if you use AppCode or export your project with another third-party tool, git (or other repositories) will encounter xcodeproj structure in general and pbxproj files in particular.

Instead of a JSON-style tree structure, Xcode uses its own proprietary format with auto-generated object IDs, which creates a lot of merge conflicts.

There are two ways to solve this problem:

  1. You can create a workspace and split your project into several smaller projects.
  2. You can generate a project with xcodegen And put it out of your repository.

In this article, I am going to describe the second way.

It’s a free and open-source tool that generates Xcode projects from a yaml description.

https://github.com/yonaskolb/XcodeGen. Xcodegen logo from

Project description files do not contain the entire structure. xcodegen YAML automatically looks for files from selected folders, following the rules defined in the file.

xcodegen Supports various goals, build settings, custom schemas, unit tests and many other features. Let’s review how it works.

how it works

First, you need to install xcodegen,

brew install xcodegen

Second, create a project.yaml file. You can either write your own configuration, or use an example from the official GitHub repository:

https://github.com/yonaskolb/XcodeGen

Finally, run:

xcodegen generate

In case of success, you will get a xcodeproj folder even if you didn’t have it before. Now you can open it with Xcode or AppCode.

layout

xcodegen There is a very rich configuration file. this is a yaml format and default name is project.yaml, The first line is usually the project name:

name: myproject

It defines the project name and the project file name. options Argument sets project-wide options:

options:
minimumXcodeGenVersion: 2.23
deploymentTarget:
iOS: "13.0"

The example above sets the minimum xcodegen Edition. You need to use the minimum version that supports all the features you want to use. New versions may add new options. The minified version should support all the options you use. deploymentTarget Sets the minimum platform version. The version number is different for each platform.

packages The option Swift Package Manager adds references to packages:

packages:
Yams:
url: https://github.com/jpsim/Yams
from: 2.0.0

You can list all SPM dependencies here, so later you can just reference them by name.

Configuration files may include other files:

include:
- config.yml

This can be used when you have some base configuration for multiple projects, or want to minify your main configuration file.

The most important configuration item is targets, It defines a list of targets (application, library, framework, unit test, etc.) with target-specific options.

targets:
myapp:
type: application
platform: iOS
sources:
- path: project_root
excludes:
- "*.md"
- path: project_additional_files
dependencies:
- target: mylib
- framework: SomeFramework.framework
- sdk: libc++.tbd
- package: Yams
settings:
PRODUCT_NAME: My Project
SWIFT_VERSION: 5.7
ENABLE_BITCODE: YES
mylib:
type: framework
platform: iOS
sources:
- path: library_path

This configuration is very straightforward. each goal has one typeis saying that it is a library, framework, application or other target. platform Defines the target platform, for example, iOS,

sources There is a list of paths to source files. they are relative to project.yaml file. You can exclude certain files using excludes list.

dependencies Set up a list of project dependencies. They can be targets of the same project, frameworks distributed as folders, static libraries, SPM packages, etc.

settings Include a list of app build settings. For example, header search path, ld flag, bitcode, swift version, and more. You can see the list of keys in the original Xcode project.

You can get full documents xcodegenOfficial GitHub repository of:

https://github.com/yonaskolb/XcodeGen

.gitignore

Since our main goal is to get rid of merge conflicts, you will need to exclude the project from the repository. If you use Git – and it is the most popular repository for Xcode projects – you need to add this line .gitignore file:

my-project.xcodeproj/

if you also use CocoaPods you can also delete Pods folder and workspace file:

my-project.xcworkspace/
Pods/

xcodegen with CocoaPods

xcodegen And CocoaPods can be used together. You need to generate a project first, then install pods:

xcodegen generate
pod install

You can write a simple script that runs these commands. If you use other autogenerated stuff, you can generate it in this script as well.

Generated project editing

It’s fine to edit a generated project for experiments, or to create and add files to the project. But keep in mind that every time you run xcodegen generate All changes will be discarded. so you need to change it project.yaml Before pushing your changes to the repository.

The only exception are files. When you create a new file with Xcode, it is visible in the file system. xcodegen Reads files from the file system, so they will still be visible in your project after regeneration.

xcodegen A very powerful tool covering all or almost all Xcode features. This helps to avoid merge conflicts and allows the project to be generated directly from the file tree without adding it to the project manually.

I recommend this tool for all teams with at least 2-3 developers working on the same project. Especially big projects.

Happy coding!

Leave a Comment