Система за контрол на версиите – Уикипедия

Система за контрол на версиите (на английски: version control system) е механизмът, по който се управлява работата по даден софтуерен проект. За да се улесни разработката на софтуер са създадени специални системи, които намаляват неудобствата при съвместна работа на много хора върху един проект.

Системите за контрол на версиите обикновено използват едно централно хранилище, в което се съхраняват файловете на проекта. Когато някой започне да работи по този проект, той създава копие на файловете от това хранилище на своята система и работи с тези копия. В процеса на работа потребителят може да изпраща към хранилището направените от него промени и да получава промените, направени по проекта от другите хора в екипа.

След обновяване на хранилището, в него се запазват старите версии на променените файлове. Така тези файлове могат да бъдат възстановени при необходимост. Системата за контрол на версиите също така следи за конфликти – различни промени на различните потребители, които ползват хранилището.

В компютърното софтуерно инженерство, контрол на версиите е всяка практика, която следи и предлага контрол върху промените в изходния код. Понякога, софтуерните разработчици използват Система за Контрол на Версиите (VCS, на английски: Version Control System) както за кода, така и за да поддържат документацията и конфигурационните файлове по даден проект. Въпреки че примерът даден тук е свързан с програмен код, практически всякакъв тип компютърни файлове могат да бъдат поставени под контрол чрез VCS. Ако например графичен дизайнер има нужда да запази всички версии, варианти или стадии на изображение, или графично оформление, то би било добра практика да използвате такава VCS. Най-простата употреба и обяснение на VCS е, че потребителят би могъл лесно да се върне към предишна работеща версия на документ, по който работи в случай, че нещо се обърка.

На най-елементарно ниво разработчиците биха могли да пазят копия на различните версии на компютърната програма и да ги именуват подходящо, давайки им например поредни номера. Този елементарен подход е бил използван за различни големи софтуерни проекти. И докато този метод би могъл да работи, той е неефективен заради необходимостта да бъдат поддържани много, почти идентични копия на програмата. Това изисква сериозна самодисциплина от страна на програмистите и често води до грешки. За решението на този проблем са били разработени, системи за автоматизиране на някои, или всички етапи от процеса за контрол над версиите.
Големите, бързоразвиващи се проекти с много автори се нуждаят от система за контрол на версиите за да организират и оптимизират максимално ефективно всички етапи от процеса на софтуерна разработка. VCS са станали важна част от този процес поради следните предимства, които предлагат:

  • Сътрудничество – група от разработчици, дори и да се намират на различни географски местоположения, могат да работят по един и същ набор от документи или файлове без да пречат един на друг.
  • Архивиране и Възстановяване – Файловете се поставят в хранилището на проекта след редактирането им и след това можете да се върнете към всеки един момент от развитието на тези файлове.
  • Синхронизация – Дава възможност на членовете на екипа да споделят документи и да могат да разполагат с най-актуалните им версии.
  • Отмяна – В случай, че нещо сериозно се обърка, системата дава възможност да се върнем към последната „работеща“ версия.
  • Следене на Промените – Всяка промяна по файловете в хранилището се асоциира с пореден номер и се запазва в история на промените. Когато файла бива променян, може да се добави и кратко обяснение за промените, тяхната необходимост и проблемите, които те решават, което обяснение се запазва заедно с поредния номер в историята на промените на VCS, а не в самия файл. Това прави лесно проследяването на развитието на документа през времето.
  • Управление на промените – промените могат да бъдат инспектирани, обсъждани, одобрявани или отхвърляни по необходимост, като при желание състоянието на документа или файла може да се върне такова каквото е било на определен етап от развитието си.
  • Следене на Принадлежността – VCS запазва името на редактиращия към всяка промяна направена от него.
  • Разклоняване и Обединяване – Възможност за разклоняване на копие от кода в отделна локация и редактирането му в изолация, като при това промените му се следят отделно. По-късно е възможно сливането на кода обратно с друго разклонение.
  • Непрекъсната Интеграция – възможността, която предлагат системите за контрол на версиите, развитието на даден софтуерен продукт да се раздели на малки части (промени), дава възможността да се провеждат операции, тестове и проверки върху всяка последователна промяна, в непрекъснат стил

Структура и Общи Функции

[редактиране | редактиране на кода]

