Должен ли я хранить сгенерированный код в системе управления версиями


Это дебаты, в которых я принимаю участие. Хотелось бы получить больше мнений и точек зрения.

У нас есть некоторые классы, которые генерируются во время сборки для обработки операций с БД (в данном конкретном случае с дозвуковым, но я не думаю, что это очень важно для вопроса). Поколение находится в качестве предварительного этапа построения в Visual студии. Поэтому каждый раз, когда разработчик (или официальный процесс сборки) запускает сборку, эти классы генерируются, а затем компилируются в проект.

теперь некоторые люди утверждают, что сохранение этих классов в системе управления версиями может вызвать путаницу, если код, который вы получаете, не соответствует тому, что было бы сгенерировано в вашей собственной среде.

Я хотел бы иметь возможность проследить историю кода, даже если оно обычно рассматривается как черный ящик.

любые аргументы или контраргументы?


Обновление: я задал этот вопрос, так как я действительно верил есть один окончательный ответ. Глядя на все ответы, я мог бы с высокой степенью уверенности сказать, что такого ответа нет. Решение должно приниматься на основе более чем одного параметра. Чтение ответов ниже может дать очень хорошее руководство по типам вопросов, которые вы должны задавать себе, когда вам нужно решить эту проблему.

Я не буду выбирать принятый ответ на данный момент по причинам, упомянутым выше.

27 93

27 ответов:

сохранение его в системе управления версиями больше проблем, чем это стоит.

вы должны делать фиксацию каждый раз, когда вы делаете сборку, чтобы она была любым значением.

Как правило, мы оставляем сгенерированный код( идл на JAXB вещи и т. д.), находящихся вне контроля источник, где я работаю, и это никогда не было проблемой

поместите его в управление исходным кодом. Преимущество наличия истории всего, что вы пишете, доступной для будущих разработчиков, перевешивает незначительную боль от случайного восстановления после синхронизации.

каждый раз, когда я хочу показать изменения в исходном дереве на мой собственный РЕПО, все сгенерированные файлы будут отображаться как изменилось и нужно comitting.

Я бы предпочел иметь более чистый список изменений, которые включают только реальные обновления, которые были выполнены, а не автоматически сгенерированные изменения.

оставьте их, а затем после сборки добавьте "игнорировать" на каждый из созданных файлов.

посмотрите на это так: вы проверяете свои объектные файлы в системе управления версиями? Сгенерированные исходные файлы являются артефактами сборки так же, как объектные файлы, библиотеки и исполняемые файлы. К ним нужно относиться одинаково. Большинство будет утверждать, что вы не должны проверять созданные объектные файлы и исполняемые файлы в системе управления версиями. Те же аргументы применяются к сгенерированному источнику.

Если вам нужно посмотреть историческую версию сгенерированного файла, вы можете синхронизировать его с исторической версией источники и перестроить.

проверка сгенерированных файлов любого рода в системе управления версиями аналогична денормализации базы данных. Есть иногда причины для этого (как правило, для производительности), но это должно быть сделано только с большой осторожностью, поскольку становится намного сложнее поддерживать правильность и согласованность после денормализации данных.

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

Я называю сухой принцип. Если у вас уже есть "исходные файлы" в репозитории которые используются для создания этих файлов кода во время сборки, нет необходимости иметь тот же код, совершенные "в два раза".

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

Я не думаю, что вы должны проверить их.

конечно, любое изменение в сгенерированном коде будет либо шум-изменения между средами, либо изменения в результате чего - то еще-например, изменение в вашей БД. Если скрипты создания вашей БД (или любые другие зависимости) находятся в системе управления версиями, то зачем вам нужны сгенерированные скрипты?

нет, по трем причинам.

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

  2. Я не хочу у кого-то может возникнуть соблазн попытаться сократить сборку из первичных источников с помощью промежуточного кода, который может быть или не быть текущим (и что более важно, что я не хочу брать на себя ответственность.) И не слишком ли заманчиво для некоторых людей попасть в бессмысленный процесс отладки конфликтов в промежуточном коде на основе частичных сборок.

  3. Как только он находится в системе управления версиями, я принимаю на себя ответственность за a. это быть там, b. это быть текущим, и c. это быть надежно интегрируется со всем остальным там. Это включает в себя удаление его, когда я больше не использую его. Чем меньше ответственности, тем лучше.

общие правила нет, но если требуется время для генерации кода (из-за доступа к БД, веб-служб и т. д.) затем вы можете сохранить кэшированную версию в системе управления версиями и сохранить все боль.

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

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

