Как правильно использовать Git с Xcode?

94

Некоторое время я был разработчиком iphone, и недавно я включил git в свой рабочий процесс. До сих пор я использовал настройки git, найденные на http://shanesbrain.net/2008/7/9/using-xcode-with-git для своего рабочего процесса.

Эти настройки говорят git исключить * .pbxproj из слияний? Есть ли для этого настоящая причина? Например, когда я добавляю файл в проект и отправляю его в источник, мои коллеги-разработчики не будут добавлять этот файл в свой проект xcode, когда они его извлекают. Тогда, если один из них соберет релиз, этот файл может не быть включен. Разве я не должен просто позволить git обрабатывать слияния для файла проекта? Почему или почему этот файл не должен быть объединен и как правильно справиться с ситуацией, когда файлы добавляются в проект?

Рикхаррисон
источник
9
Я не работаю с XCode, но если файлы * .pbxproj чем-то похожи на файлы * .csproj Visual Studio (что-то вроде списка файлов), этот параметр мне кажется довольно идиотским. Похоже, кто-то устал от конфликтов слияния, когда два человека добавили файлы в проект и решили, что лучшим решением будет все испортить ...
Р. Мартинью Фернандес
Проблема с XCode (не уверен в Visual Studio) в том, что файлы .pbxproj плохо читаются человеком, поэтому нет смысла разрешать конфликты вручную.
Том
7
Файлы * .pbxproj на самом деле довольно хорошо структурированы, у вас просто есть длинные промежутки между концом блока и начальным сегментом. Изящество экономии заключается в том, что в файле очень хорошо размещены разрывы строк, поэтому сложно его испортить, просто изменив строки, и автоматическое объединение обычно работает очень хорошо. Это также означает, что блоки слияния, как правило, легко понять - вы можете видеть одну сторону с несколькими добавленными наборами файлов, а другую - с добавленными другими наборами файлов.
Кендалл Хельмштеттер Гельнер

Ответы:

136

С момента запуска SDK я работал над приложениями для iPhone все время, большую часть времени проводил в командах с несколькими разработчиками.

По правде говоря, запретить слияние этого файла .pbxproj гораздо вреднее, чем полезно. Как вы говорите, когда вы добавляете файл, если другие люди не получат этот файл, они также должны добавить его в свой проект - в приложении любого размера это отстой, а также лишает вас огромного преимущества контроля исходного кода в том, что вы не может вернуться к полному предыдущему состоянию проекта только через git.

Файл .pbxproj - это просто список свойств (аналогичный XML). По опыту можно сказать, что ЕДИНСТВЕННЫЙ конфликт слияния, который вы когда-либо возникали, - это когда два человека добавляли файлы одновременно. Решением в 99% случаев конфликта слияния является сохранение обеих сторон слияния, что для git, по крайней мере, просто включает удаление любых строк >>>>, <<<< и ====. На самом деле это настолько распространено, что я создал простой сценарий оболочки для исправления файла .pbxproj в состоянии слияния из 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 и повторно добавляете свои файлы. Но у меня никогда не случалось этого за многие месяцы использования этого скрипта, когда я снова работаю над приложениями для iPhone с несколькими другими разработчиками.

Другой вариант (указанный в комментариях ниже), который вы можете попробовать использовать вместо скрипта, - это добавить эту строку в файл .gitattributes:

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

Тогда git всегда будет использовать обе стороны слияния файлов .pbxproject, имея тот же эффект, что и предоставленный мной скрипт, только без дополнительной работы.

Наконец, вот мой полный файл .gitignore, показывающий, что у меня есть, он настроен на игнорирование, так как есть несколько вещей, которые вам не нужны - в моем случае действительно просто остатки emacs и весь каталог сборки:

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

# old skool
.svn