Повечето системи за контрол на версиите включват следните концепции, въпреки че наименованията могат да варират:

  • Repository (Хранилище) – базата данни съхраняваща файловете
  • Server (Сървър) – компютърът, на който е разположена базата данни
  • Client (Клиент) – компютърът свързващ се с хранилището
  • Working Copy (Работно копие) – локалното копие на файловете, където се правят промените
  • Trunk (Стъбло) – Основната локация в хранилището, от която започва развитието на проекта. Главната линия, посока за разработка. Можем да мислим за кода почти като горски път, разклоняващ се, и сливащ се обратно, или продължаващ разклонен.
  • Branch (Разклонение) – Копие на кода от даден момент на развитие на проекта, което може да се развива независимо, или да се обедини обратно.
  • Add (Добавяне) – поставяне на файл в хранилището за първи път. Т.е. започване на проследяването му чрез VCS.
  • Revision (Ревизия) – поредната версията на файла(напр. v1, v2, v2.3 и т.н.)
  • Head (Хед) – последната версия на проекта в дадено разклонение в хранилището.
  • Check out (Изтегляне) – Изтеглянето на файл от хранилището. Тази функция има 2 основни задачи. На сървъра – VCS запомня, че файла е бил изтеглен за редактиране и при нужда уведомява останалите членове на екипа. На клиента – подготвя работна версия на файла за редактиране давайки му съответните разрешения. Тази функция е начин да заявите вашите намерения пред останалите, така че те могат да се съобразят и да избегнат паралелното редактиране на същия файл, което би довело до допълнителни усложнения (конфликт) при опит за качване. Някои VCS предлагат автоматичното заключване на файла, ако той е бил изтеглен, така че да бъде невъзможно паралелното му изтегляне от друг сътрудник.
  • Check in, Commit (Качване) – Качването на файл в хранилището(ако е бил променен). Файла приема нов номер на ревизия и вече не е маркиран като изтеглен, така че членовете на екипа могат да изтеглят последната му версия. Някои VCS заключват за редактиране локалното копие на файла след качване.
  • Коментар за Качването – кратък коментар описващ промените по файла. Добра практика е промените да се описват оптимално, така че в историята на промените да бъдат ясно упоменати и разбираеми причините и корективите, които са били предприети. Това може да бъде изключително полезно след време, когато е нужно да се разбере подобна информация, а спецификата е забравена.
  • Changelog/History (История на промените) – Списък с всички промени направени по даден файл от началото на неговото добавяне в VCS
  • Update/Sync (Синхронизиране) – Синхронизиране на локалните файлове с последните техни версии от хранилището
  • Revert (Връщане) – Отхвърляне на локалните промени по файла и презареждането на последната му версия от хранилището.
  • Branch(Разклонение) – създаване на отделно копие на файл или папка за независимо ползване (тестване, дебъгване и т.н.).
  • Diff/Change/Delta (Разлики) – откриване на различията между два файла. Полезно за визуализирането на настъпили промени между определени ревизии.
  • Merge(Съединяване, сливане) – Прилагане на промените от един документ към друг, който да бъде актуализиран. Например могат да се обединят елементи от едно разклонение с друго.
  • Conflict (Конфликт) – когато чакащи промени към един файл в хранилището си противоречат (не могат да се приложат и двете промени)
  • Resolve (Решение) – разрешаване на проблема с противоречащи си чакащи промени и качването на коректен вариант
  • Locking (Заключване) – установяване на контрол върху файл, така че никой не може да го редактира докато не бъде отключен. Някои VCS използват това за избягване на конфликти
  • Breaking the lock (Силово Отключване) – силово отключване на файла, така че той да може да бъде редактиран. Налага се когато някой заключи файла и се отправи на почивка например.
  • Tag/Label (Тагване) – разклоняване, обикновено съдържащо стабилна версия на проекта готова за пускане, при което се задава име или пореден номер на версията. Прави по-удобно проследяването на развитието на проекта и възможността за бързо връщане към стабилно негово състояние.

Модели за контрол на версиите

[редактиране | редактиране на кода]

Всички системи за контрол на версиите трябва да решат един фундаментален проблем: как системата ще позволи на потребителите да споделят данни без да си пречат един на друг, защото е лесно промени направени от един потребител да бъдат пренебрегнати от друг по невнимание. Ето един пример. Двама потребители – Георги и Петър – свалят един и същ файл за редактиране. Всеки прави уникални промени в своето работно копие. Георги завършва пръв и качва готовия файл. Петър завършва с работата по-късно и също качва неговата версия на файла. Това което може да се случи е, че в хранилището ще съществуват и двата файла, но промените направени от Георги няма да имат никакъв ефект. Възможно пренебрегване на промените на предишната версия