мы также не храним сгенерированный код БД: поскольку он сгенерирован, вы можете получить его по желанию в любой заданной версии из исходных файлов. Хранение его было бы похоже на хранение байт-кода или такого.

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

покинуть его.

Если вы проверяете сгенерированные файлы, вы делаете что-то неправильно. Что не так может отличаться, это может быть, что ваш процесс сборки неэффективен, или что-то еще, но я не вижу его когда-нибудь хорошая идея. История должна быть связана с исходными файлами, а не с созданными.

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

мир боли ждет тех, кто регистрирует сгенерированные файлы!

существует особый случай, когда вы хотите проверить свои сгенерированные файлы: когда вам может потребоваться построить на системах, где инструменты, используемые для создания других файлов, недоступны. Классический пример этого, и один из них, с которым я работаю, - это код Lex и Yacc. Поскольку мы разрабатываем систему времени выполнения, которая должна строить и работать на огромном разнообразии платформ и архитектур, мы можем полагаться только на целевые системы, чтобы иметь компиляторы C и C++, а не инструменты, необходимые для создания кода лексики / синтаксического анализа для наш переводчик определения интерфейса. Таким образом, когда мы меняем наши грамматики, мы проверяем сгенерированный код, чтобы разобрать его.

прибытие немного поздно ... в любом случае...

вы бы поместили промежуточный файл компилятора в систему управления версиями исходного кода ? В случае генерации кода, по определению исходный код является входом генератора, в то время как сгенерированный код может рассматриваться как промежуточные файлы между "реальным" источником и встроенным приложением.

поэтому я бы сказал: Не ставьте сгенерированный код под контроль версий, но генератор и его вход.

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

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

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

Это действительно зависит. В конечном счете, цель состоит в том, чтобы иметь возможность воспроизвести то, что у вас было, если это необходимо. Если вы можете точно восстановить свои двоичные файлы, нет необходимости их хранить. но вам нужно помнить, что для воссоздания вашего материала вам, вероятно, понадобится ваша точная конфигурация, с которой вы это сделали в первую очередь, и это означает не только ваш исходный код, но и вашу среду сборки, вашу IDE, возможно, даже другие библиотеки, генераторы или прочее, в точной конфигурации (версии) вы использовали.

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

Итак, вы бы сохранили сгенерированный код: я бы сказал Нет. Двоичные файлы или результаты, которые будут выпущены, в том числе инструменты, которые вы воспроизвели их с я бы хранить. И тогда, нет необходимости хранить их в систему управления версиями, просто сделать резервную копию этих файлов.

задача управления конфигурацией (из которых контроль версий является только одной частью) должна быть в состоянии сделать следующее:

  • знайте, какие изменения и исправления ошибок были внесены в каждую поставленную сборку.
  • иметь возможность точно воспроизвести любую поставленную сборку, начиная с исходного кода. Автоматически сгенерированный код не считается "исходным кодом" независимо от языка.

первая гарантирует, что когда вы говорите клиенту или конечный пользователь "ошибка, о которой вы сообщили на прошлой неделе, исправлена, и новая функция была добавлена" они не возвращаются через два часа и говорят: "Нет, это не так". Он также гарантирует, что они не говорят: "почему он делает X? Мы никогда не просили х".

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

Это означает, что ваш компилятор, библиотеки и т. д. Также должны быть частью см.

Так что теперь, чтобы ответить на ваш вопрос: если вы можете сделать все выше, то вам не нужно записывать какие-либо промежуточные представления, потому что вы гарантированно получите тот же ответ в любом случае. Если вы не можете сделать все выше, то все ставки выключены, потому что вы никогда не можете гарантировать, чтобы сделать то же самое дважды и получить тот же ответ. Так что вы могли бы также положить все ваши .o файлы под контролем версий, а также.

правильный ответ - "Это зависит". Это зависит от потребностей клиента. Если вы можете откатить код до определенного выпуска и противостоять любому внешнему аудиту без него, то вы все еще не на твердой почве. Как разработчики, мы должны учитывать не только "шум", боль и дисковое пространство, но и тот факт, что нам поручена роль создания интеллектуальной собственности, и могут быть правовые последствия. Сможете ли вы доказать судье, что вы можете восстановить веб-сайт точно так же, как клиент видел это два года назад?

Я не предлагаю вам сохранять или не сохранять файлы gen'D, в зависимости от того, как вы решите, если вы не привлекаете экспертов по предмету решения, вы, вероятно, ошибаетесь.

