TFS: Объедините лучшие практики

Nemerle:

Это катастрофические отказы компилятор с StackOverflowException:

def o(){[o()]}
46
задан Community 24 July 2013 в 13:57
поделиться

2 ответа

  1. Merges from Dev* -> Integration and Integration -> Production should always be "copy" merges. This is the safest way to preserve the stability of your downstream branches.
    1. Сначала выполните слияние в другом направлении (например, Интеграция -> Dev2), чтобы уловить последние изменения из целевой ветви.
    2. Если есть конфликты, обрабатывайте различия в каждом конкретном случае. AcceptMerge (автоматический или ручной) обычно является желаемым результатом, но иногда вам нужно сохранить копию одной или другой ветки без изменений.
    3. Используйте исходную ветку (Dev # 2 в нашем случае), чтобы полностью включить, отреагировать на, и стабилизировать эти изменения.
    4. Слияние в желаемом направлении (например, Dev2 -> Интеграция). Разрешите все конфликты как AcceptTheirs [также известное как «копия из источника»].
    5. Убедитесь, что нет изменений в целевой ветви между шагами №1-4. Если ветвь Dev принимает слияния рано и часто, как и должно быть, тогда не должно быть обременительным блокировать целевую ветвь во время этого, надеюсь, короткого процесса. Если вы по какой-то причине ожидаете «большого взрыва» слияния смерти, есть большая вероятность, что блокировка не позволит другим командам делать то же самое параллельно, поэтому вам, возможно, придется повторять шаги 1-4 несколько раз, пока вы не будете готовы. .
  2. По возможности делайте «догоняющие» слияния. То есть объединяйте объекты в том же порядке, в котором они были отмечены. Если наборы изменений 10, 20 и 30 являются кандидатами на слияние от A до B, то любой из этих диапазонов слияния является «догоняющим»: 10 ~ 10, 10 ~ 20, 10 ~ 30. Любой диапазон набора изменений, пропускающий № 10, известен как «вишневый выбор». Как только вы начнете собирать вишню, вы столкнетесь с несколькими опасностями: так что вам, возможно, придется повторять шаги 1-4 несколько раз, пока вы не будете готовы.
  • По возможности делайте «догоняющие» слияния. То есть объединяйте объекты в том же порядке, в котором они были отмечены. Если наборы изменений 10, 20 и 30 являются кандидатами на слияние от A до B, то любой из этих диапазонов слияния является «догоняющим»: 10 ~ 10, 10 ~ 20, 10 ~ 30. Любой диапазон набора изменений, пропускающий № 10, известен как «вишневый выбор». Как только вы начнете собирать вишню, вы столкнетесь с несколькими опасностями: так что вам, возможно, придется повторять шаги 1-4 несколько раз, пока вы не будете готовы.
  • По возможности делайте «догоняющие» слияния. То есть объединяйте объекты в том же порядке, в котором они были отмечены. Если наборы изменений 10, 20 и 30 являются кандидатами на слияние от A до B, то любой из этих диапазонов слияния является «догоняющим»: 10 ~ 10, 10 ~ 20, 10 ~ 30. Любой диапазон набора изменений, пропускающий № 10, известен как «вишневый выбор». Как только вы начнете собирать вишню, вы столкнетесь с несколькими опасностями:
    1. Вы не можете использовать описанную выше модель объединить вниз, скопировать вверх . Только для этого Лаура Вингерд сказала, что вы перепрыгиваете через бордюр.
    2. Если какой-либо из файлов, затронутых в вашем диапазоне, также был затронут ранее, вам придется выполнить 3-стороннее слияние содержимого, чтобы только вишня -выбранные различия распространяются. Нет идеального инструмента сравнения; вы добавляете ненулевой риск переноса большего количества кода, чем предполагалось, случайной перезаписи изменений, внесенных в целевой объект, введения логических ошибок, когда две ветви расходятся, и т. д.
    3. Набор изменений, которые вы продвигаете в предположительно более стабильную ветвь представляет собой конфигурацию, которая никогда не была создана или протестирована ранее. Вы можете приблизительно догадаться о конечном состоянии целевой ветви. "Я объединяю все изменения, затрагивающие Module Foo, t включить само восстановление. Если вы объедините Moves со всеми правильными областями пути и версии, но сделаете это не по порядку, возможно, в конечном итоге получится другое целевое имя, отличное от исходного, даже после того, как все возможные ревизии будут исчерпаны. Я уверен, что у этой комбинации есть еще несколько способов, которые не приходят в голову прямо сейчас ... просто поверьте мне.
  • Всегда делайте Get на целевой ветке перед слиянием. Расширенная версия для максимальной безопасности: синхронизируйте рабочую область, в которой вы будете выполнять слияние, с определенным номером набора изменений, который находится рядом с Советом, а затем также [догоняющее] слияние с тем же набором изменений. Это позволяет избежать нескольких потенциальных проблем: s возможно получить имя цели, отличное от имени источника, даже после того, как все кандидаты ревизии были исчерпаны. Я уверен, что у этой комбинации есть еще несколько способов, которые не приходят в голову прямо сейчас ... просто поверьте мне.
  • Всегда делайте Get на целевой ветке перед слиянием. Расширенная версия для максимальной безопасности: синхронизируйте рабочую область, в которой вы будете выполнять слияние, с определенным номером набора изменений, который находится рядом с Советом, а затем также [догоняющее] слияние с тем же набором изменений. Это позволяет избежать нескольких потенциальных проблем: s возможно получить имя цели, отличное от имени источника, даже после того, как все кандидаты ревизии были исчерпаны. Я уверен, что у этой комбинации есть еще несколько способов, которые не приходят в голову прямо сейчас ... просто поверьте мне.
  • Всегда делайте Get на целевой ветке перед слиянием. Расширенная версия для максимальной безопасности: синхронизируйте рабочую область, в которой вы будете выполнять слияние, с определенным номером набора изменений, который находится рядом с Советом, а затем также [догоняющее] слияние с тем же набором изменений. Это позволяет избежать нескольких потенциальных проблем: синхронизируйте рабочую область, в которой вы будете выполнять слияние, с определенным номером набора изменений, который находится рядом с Советом или рядом с ним, а затем также выполните слияние с тем же набором изменений. Это позволяет избежать нескольких потенциальных проблем: синхронизируйте рабочую область, в которой вы будете выполнять слияние, с определенным номером набора изменений, который находится рядом с Советом или рядом с ним, а затем также выполните слияние с тем же набором изменений. Это позволяет избежать нескольких потенциальных проблем:
    1. Merging into stale code, yielding confusing 3-way diffs that appear to remove changes from what you see at Tip. [you'd eventually get them back upon Checkin + Resolve, but no reason to go thru two risky diffs when you can avoid both]
    2. Having to go thru the conflict resolution process twice: once on Merge, once on Checkin. There's no way to avoid this in the general case, but most of the time the # of simultaneous changes made while you Merge + Resolve is tiny compared with the # of changes you'd encounter in a workspace that might be days or weeks out of date.
  • Don't merge by label (or workspace) unless you really really know what you're doing. Let's review the features offered by TFS labels and then dissect why each is inappropriate for safe & consistent merging.
    1. Метки могут представлять несколько моментов времени. Если метка представляет собой согласованный снимок VCS - и всегда задумывалась как таковая - тогда она не имеет технического преимущества перед датой или набором изменений №. К сожалению, довольно сложно сказать, является ли этикетка неизменной во времени. В противном случае слияние по метке может привести к:
      1. Непреднамеренный выбор вишни, если диапазон начинается с метки, указывающей на элемент @ на время раньше его первого кандидата.
      2. Случайное исключение, если диапазон начинается с метки, указывающей на элемент @ на время вперед конца диапазона
      3. Непреднамеренное исключение, если диапазон заканчивается меткой, указывающей на элемент @ за время до начала диапазона
    2. Спецификации версий метки представляют определенный набор элементов. Их можно использовать для преднамеренного исключения файлов и папок, которые в противном случае увидел бы чистый рекурсивный запрос. Эта функция тоже плохо подходит для операций слияния. (И опять же, если вам не эта способность, вы подвергаетесь следующему риску, ничего не получая за даты и наборы изменений.)
      1. Items not present in the label will be simply ignored, rather than merged as pending deletes. Unlike some of the edge cases covered so far, this is a big deal that's quite likely to happen in mainstream scenarios yet most people miss. [As a result, TFS 2010 adds support for deleted items inside labels.]
      2. Inadvertent cherry picking, if you add an item to the label that has been present for awhile but was excluded from prior merges due to one of the aforementioned side effects.
      3. Intentional cherry picking. The whole advantage this feature brings to Merge is to break one of our guidelines, so obviously that's not a good reason at all. Furthermore, it causes cherry-picking at the file level, which is even more dangerous than "ordinary" cherry picking by changeset.
    3. Labels have friendly customizable names, owners, and comments. Thus we have a pure usability difference vs dates/changesets; no technical advantage is conferred. But even here it's not as attractive as it looks. TFS doesn't do much to actually surface labels in the UI, whereas you can see changeset comments all over the place. Querying by owner is fast (server side), but most other searches are slow (client side) unless you know the exact label name. Management facilities are virtually nonexistent. No changelog or auditing, only a timestamp. In all, these are hardly reasons to abandon the surety provided by changesets.
  • Always merge the entire branch at once. Merging files or subtrees is sometimes tempting, but ultimately amounts to mere cherry-picking under a new guise.
  • Plan ahead. Unfortunately, re-parenting branches in TFS is a painful topic. Sometimes it's arduous, sometimes it's only a few steps, but it's never obvious; there is no built in command (until 2010). Pulling it off in 2005/2008 requires a pretty deep knowledge of your current branch structure, desired structure, and how to abuse the side effects of various TF commands.
  • Don't create branches inside of branches. For example, branching & merging is sometimes recommended as a way to maintain common modules or binaries between loosely coupled projects. I don't think this is very good advice to begin with -- far better to make your build system do its primary job properly, than to shoehorn your source control system into doing something it's not really designed to do. Anyway, this "sharing" tactic clashes terribly with projects themselves live inside a broader branch hierarchy for SCM purposes. If you're not uber careful, TFS will happily let you create arbitrary many-to-many branch relationships between version control items. Good luck sorting that out (I once had to do it for a customer, not pretty.)
  • Don't create files with the same relative path in two branches independently; use Merge to branch them around or you'll spend hours chasing namespace conflicts. (n/a in 2010)
  • Don't re-add files on top of a path where other items used to exist. Whether the old items were Rename/Moved away, or simply Deleted, you'll face interesting challenges at Merge time; at minimum, it'll require two Checkins to fully propagate. (n/a in 2010, though the experience is still somewhat degraded; only 1 checkin is required, item contents is preserved, but the name history is in that branch & all downstream branches)
  • Don't use the /force flag unless you know what you're doing. All /force merges are effectively cherry picks, leading to very similar risks (code getting lost during the Resolve process, etc etc).
  • Don't use the /baseless flag unless you really really know what you're doing. You miss out on deletes -- similar to labels, except that renames always get morphed into branches instead of just in the unlucky edge cases. You don't get any debit/credit protections whatsoever. And scariest of all, you'll be creating new branch relationships. Sometimes. (no feedback is shown to the user as to whether each target items is new, old with a new relationship, or old with an existing relationship)
  • Avoid /discard (and equivalently, AcceptYours resolutions) when possible. Discarding some changesets only to accept subsequent ones is yet another name for cherry-picking :)
  • Be careful with your resolutions in general. Each has unique downstream effects apart from its effect on the merge at hand.
    1. AcceptTheirs - это быстрый и эффективный способ получить «копию» слияния, как рекомендовано в первом руководстве. Если вы используете его и в других сценариях, помните, что вы , а не , просто говорите TFS, чтобы содержимое файла было таким же. Вы говорите ему, что два файла полностью синхронизированы из точки зрения управления версиями. Таким образом, любые предыдущие изменения в целевом файле, которые могли быть объединены в противоположном направлении, больше не будут считаться кандидатами после того, как вы отметите AcceptTheirs.
    2. Обратите внимание, что AcceptMerge (автоматический или ручной), результирующее содержимое которого идентично исходному файл будет рассматриваться сервером как AcceptTheirs. В протоколе веб-службы Checkin нет никаких различий.
    3. Использование AcceptYours при переименовании может исказить ваш мозг. Вы' Я быстро попаду в ситуацию, когда «один и тот же» элемент будет иметь разные имена в разных ветках. Предполагая, что у вас есть веская причина для отказа от изменений, это явление само по себе небезопасно - на самом деле, вероятно, необходимо избегать прерывания сборки или разовой настройки ваших make-файлов. Это просто сбивает с толку людей и, скорее всего, нарушит работу любых сценариев автоматизации, которые предполагают, что древовидные структуры согласованы от ветки к ветке.
    4. AcceptMerge используется по умолчанию по определенной причине. Иногда это приводит к большему количеству конфликтов версий, чем кажется строго необходимым, но это самый безопасный вариант, когда требуется истинное слияние. (Например, шаг № 1 основного правила «объединить вниз, скопировать вверх».) Пока вы следуете другим правилам, количество слияний, требующих ручного внимания, должно сократиться - резко, поэтому, если вы исходите из рабочего процесса, который сильно зависит от выбора вишен.
  • Ошибки должны быть связаны с набором изменений, в котором было фактически сделано исправление. Если позже вам потребуется перейти к нижестоящим ветвям, чтобы увидеть, когда, где (и, возможно, как) было распространено исправление, это чисто функция контроля версий. Нет необходимости загромождать рабочий элемент лишним багажом, не говоря уже о принципиальном изменении способа выполнения слияний. В 2005/2008 годах вы можете просматривать историю слияний с помощью команды tf merges или стороннего пользовательского интерфейса, такого как Attrice SideKicks. В 2010 году вы получите отличные визуализации, встроенные в Visual Studio. Инструкции и снимки экрана в MSDN.
  • 75
    ответ дан 26 November 2019 в 20:29
    поделиться

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

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

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

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

    5
    ответ дан 26 November 2019 в 20:29
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: