лучший способ для создания версий различных веток Git - PullRequest
4 голосов
/ 16 января 2010

У нас есть следующий сценарий: у нас есть несколько базовых версий нашей игры OpenLieroX; сейчас 0,57, 0,58 и 0,59. Для каждой базовой версии у нас есть отдельная ветка. Каждая такая базовая версия имеет несколько выпусков (например, 0.57 beta1-beta8 и rc1, 0.58 beta1-beta9).

Когда мы работаем над новым материалом, мы работаем в ветке с самой высокой базовой версией (сейчас это 0,59). Когда мы исправляем некоторые обнаруженные ошибки, мы делаем это в самой ранней версии (в основном 0.58), где это произошло. Время от времени мы всегда объединяем все изменения в 0,58 в 0,59 (до тех пор, пока мы будем сохранять и вносить изменения в старую ветвь).

Это все работает очень хорошо, пока не произойдут некоторые изменения, которые мы хотим иметь только в 0,58, но не в 0,59. Это произошло только для одного случая: номер версии. У нас есть файл Version.cpp (а также некоторые другие файлы), который содержит номер версии. Поэтому, когда мы хотим выпустить новую версию для 0.58, мы меняем там строку версии на «0.58 beta10» (или любую другую). Теперь, когда мы делаем обычное слияние с 0,58 до 0,59, это изменение также будет применено. Мы исправляем такие случаи в настоящий момент, просто перезаписывая его с правильным номером версии (или в случаях для других плохих фиксаций, возможно, возврата).

Эта деталь о таких нежелательных изменениях кажется мне немного уродливой. Является ли способ, которым мы справляемся с этим, вообще плох / необычен? Как было бы самым простым способом сделать это, чтобы получить тот же результат? Вишневый сбор всех коммитов 0,58 в 0,59 был бы гораздо более трудоемким.


Есть еще одна деталь, которая, вероятно, усложняет задачу: работая над кодом, я должен уже указать номер следующей версии. Это потому, что у нас есть сетевой движок, и мы могли ввести некоторые новые функциональные возможности, и в коде есть проверки типа 'if (client-> version ()> = Version (X, Y, Z)) ...'. Теперь, когда мы вводим что-то новое, обычно это означает, что в некоторые моменты также такие проверки. (Но мы пытаемся избежать этих изменений в старых ветвях.)

Другая проблема заключается в том, что мы не просто считаем версию (например, 0.58.1, 0.58.2, ...), но считаем так: 0,58 бета1, 0,58 бета2, ..., 0,58 бетаX, 0,58 rc1, ..., 0.58, 0.58.1, 0.58.2, ... Это потому, что мы хотим пометить его как экспериментальный для начала (бета-этап), а затем как в основном стабильный или стабильный. В некоторых редких случаях могут быть серьезные изменения (возможно, сетевой протокол) даже между двумя различными бета-версиями (конечно, мы стараемся избегать их, но иногда это невозможно без).

Ответы [ 4 ]

5 голосов
/ 16 января 2010

с дополнительными ветвями

После того, как 0,59 отклонится от 0,58, вы можете использовать отдельную ветку «release» для изменения номера версии в 0,58. Каждая версия (кроме самой последней) будет иметь свою собственную ветку «релиз», которая содержит только слияния из базовой ветки и изменения, которые обновляют внешний номер версии. Структура ветки может выглядеть примерно так:

                A--------o--B                  0.58-release
               /        /
...--o--o--o--o--o--o--o--o                    0.58
      \        \        \  \
       \        \        \  \            C     0.59-release
        \        \        \  \          /
         o--o--o--o--o--o--o--o--o--o--o--o    0.59
                                  \     \
                                   o--o--o     0.60
  • A обозначает программное обеспечение «0.58 beta9»
  • B обозначает программное обеспечение «0.58 rc1»
  • 0.58 содержит изменения, которые еще не были выпущены
  • C обозначает программное обеспечение «0.59 beta1»
  • 0.59 содержит изменения, которые еще не были выпущены
  • 0,60 еще не полностью обновлен с 0,59

Или, если вы очень строги в том, чтобы вносить изменения только в A, B, C и т. Д., Которые изменяют внешний номер версии (без существенных изменений кода, они относятся к «базовым» ветвям: 0,58, 0,59 и т. Д.) ), тогда можно было бы обойтись без «релизных» веток. Вместо этого вы можете использовать отдельную HEAD или временную ветвь (удаляемую после того, как релиз версионирован), чтобы зафиксировать обновление внешней версии и сохранить его в теге.

                A        B
               /        /
...--o--o--o--o--o--o--o--o                    0.58
      \        \        \  \
       \        \        \  \            C
        \        \        \  \          /
         o--o--o--o--o--o--o--o--o--o--o--o    0.59
                                  \     \
                                   o--o--o     0.60
  • A обозначает программное обеспечение «0.58 beta9» и является тегом 0.58-beta9
  • B обозначает программное обеспечение «0.58 rc1» и является тегом 0.58-rc1
  • C обозначает программное обеспечение «0.59 beta1» и является тегом 0.59-beta1