Някои системи за контрол на версиите използват lock-modify-unlock модел за разрешаването на гореописания проблем. При този модел системата позволява само на един потребител да редактира даден файл. Когато Георги заключи файла за редактиране, никой освен него не може да направи същото. Потребителят редактира файла, след което го качва (commit) обратно хранилището и го отключва. Оттук нататък Петър може да започне работа по файла спазвайки същия ред. Моделът Lock -Modify - Unlock

Проблемът с този модел е, че той може сериозно за възпрепятства работата по даден проект и често се превръща в бариера за потребителите.

  • Заключването на файла може да доведе до административни проблеми. Понякога Георги, който е заключил файла, може да забрави за това. Междувременно, Петър трябва да направи промени, но ръцете му са вързани. Георги отива в отпуск или се разболява, и тогава се налага ангажирането на администратор, който да отключи файла за да бъде възможна работата по него. Всичко това приключва с ненужно забавяна и загуба на време.
  • Заключването може да причини излишна сериализация. Ако Георги редактира началото на файла, а на Петър се налага да направи промени в края му, то тогава двете промени не влизат в конфликт и работата може да бъде свършена едновременно, и с подходящо сливане няма да има проблеми. В този случай не е нужно изчакването на ред.
  • Заключването на файл може да създаде фалшиво усещане за сигурност. Ако например Георги заключи и редактира файл А, в същото време Петър редактира файл Б. Но файл А и Б са зависими един от друг и промените направени по тях са семантично несъвместими. Тогава двата файла спират да работят по между си. Заключването не е в състояние да предотврати подобна ситуация, но вместо това създава погрешно усещане за сигурност у двамата потребители, което води до липса на комуникация относно съвместимостта на файловете.

Алтернатива на гореописания модел е Copy-Modify-Merge, където всеки потребител разполага с локално работно копие на файла. Потребителите могат да работят паралелно по техните работни копия и накрая тези файлове се сливат (merge) в една обща финална версия. Системата за контрол на версиите често предлага помощ и автоматизация при процеса на сливане, но понякога, за да протече този процес коректно, е необходима и човешка намеса.

Пример. Петър и Георги създават работни копия на файл А от хранилището. Те работят паралелно всеки по собствената си версия. Петър пръв качва своите промени в хранилището. Когато Георги се опитва да направи същото, системата съобщава, че неговата версия е остаряла и не отговаря на това което той е свалил. Така че, Георги съобщава на системата, че иска да слее двете версии, при което има вероятност промените направени от Петър и тези на Георги да не се препокриват и сливането става автоматично. След което той качва съединената версия обратно в хранилището и така промените и на двамата са запазени в последната версия на файла.

Моделът Copy - Modify - Merge

Но ако промените на Петър си пречат с промените на Георги? Тази ситуация се нарича конфликт и обикновено не е особен проблем. Когато Георги се опита да слее двата файла, той ще види конфликтните промени и в двете версии на файла и ще може ръчно да избере какво да се запази. Трябва да се знае, че софтуер не може автоматично да разрешава конфликти. Само хора биха могли да ги разберат и да вземат необходимите разумни решения. Когато Георги е разрешил възникналите конфликти, навярно след дискусия с Петър, той може уверено на качи съединения файл в хранилището.

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

Примерна стратегия при използване на VCS

[редактиране | редактиране на кода]

Специфична терминология:

  • Рилийз – състояние на софтуерния продукт, когато той е пуснат (или готов) за разпространение и използване от крайния потребител.
  • Дебъгване – търсене и коригиране на грешки в изходния код.
  • Хотфикс – поправка на грешка или допълване на важна информация в продукт, който обикновено е вече пуснат за използване.
Примерен модел за използване на система за контрол на версиите при софтуерна разработка.
Примерен модел за използване на система за контрол на версиите при софтуерна разработка.

В основата на този модел са 2 основни разклонения с безкраен жизнен цикъл. По правило в едното (1) ще пазим код, който е стабилен, и който според спецификата си е готов за разпространение, внедряване или за пускане за употреба. Тук е възможно и поставянето на началния код, от който стартира проекта. Версиите на кода в това разклонение ще бъдат „тагвани“ със съответните наименования (например версия 1.1, v2.0 и т.н.), според регламента, който сме избрали за именуване. Другото разклонение, това за интеграция (2), ще съдържа код, чиито „хед“ отразява последните качени промени и разработки за следващ рилийз. Когато изходния код в разклонението за интеграция достигне стабилен стадий и е готов да бъде пуснат за употреба, промените се сливат обратно в (1) и версията се тагва с номер.