# osx noise
.DS_Store
profile
Кендалл Хельмштеттер Гельнер
источник
3
Вы вообще используете файл .gitattributes для своего проекта xcode? И спасибо за понимание. Я думаю, что в будущем будет намного проще попробовать объединить файлы pbxproj.
rickharrison
1
На сегодняшний день мы не были, хотя некоторые аспекты этого выглядят интересными, но люди, с которыми я работал, не были продвинутыми пользователями git, поэтому защита расширенных функций не является сильной.
Кендалл Хельмштеттер Гельнер,
1
«Файл .pbxproj - это просто JSON (похожий на XML)». Фактически, это список свойств в формате OpenStep. Те же основные идеи, что и JSON, но синтаксис отличается в нескольких местах.
Питер Хози
1
Еще одна вещь, которую
стоит
1
Я согласен с @KendallHelmstetterGelner вместо запуска скрипта, который удаляет эти специальные линии, вы можете обновить .gitattribute с unionпереключателем: *.pbxproj text/plain -crlf -diff -merge union.
Besi
9

У меня это работает в Xcode 4.6 и Git 1.7.5.

Добавьте и зафиксируйте файл .gitattributes следующим образом:

*.pbxproj binary merge=union

Я тестировал это с другим членом команды и отлично работает.

Взято из: http://robots.oughttbot.com/post/33796217972/xcode-and-git-bridging-the-gap

Oneyenjug
источник
Merge = union - это хорошо, но инструмент mergepbx должен быть принятым ответом.
Alper
8

Откровенно говоря, существующие ответы вводят в заблуждение.

Если вы никогда не удаляете и не переименовываете файлы, то merge=unionхорошей идеей будет использование стратегии, которая просто объединяет различия в разных фиксациях напрямую.

Однако в реальном мире нам иногда нужно удалять или переименовывать файлы. Объединение различий без каких-либо изменений может создать множество проблем в этих ситуациях, и эти проблемы обычно приводят к проблеме «Целостность рабочего пространства - не удалось загрузить проект», из-за которой вы даже не сможете запустить проект.

Лучшее решение, которое я получил до сих пор:

1) Хорошо спроектируйте проект и добавьте все необходимые файлы в начале, чтобы вам редко приходилось менять project.pbxproj.

2) Сделайте свои черты крошечными. Не делайте слишком много дел в ветке.

3) По какой-либо причине, если вам нужно изменить структуру файла и возникают конфликты project.pbxproj, используйте свой любимый текстовый редактор, чтобы разрешить их вручную. Если вы сделаете свои задачи крошечными, конфликты можно будет легко разрешить.

Брайан
источник
3

Короткий ответ заключается в том, что даже если вы не включите эту строку .gitattributes, вы не сможете легко объединить две модифицированные версии .pbxproj. Для git лучше рассматривать его как двоичный файл.

Подробнее см. Здесь: Git и pbxproj

Обновление: несмотря на то, что книга git все еще согласна с этим ответом, я больше не согласен . Я управляю версиями, .pbxprojкак и любой другой небинарный исходный файл.

Том
источник
звучит так, будто вы могли бы настроить фильтр фиксации для отправки файла simplejsonили что-то в этом роде на пути к индексу. Однако это все равно не будет гарантированно работать.
интуитивно понятен
1
Это не файл в формате JSON. Выглядит похоже, но имеет много отличий в деталях.
eonil
В книге git написано, что это JSON, но похоже, что это неправильно. git-scm.com/book/ch7-2.html
Huggie
1
ОК. .pbxprojНа самом деле это файл NeXT / Cocoa PList старого стиля, который старше и определен намного раньше, чем JSON, и теперь не рекомендуется Apple. (но кое-где все еще используют) Упоминание файла в книге совершенно неверно. Я удалил голос "против", потому что вы прямо упомянули об этом.
eonil
2

Я создал сценарий Python, который может обрабатывать конфликты слияния в файлах проекта XCode.

Если вы хотите попробовать, вы можете проверить это здесь: https://github.com/simonwagner/mergepbx

Вам нужно будет установить его как драйвер слияния, поэтому он будет вызываться автоматически, когда у вас есть конфликт слияния в файле проекта (README.md расскажет вам, как это сделать).

Это должно работать намного лучше, чем использование merge=unionas, которое mergepbxпонимает семантику вашего файла проекта и, следовательно, разрешит конфликт правильно.

Однако проект все еще находится в стадии альфа-тестирования, поэтому не ждите, что он поймет все существующие файлы проекта.

Саймон
источник