Как Git делает это

Вы также можете посмотреть, как Git выполняет собственные версии.

Для сборок, сделанных из рабочего дерева Git, номер версии генерируется из вывода git describe HEAD. Makefile знает, какие файлы необходимо перекомпилировать / перестроить, если номер версии изменяется, и он всегда запускает сценарий GIT-VERSION-GEN , чтобы убедиться, что он имеет самый последний номер версии. Номер версии доступен в Makefile путем включения сгенерированного файла версии. Он передается в файлы C по аргументу компилятору (-DGIT_VERSION=…) и подставляется в сценарии с помощью sed .

Существуют некоторые положения для переопределения номера версии, «записанного» в сборке, но обычно они существуют только для сборок, выполненных вне рабочего дерева (например, сборка, сделанная из дерева, извлеченного из файла tar).

Смешивание изменений версии-строки с другими изменениями

В своем приложении к вашему вопросу вы утверждаете, что вам нужно изменить номер версии во время разработки. Во-первых, я думаю, что описанная мной и seh схема ветки «0.58-release» все еще может работать для вас. Просто потребуется больше дисциплины, чтобы отделить ваши изменения. Если вы думаете о * -релизных ветках как «выпущенных для внутреннего тестирования», а не просто «выпущенных для клиентов (или для внешнего тестирования)», то это все равно имеет смысл. Всегда выполняйте разработку в базовой ветке (например, «0.58») и всегда объединяйте базовую ветвь с веткой релиза (например, «0.58-релиз») перед выполнением сборки, для которой потребуется определенный номер версии (всегда собирайте из такой объединенная ветка выпуска).

Если вы настаиваете на внесении изменений номера версии и (не-слияния) изменений кода в одну и ту же строку истории, то мне кажется, что у вас не будет иного выбора, кроме как иметь дело с конфликтом при слиянии (если вы не идете с git cherry-pick (для Дэмиена Уилсона или сценарием автоматического редактирования, нацеленным на git rebase -i).

Если ваши «файлы версий» только содержат информацию о версиях, вы можете упростить разрешение конфликтов, используя .gitattributes, чтобы пометить файл Version.cpp как неотключаемый.

.gitattributes в каталоге, который содержит Version.cpp

/Version.cpp -merge

Пометка (как и merge=binary) всегда будет вызывать конфLict, если файл отличается между объединенными ветвями. Версия рабочего дерева после слияния будет по умолчанию версией из ветви, которую вы извлекли (а не из ветви, которую вы объединяете), так что вы можете просто git add Version.cpp && git commit завершить объединение (при условии, что все остальные конфликты также разрешаются).

0 голосов
/ 16 января 2010

Хитрая часть изолирует обозначение версии от базового кода.

Вы можете поместить ветку с обозначением версии поверх ветки освобожденного кода, чтобы вы могли безопасно объединить весь этого кода из вашей выпущенной ветки (0.58) с вашей основной веткой (0.59) любой момент, не смешивая противоречивые обозначения версий. Эта ветвь с указанием версий никогда не будет объединена обратно с выпущенной веткой; вы просто перебазируете его поверх выпущенной ветки, если хотите включить новый код в версионный выпуск.

Вы можете легко это сделать с помощью следующей записи в файле .git / config :

[branch "0.58-release"]
        remote = .
        merge = refs/heads/0.58
        rebase = true

При этом ваша ветвь релиза называется «0.58», и вы будете создавать версионные сборки, используя ветку «0.58-релиз». Когда пришло время сделать релизную сборку, вы должны выполнить следующие команды:

git checkout 0.58-release
git pull
# Edit the version-designating file.
git commit -a -m'Updated version.'

Все изменения в файлах, обозначающих версии, сохраняются только в ветви "58-release" и могут быть безопасно перемещены вперед с помощью git rebase. С другой стороны, если вы хотите, чтобы каждое изменение в файле с указанием версии соответствовало состоянию кода из ветви "0.58", вы можете объединить ветку "0.58" с веткой "0.58-release" вместо того, чтобы перебрасывать «0.58-release» поверх «0.58».

0 голосов
/ 16 января 2010

Если я понимаю проблему, кажется, что вы хотите включить определенное подмножество коммитов из разных веток. В этом случае вам может понадобиться запустить git cherry-pick и применить только те коммиты, которые вы хотите.

Дополнительная информация о команде в git docs и Git Ready .

0 голосов
/ 16 января 2010

Похоже, что вы делаете правильный путь (для этого результата). Но, возможно, вам следует пересмотреть свою версию системы.

Вы можете добавить версию сборки 0.58.1, 0.58.2 и т. Д. Таким образом, вы можете добавить столько материала, сколько захотите, и вы все равно будете называть его «0.58», даже если у него есть сборка номер к нему.

После выпуска вы можете добавить бета, RC, что угодно, но это не то, о чем должна заботиться система управления версиями.

Релиз "0.58.3 (бета1)" просто означает версию 0.58.3. Часть бета1 - это информация о человеке, а не система контроля версий.

...