Заедно с главните разклонения (1) и (4), в нашия модел ще включим и няколко допълнителни, поддържащи разклонения, които да подпомагат паралелната разработка на кода между отделни участници в екипа, да улеснят проследяването на работата по разширени функционалности на продукта, да подготвят кода за пускане, и да ускорят работата по отстраняване на грешки (hotfix) от вече пуснат за използване продукт. За разлика от главните разклонения, поддържащите имат ограничен живот, поради това, че ще се слеят с главните рано или късно, или просто поддръжката им ще бъде преустановена.

Един вид помощни разклонения са тези за разработка на допълнителни функционалности и възможности на продукта. Те могат да се разграничат по това дали разработката в тях е за следващ рилийз (5), или за бъдещ (6), в случай, че не е категорично установена версията, която трябва да включва разширението. Характерното при тези разклонения е, че те съществуват само докато допълнителното разширение е в процес на разработка. След това те окончателно се сливат с разклонението за интеграция (4), или се изоставят и изтриват в случай на незадоволителни резултати.

В разклонението за подготовка за рилийз(3) се извършват окончателните довършителни работи по проекта и също така се отстраняват някои малки грешки, пропуснати на по-ранен етап. Изнасяйки този процес в отделно разклонение, се освобождава разклонението за интеграция(4), където вече могат да се внедрят разширени функционалности за следващ рилийз. Възловият момент за разклоняването на този клон от клона за интеграция е когато проекта (почти) отразява желаното състояние за завършен и готов за пускане продукт. Най-малкото, всички функционалности вече трябва да са добавени и не трябва да се добавят нови разширения директно към този клон, а вместо това да се слеят в разклонението за интеграция и да чакат за следващ рилийз. Това е момента, в който проекта получава поредния си рилийз номер. След като кода е готов за разпространение, той се слива в (1) и се тагва (дава му се име), което улеснява бъдещи референции към точно този момент и състояние от развитието на проекта. Накрая, кода от (3) се слива обратно в (4), за да може бъдещите версии на проекта да включват всички поправки на грешки, направени по-рано в разклонението за подготовка.

Разклонението за поправка на критични грешки(2), възникнали при работата на продукт, който е вече пуснат за ползване, може да се разклони от съответния таг на програмата(от(1)), при който се е проявил проблема. Полезното на това е, че работата на екипа в разклонението за интеграция(4) може да продължи необезпокоявано, докато друг екип направи бързата поправка. Когато грешката е отстранена, кода се слива както обратно в (1), така и в (4), за да подсигурим и бъдещите версии срещу този бъг. Единственото изключение на този процес е, че когато съществува разклонение за подготовка(3), тогава кода от (2) се слива с (3) а не с (4).

Специализирани стратегии

[редактиране | редактиране на кода]

Контролът на инженерната ревизия се е развил от формализиран процес базиран на проследяването на ревизии на по-ранни планове или редакционни филтри. Тази система на контрол безусловно позволява възстановяване на всяка по-ранно фаза на дизайна за случаи, в които инженерът е попаднал в задънена улица с разработката на дизайна. Налична е ревизионна таблица, която проследява направените промени. В допълнение, модифицираните райони на рисунката са маркирани, чрез ревизионни клаудове.

Контролът на версията е широко разпространен в бизнеса и правото. В същност "contract redline" и "legal blackline" са някои от най-ранните форми на ревизионен контрол и са все още използвани в бизнеса и правото, усъвършенствани до различна степен. Цяла нова индустрия се е появила, за да обслужва нуждите от ревизионен контрол на документи на бизнеса и други потребители, някои от технологиите за контрол на ревизиите, които се използват са усъвършенствани, стабилни и иновативни. Най-усъвършенстваните техники се въвеждат в употреба за електронно проследяване на промени в CAD файлове, заменяйки ‚‘ръчната‘‘ електронна употреба на традиционния контрол на ревизиите.

Модели за управление на източниците

[редактиране | редактиране на кода]

Традиционните системи за ревизионен контрол използват централизиран модел, където всичките ревизионно-контролни функции се извършват на общ сървър. Ако двама разработчици се опитват да променят един и същ файл по едно и също време, без някакъв начин за управление на достъпа, може да се окаже, че те записват върху работата на другия. Централизираните системи за контрол на ревизията решават този проблем с един от двата „модела за управление на източниците“: заключване на файловете и сливане на версиите.

