Обработка нескольких наборов изменений в системах управления версиями

У меня довольно редкая проблема с контролем источника. В примере здесь проблема возникла с Perforce, но я подозреваю, что одна и та же проблема будет иметь место со многими SCM, особенно с распределенными SCM.

Perforce поддерживает списки изменений (или изменения, если вы предпочитаете). Хэндэлисты поддерживают два общих обычаев:

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

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

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

Теперь, что вы делаете? У вас есть несколько вариантов:

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

  • Сделайте выдумку. Создайте резервную копию измененной копии main.h и верните этот файл. Затем вы можете проверить main.h в списке изменений в bugfix. Вы исправляете ошибку, проверяете список изменений в bugfix, затем проверяете main.h в списке изменений электронной почты. Наконец, вы слейте все свои изменения из резервной копии, сделанной в начале.

  • Вы определяете, что все изменения, внесенные в main.h, не имеют побочных эффектов или зависимостей, поэтому просто переместите main.h в список изменений в bugfix, внесите изменения и проверьте их. Затем вы проверяете это снова в список изменений электронной почты. Очевидно, что существует два проблемы с этим подходом: во-первых, на самом деле могут быть побочные эффекты, которые вы не рассматривали, а во-вторых, вы испортили свою версию histoty.

Вариант 1, вероятно, самый чистый, но не всегда практичный. Проект, над которым я работал, имел миллионы строк кода и действительно сложный процесс сборки. Для настройки новой среды потребуется целый день, поэтому это было не очень практично для исправления ошибки на 5 минут.

Вариант 3 - это плохой вариант, но он самый быстрый, поэтому он может быть очень соблазнительным.

Это оставляет вариант 2, который я обычно использовал.

Есть ли у кого-нибудь лучшее решение?

Мои извинения за длительный вопрос, но я обнаружил в StackOverflow, что полностью продуманные вопросы дают лучшие ответы.

Ответ 1

Эта точная проблема называется "проблема с заданной рабочей копией". У Райана Томайко есть запись в блоге The Thing About Git, в которой подробно описывается эта проблема и как Git обращается к ней.

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

Ответ 2

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

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

Ответ 3

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

Вариант 1 ( "вид ветки" ) имеет смысл только тогда, когда вы определяете, что "отладочная работа" несовместима с текущими усилиями по разработке (функция электронной почты) и лучше всего хранится в отдельной ветке. Затем вы можете модифицировать любую поправку, сделанную в ветке "patch", в основную ветку (так как не каждая ошибка, которую вы исправили, должна присутствовать в обоих: текущая разработка может сделать некоторые исправления устаревшими). См. Также "Что такое ветка ", и каков ваш рабочий процесс слияния.

Вариант 3 является иллюстрацией предела понятия набора изменений: одна ревизия (или "версия" ) файла может быть только частью одного набора изменений за раз.

git add -p (добавить патч) упомянутый Грегом, является альтернативой вариантам 1 и 3, поскольку он использует функцию промежуточного этапа "Индекс" (Область постановки), зона, в которой вы решаете, что на самом деле будет совершено, и что останется в вашем личном пространстве.
Это хорошо, но также и в моем опыте довольно сложно выдержать в течение длительного периода времени, особенно в общем наборе файлов, на которые вы применяете две разные эволюции. Филиал чище, проще для модульного тестирования. Однако, для небольшого исправления, как вы упоминаете, это может быть хорошим выходом.

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

  • проверить текущее состояние main.h по электронной почте,
  • проверка в ошибке, исправление, проверка в ошибке
  • а затем проверить электронную почту, чтобы возобновить разработку функции электронной почты.

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

Ответ 4

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

Таким образом:

  • Проверить, что изменения main.h не зависят от других изменений.
  • Текущее состояние main.h в текущем состоянии - при долгосрочном задании электронной почты
  • Исправить ошибку в main.h
  • Проверка изменений исправления ошибок.
  • Отредактируйте main.h по заданию электронной почты, если требуется

Ответ 5

Вы не указали вариант 4, который должен создавать ветки.

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

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

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

Это (IMO) лучшее решение.

Ответ 6

Для Perforce вы можете использовать инструмент, например p4 tar:

http://public.perforce.com/wiki/P4tar

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

Ответ 7

Я согласен с ChrisF: ветвление было бы самым естественным решением для этого.

Я использовал Perforce какое-то время, и это правда, что он не так силен в ветвлении, как другие SCM, но это можно сделать.

Трюк очень прост: создайте ветвь для каждой задачи, над которой вы работаете (ветвь god-ol на каждый шаблон задачи), переключитесь на него. Что делать, если вам нужно исправить что-то еще? Легко, просто переключитесь на другую ветку после проверки всего (с помощью некоторых scms, которые вам даже не нужно проверять) исправьте и вернитесь позже в свою оригинальную ветку "email".

Ответ 8

Я думаю, что решение проблемы "Tangled Working Copy" в Perforce shelving

Вы можете использовать его в командной строке следующим образом:

p4 shelve -c 123

Я обычно использую его в подключаемом модуле IDE (Visual Studio или Eclipse) или P4V. Когда вы откладываете, вы можете выбрать, хотите ли вы вернуть свои файлы, в основном получая чистый список для вашей экстренной работы. И тогда вы можете удалить файлы, когда закончите, чтобы вернуться к вашей прерванной работе.

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

p4 shelve -c $1 && p4 revert -c $1//depot/your/branch/...

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

p4 unshelve -c $1 -f -s $1 && & p4 shelve -c $1 -d