мои два цента.

здесь представлены хорошие аргументы как за, так и против. Для записи я создаю систему генерации T4 в Visual Studio, и наш параметр по умолчанию out-of-the-box вызывает возврат сгенерированного кода. Вы должны работать немного сложнее, если вы предпочитаете не регистрироваться.

для меня ключевым соображением является дифференцирование сгенерированного выхода при обновлении самого входа или генератора.

Если вы не зарегистрировали свой вывод, то вам нужно сделать копию всего сгенерированного кода перед обновлением генератора или изменением входа, чтобы иметь возможность сравнить его с выходом из новой версии. Я думаю, что это довольно утомительный процесс, но с проверенным выводом это простой вопрос о различии нового вывода с репозиторием.

на этом этапе разумно спросить: "Почему вас волнуют изменения в сгенерированном коде?"(Особенно по сравнению с объектным кодом.) Я считаю, что есть несколько ключевых причин, которые сводятся к современное состояние, а не внутренние проблемы.

  1. вы создаете рукописный код, который тесно связан с сгенерированным кодом. В наши дни это не так в целом с obj-файлами. Когда сгенерированный код изменяется, к сожалению, довольно часто бывает, что какой-то рукописный код должен измениться, чтобы соответствовать. Люди часто не наблюдают высокую степень обратной совместимости с точками расширяемости в сгенерированном коде.

  2. автоматически код просто меняет свое поведение. Вы не потерпите этого от компилятора, но справедливости ради, генератор кода уровня приложения нацелен на другую область проблемы с более широким диапазоном приемлемых решений. Важно увидеть, нарушены ли предположения, которые вы сделали о предыдущем поведении.

  3. вы просто не на 100% доверяете выходу вашего генератора от выпуска к выпуску. Есть много пользы от инструментов генератора, даже если они не построены и поддерживается с строгостью вашего поставщика компилятора. Выпуск 1.0 мог бы быть совершенно стабильным для вашего приложения, но, возможно, 1.1 имеет несколько сбоев для вашего варианта использования. В качестве альтернативы вы меняете входные значения и обнаруживаете, что вы выполняете новую часть генератора, которую вы раньше не использовали, - потенциально вы удивляетесь результатам.

по существу все эти вещи сводятся к зрелости инструмента-большинство генераторов кода бизнес-приложений не закрыты до уровня, на котором компиляторы или даже инструменты уровня lex/yacc были в течение многих лет.

у обеих сторон есть веские и разумные аргументы, и трудно договориться о чем-то общем. Системы контроля версий (СКВ) отслеживает файлы разработчики вкладывают в него и имеют предположение, что файлы внутри VCS создаются вручную разработчиками, а разработчики интересуются историей и изменения между любыми ревизиями файлов. Это предположение уравняет две концепции: "я хочу получить этот файл, когда я выполняю проверку."и "я есть заинтересованы в изменении этого файл."

теперь аргументы с обеих сторон можно перефразировать так:

  • " Я хочу получить все эти сгенерированные файлы, когда я делаю проверку, потому что у меня нет инструмента для их создания на этой машине."
  • " Я не должен помещать их в VCS, так как я не заинтересован в изменении этого файла."

к счастью, кажется, что эти два требования не противоречат друг другу в корне. С некоторым расширением текущего VCSs, это должны быть оба. Другими словами, это ложная дилемма. Если мы немного подумаем, нетрудно понять, что проблема связана с предположением, что vcss удерживается. ВКС следует отличать файлы, созданные вручную разработчиками, от файлов, которые не были созданы вручную разработчиками, но просто оказались внутри этой VCS. Для первой категории файлов, которые мы обычно называем исходными файлами (кодом), VCSs проделали большую работу. Для последней категории, VCSs имеют не было такого концепции пока нет, насколько я знаю.

резюме

Я возьму git в качестве одного примера, чтобы проиллюстрировать, что я имею в виду.

  • git status не должны показывать сформированные файлы по умолчанию.
  • git commit должен включать сгенерированные файлы в качестве моментального снимка.
  • git diff не должны показывать сформированные файлы по умолчанию.

PS

git крючки могут быть использованы в качестве обходного пути, но было бы здорово, если git поддерживает его изначально. gitignore не соответствует нашим требованиям, проигнорированы файлы не будут входить в VCSs.enter code here

Я бы поспорил. Если вы используете непрерывный процесс интеграции, который проверяет код, изменяет номер сборки, создает программное обеспечение и затем тестирует его, то проще и проще просто иметь этот код как часть вашего репозитория.