Хората, занимаващи се с компютърни науки, говорят за атомни операции, когато системата е в стабилно състояние, дори операцията да е прекъсната. Операцията, наречена комите най-опасна в този случай. Комитите са операции, които казват на системата за ревизионен контрол, че искаш да направиш дадена група от промени окончателни и достъпни за всички потребители. Не всички системи за ревизионен контрол имат атомен комит, забележително, но на широко използваната CVS ѝ липсва тази характеристика.

Заключване на файлове

[редактиране | редактиране на кода]

Най-простият метод за предотвратяването на проблемите, свързани с конкурентния достъп е заключването на файлове, така че в даден момент от времето само един разработчик има право да пише върху основните копия на този файл в „хранилището“. Щом разработчик „обработва“ файл, другите могат да го гледат, но никой не може да променя файла, докато този разработчик „пуска“ ъпдейтнатата версия (или не откаже „обработката“)

Заключването на файлове има своите предимства и недостатъци. Може да осигури защита срещу сложни „преплетени“ ситуации, когато един потребител прави сериозни промени на много части от голям файл (или група файлове). Обаче, ако файловете за заключени за твърде дълго от един човек другите потребители може да се изкушат да пренебрегнат софтуера за ревизия на контрола и да променят файловете на локално ниво, което води до много по-сериозни проблеми.

Повечето системи за контрол на версията позволяват множество разработчиции да редактират един и същ файл по едно и също време. Първият разработчик, който „пуска“ промените в централното хранилище, успява. Системата може да осигурява инструменти за по-нататъшно сливане на промените в централното хранилище и да запазва промените, направени от първия разработчик, когато другите пускат своите.

Сливането на два файла може да е много деликатна операция и обикновено е възможно само ако структурата на данните е проста като в текстовите файлове. Резултатът от сливането на два графични файлови формата може изобщо да не даде резултат, който да е в такъв формат. Вторият разработчик, който пуска кода, трябва да се погрижи за сливането, трябва да се увери, че промените са съвместими и че операцията по сливането няма свои собствени логически грешки във файловете. Тези проблеми ограничават възможността за автоматично или полуавтоматично сливане само до прости текстови документи освен ако специфичен плъгин за сливане не е наличен.

Концепцията за ограничено редактиране при желание може да осигури начини за заключване на файла и само един човек да може да го променя дори когато самият файл има възможност за сливане.

Изходни нива, лейбъли и тагове

[редактиране | редактиране на кода]

Повечето системи за контрол на ревизията използват само един от тези приличащи си методи (изходно ниво, лейбил и таг), за да разпознаят снапшот („дай лейбъл на проекта“) или записа на снапшот(" опитай изходно ниво Х"). Обикновено само един от тези методи (изходно ниво, лейбъл итаг) се използва; те са смятани за изключително близки. В повечето проекти някои снапшотове са по-важни от други.

Когато терминът изходно ниво се използва заедно с лейбъл или таг в един и същи контекст лейбъл и таг обикновено се отнасят до механизма на инструмента за идентифициране или правене на записа на снапшота, а изходното ниво маркира повишената важност на даден лейбъл или таг.

Разпределен контрол на ревизията

[редактиране | редактиране на кода]

Системите за разпределен контрол на ревизията (DRCS) имат peer-to-peer подход, за разлика от подхода клиент-сървър на централизираните системи. Вместо едно централно хранилище, на което клиентите се синхронизират, работното копие на всеки peer на програмния код е хранилище. Разпределеният контрол на ревизията извършва синхронизация като обменя пачове (сетове с промени) между peer-ите. Резултатът е много по-различен от този при централизираните системи.

  • Няма общ дубликат на програмния код; само работни копия.
  • Базови операции като преглеждането на историята и премахване на промените се случват по-бързо, защото няма нужда да се комуникира с централен сървър.

Комуникацията е необходима при обмен на промени с други peer-и.

  • Всяко работно копие ефективно действа като запис на програмния код и на историята на промените му, осигуряващ защита срещу загуба на данни.

Някои от по-развитите инструменти за контрол на ревизиите предлагат много други помощни средства, позволяващи по-пълна интеграция с други инструменти и софтуерно-инженерни процеси. Плъгини често са налични за много интегрирани среди за разработка като Oracle JDeveloper, IntelliJ IDEA, Eclipse и Visual Studio. NetBeans IDE, а Xcode има интегрирана версия за контрол на поддръжката.

Популярни системи за контрол на версиите

[редактиране | редактиране на кода]