кроме того, это неотъемлемая часть каждого "снимка", который вы берете из своего репозитория программного обеспечения. Если это часть программного обеспечения, то она должна быть частью репозитория.

Я бы сказал, что да, вы хотите, чтобы положить его под контроль версий. С точки зрения управления конфигурацией все, что используется для создания сборки программного обеспечения, должно контролироваться, чтобы его можно было воссоздать. Я понимаю, что сгенерированный код можно легко воссоздать, но можно сделать аргумент, что это не одно и то же, поскольку метки даты/времени будут отличаться между двумя сборками. В некоторых областях, таких, как правительства, они требуют много раз это делал.

В общем случае, сгенерированный код не нужно хранить в системе управления версиями, потому что история изменений этого кода может быть прослежена по истории изменений кода, который его сгенерировал!

тем не менее, похоже, что OP использует сгенерированный код в качестве уровня доступа к данным приложения вместо того, чтобы вручную писать его. В этом случае я бы изменил процесс сборки и зафиксировал код в системе управления версиями, поскольку он является критическим компонентом кода среды выполнения. Это также удаляет зависимость от инструмента генерации кода из процесса сборки в случае, если разработчикам необходимо использовать разные версии инструмента для разных ветвей.

кажется, что код должен быть создан только один раз вместо каждой сборки. Когда разработчику необходимо добавить/удалить / изменить способ доступа объекта к базе данных, код должен быть сгенерирован снова, так же, как и внесение изменений вручную. Это ускоряет процесс сборки, позволяет вручную оптимизировать данные уровень доступа и история уровня доступа к данным сохраняются простым способом.

Я (к сожалению) заканчиваю тем, что помещаю много производных источников под контроль источника, потому что я работаю удаленно с людьми, которые либо не могут быть обеспокоены созданием правильной среды сборки, либо у которых нет навыков для ее настройки, чтобы производные источники были построены точно правильно. (И когда дело доходит до Gnu autotools, я сам один из этих людей! Я не могу работать с тремя разными системами, каждая из которых работает с другой версией autotools-и только это версия.)

такого рода трудности, вероятно, больше применимы к неполным рабочим дням, добровольцам, проектам с открытым исходным кодом, чем к платным проектам, где человек, оплачивающий счета, может настаивать на единой среде сборки.

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

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

  1. С помощью codefiles в системе управления версиями вы потенциально сможете скомпилировать код без использования шага предварительной сборки Visual Studio.
  2. когда вы делаете полное сравнение между двумя версиями, было бы неплохо узнать, изменился ли сгенерированный код между этими двумя тегами, без необходимости проверьте это вручную.
  3. Если сам генератор кода изменяется, то вы хотите, чтобы убедиться, что изменения в сгенерированный код изменяется соответствующим образом. т. е. если ваш генератор изменяется, но выход не должен меняться, то когда вы идете на фиксацию своего кода, не будет никаких различий между тем, что было ранее сгенерировано и что находится в сгенерированном коде сейчас.

Я бы оставил сгенерированные файлы out исходного дерева, но поставить его in отдельное дерево построения.

например, рабочий процесс

  1. checkin/out/modify / merge source нормально (без каких-либо сгенерированных файлов)
  2. в соответствующих случаях, проверьте исходное дерево в чистое дерево сборки
  3. после сборки проверьте все "важные" файлы ("реальные" исходные файлы, исполняемые файлы + сгенерированный исходный файл), которые должны присутствовать для цели аудита / регулирования. Это дает вам историю всех соответствующих сгенерированных кодов + исполняемые файлы+все, что угодно, с временными приращениями, которые связаны с выпусками / тестовыми снимками и т. д. и отделен от повседневного развития.

вероятно, есть хорошие способы в Subversion/Mercurial/Git / etc связать историю реальных исходных файлов в обоих местах вместе.

Если это часть исходного кода, то он должен быть помещен в систему управления версиями независимо от того, кто или что его генерирует. Вы хотите, чтобы система управления версиями отражала текущее состояние вашей системы без необходимости ее регенерации.

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

обновление: я задал этот вопрос, так как я действительно верил, что есть один окончательный ответ. Глядя на все ответы, я мог бы с высокой степенью уверенности сказать, что такого ответа нет. Решение должно приниматься на основе более чем одного параметра. Прочитав другие ответы предоставьте очень хорошее руководство по типам вопросов, которые вы должны задавать себе, когда вам нужно решить эту проблему.