go to the first, previous, next, last section, table of contents.
создание ветвей и слияниеcvs позволяет изолировать изменения в отдельной линии разработки, называемой веткой. когда вы изменяете файлы на ветке, эти изменения не появляются в основном стволе или на других ветках.
позже вы можете переместить изменения с одной ветки на другую или
же с ветки в ствол, это называется слиянием. сначала
выполняется для чего хороши ветви?предположим, был выпущен tc версии 1.0. вы продолжаете его разработку, планируя выпустить версию 1.1 через пару месяцев. через некоторое время ваши пользователи начинают жаловаться на серьезную ошибку. вы извлекаете версию 1.0 (see section метки ревизий) и находите ошибку, для исправления которой требуется всего лишь тривиальное изменение). однако же, текущая версия исходников находится в крайне нестабильном состоянии и не стабилизируется по крайней мере еще месяц. вы не можете выпустить исправленную версию, основываясь на свежих исходниках. в подобной ситуации имеет смысл создать ветку в дереве ревизий, содержащую файлы, из которых состояла версия 1.0. затем вы вносите изменения в ветвь без вторжения в основной ствол. потом вы сможете либо внести те же самые изменения в основной ствол, либо оставить их только на ветви. создание ветви
вы можете создать ветвь, используя $ cvs tag -b rel-1-0-patches это отщепляет ветку, основанную на текущей ревизии рабочей копии, и присваивает этой ветке имя `rel-1-0-patches'. важно понимать, что ветки создаются в репозитории, а не в рабочей копии. создание ветки, основанной на текущей ревизии, как в вышеприведенном примере, не переключает рабочую копию на использование ветки (see section доступ к веткам, где описано, как сделать это).
можно также создать ветку вообще без использования рабочей копии,
используя $ cvs rtag -b -r rel-1-0 rel-1-0-patches tc `-r rel-1-0' означает, что эта ветка имеет корневую ревизию, соответствующую метке `rel-1-0'. это не обязательно должна быть самая последняя ревизия: довольно часто бывает полезно отщепить ветку от старой ревизии (например, для исправления ошибки в старой версии, которая в основном стабильна).
как и в случае с `tag', ключ командной строки `-b'
заставляет таким образом, полный эффект этой команды -- создать новую ветку, которая называется `rel-1-0-patches', в модуле `tc', которая растет в дереве ревизий из точки, помеченной как `rel-1-0'. доступ к веткамвы можете извлечь ветку двумя способами: извлекая ее из репозитория в чистом каталоге или переключая существующую рабочую копию на ветку. для того, чтобы извлечь ветку из репозитория, выполните команду `checkout' с ключом командной строки `-r', с именем метки в качестве параметра (see section создание ветви). $ cvs checkout -r rel-1-0-patches tc если у вас уже есть рабочая копия, вы можете переключить ее на нужную ветку с помощью `update -r': $ cvs update -r rel-1-0-patches tc или, что то же самое: $ cd tc $ cvs update -r rel-1-0-patches неважно, что рабочая копия была извлечена из основного ствола или какой-нибудь другой ветки: вышеприведенная команда переключит ее на указанную ветку. подобно обычной команде `update', `update -r' сливает сделанные изменения, уведомляя вас о произошедших конфликтах. когда вы связываете рабочую копию с какой-либо веткой, она будет оставаться связанной, пока вы не укажете обратного. это означает, что изменения, которые фиксируются из рабочей копии, будут добавлять новые ревизии на ветку, оставляя без изменений основной ствол и другие ветки. чтобы узнать, на какой ветви находится рабочая копия, можно использовать команду `status'. в том, что она вывела на экран, обратите внимание на поле, которое называется `sticky tag' (see section липкие метки) -- здесь cvs сообщает, на какой ветви находятся рабочие файлы: $ cvs status -v driver.c backend.c =================================================================== file: driver.c status: up-to-date version: 1.7 sat dec 5 18:25:54 1992 rcs version: 1.7 /u/cvsroot/yoyodyne/tc/driver.c,v sticky tag: rel-1-0-patches (branch: 1.7.2) sticky date: (none) sticky options: (none) existing tags: rel-1-0-patches (branch: 1.7.2) rel-1-0 (revision: 1.7) =================================================================== file: backend.c status: up-to-date version: 1.4 tue dec 1 14:39:01 1992 rcs version: 1.4 /u/cvsroot/yoyodyne/tc/backend.c,v sticky tag: rel-1-0-patches (branch: 1.4.2) sticky date: (none) sticky options: (none) existing tags: rel-1-0-patches (branch: 1.4.2) rel-1-0 (revision: 1.4) rel-0-4 (revision: 1.4) не смущайтесь тем, что номера ветвей для каждого файла различны (`1.7.2' и `1.4.2', соответственно). метка ветви одна и та же, `rel-1-0-patches', и все файлы действительно находятся на одной и той же ветке. номера лишь отражают ту точку в истории файла, в которой появилась ветвь. из вышеприведенного примера можно узнать, что перед тем, как была создана ветка, `driver.c' претерпел больше изменений, чем `backend.c'. смотри section ветки и ревизии, где подробно описано, как устроены номера ветвей. ветки и ревизииобычно история ревизий файла -- это линейная возрастающая последовательность номеров (see section номера ревизий): +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! +-----+ +-----+ +-----+ +-----+ +-----+ однако же, cvs не ограничен линейной разработкой. дерево ревизий может быть расщеплено на ветви, где каждая ветвь -- самостоятельная линия разработки. изменения, сделанные на одной ветке, легко могут быть внесены также и в основной ствол. каждая ветка имеет номер ветки, состоящий из нечетного числа десятичных чисел, разделенных точками. номер ветки создается путем добавления целого числа к номеру ревизии, от которой была отщеплена ветка. номера веток позволяют отщеплять от одной и той же ревизии несколько веток. все ревизии на ветке имеют номера ревизий, образованные путем добавления порядкового номера к номеру ветки. вот иллюстрация создания веток. +-------------+ branch 1.2.2.3.2 -> ! 1.2.2.3.2.1 ! / +-------------+ / / +---------+ +---------+ +---------+ branch 1.2.2 -> _! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 ! / +---------+ +---------+ +---------+ / / +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- the main trunk +-----+ +-----+ +-----+ +-----+ +-----+ ! ! ! +---------+ +---------+ +---------+ branch 1.2.4 -> +---! 1.2.4.1 !----! 1.2.4.2 !----! 1.2.4.3 ! +---------+ +---------+ +---------+ обычно не требуется задумываться о точных деталях того, как строятся номера веток, но вот еще подробности: когда cvs создает номер ветки, он берет первое неиспользованное четное число, начиная с двойки. поэтому, если вы хотите создать ветку от ревизии 6.4, она будет называться 6.4.2. номера веток, заканчивающиеся на ноль (например, 6.4.0), используются для внутренних нужд cvs (see section волшебные номера веток). ветка 1.1.1 имеет специальное значение. see section слежение за чужими исходными текстами. волшебные номера ветокв этой секции описана возможность cvs, называющаяся волшебные ветки. в большинстве случаев вам не потребуется беспокоиться о волшебных ветках, так как cvs сам следит за ними. однако, при определенных условиях их можно увидеть, и поэтому полезно было бы узнать, как они работают. номера веток состоят из нечетного количества десятичных целых чисел, разделенных точками. see section номера ревизий. однако же, это не полная правда. из соображений эффективности cvs иногда вставляет лишний ноль во вторую справа позицию (1.2.4 становится 1.2.0.4, а 8.9.10.11.12 становится 8.9.10.11.0.12 и так далее). cvs довольно хорошо прячет такие "волшебные" ветки, но в нескольких местах ему это не удается:
можно использовать команду $ cvs admin -nr4patches:1.4.2 numbers.c это сработает, только если хотя бы одна ревизия уже была зафиксирована на ветке. будьте очень осторожны, чтобы не присвоить метку неправильному числу, так как нет способа узнать, чему была присвоена эта метка вчера (за исключением ежедневного резервного копирования). слияние веток
вы можете объединить изменения, сделанные на ветке, с вашей
рабочей копией, добавив флаг `-j ветка' к команде
ключ командной строки `-j' означает "объединить" (join). представьте себе такое дерево ревизий: +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 ! <- основной ствол +-----+ +-----+ +-----+ +-----+ ! ! ! +---------+ +---------+ ветвь r1fix -> +---! 1.2.2.1 !----! 1.2.2.2 ! +---------+ +---------+ ветке 1.2.2 была назначена метка (символьное имя) `r1fix'. в нижеследующем примере предполагается, что модуль `mod' содержит единственный файл, `m.c'. $ cvs checkout mod # извлечь последнюю ревизию, 1.4 $ cvs update -j r1fix m.c # слить все изменения, сделанные на ветке, # т. е. изменения между ревизиями 1.2 # и 1.2.2.2, в рабочую копию файла $ cvs commit -m "included r1fix" # создать ревизию 1.5. в результате операции слияния может произойти конфликт. в это случае вам сначала надо справиться с ним перед фиксированием изменений. see section пример конфликта.
команда $ cvs checkout -j r1fix mod $ cvs commit -m "добавлен r1fix" многократное слияние из веткимы продолжаем обсуждение примера. теперь дерево ревизий выглядит так: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- ствол +-----+ +-----+ +-----+ +-----+ +-----+ ! * ! * ! +---------+ +---------+ ветвь r1fix -> +---! 1.2.2.1 !----! 1.2.2.2 ! +---------+ +---------+ здесь линия из звездочек представляет собой слияние ветки `r1fix' с основным стволом, обсуждавшееся только что. предположим теперь, что разработка ветки `r1fix' продолжается: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- ствол +-----+ +-----+ +-----+ +-----+ +-----+ ! * ! * ! +---------+ +---------+ +---------+ ветвь r1fix -> +---! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 ! +---------+ +---------+ +---------+
и теперь вы опять хотите слить свежайшие изменения с основным
стволом. если бы вы просто использовали команду вместо этого вам нужно указать, что вы хотите слить только те изменения на ветке, что еще не были объединены со стволом. для этого вы указываете два ключа командной строки `-j', и cvs сливает изменения между первой и второй ревизиями. например, в этом случае самым простым способом будет cvs update -j 1.2.2.2 -j r1fix m.c # слить изменения между 1.2.2.2 и # головой ветки r1fix проблемой здесь является то, что вы должны вручную указать ревизию 1.2.2.2. чуть лучшим подходом будет использование даты совершения последнего слияния. cvs update -j r1fix:yesterday -j r1fix m.c еще лучше было бы помечать ветку `r1fix' после каждого слияния со стволом, и использовать эту метку для дальнейших слияний: cvs update -j merged_from_r1fix_to_trunk -j r1fix m.c слияние изменений между двумя ревизиями
с помощью двух флагов `-j ревизия', команды $ cvs update -j 1.5 -j 1.3 backend.c отменит изменения, сделанные между ревизиями 1.3 и 1.5. обратите внимание на порядок указания ревизий! если вы попробуете использовать эту опцию при работе с несколькими файлами, помните, что номера ревизий, вероятно, будут сильно отличаться для разных файлов. в таких случаях почти всегда следует использовать символьные метки, а не номера ревизий. указав два ключа командной строки `-j', можно также отменить удаление или добавление файла. например, предположим, у вас есть файл `file1', существовавший в ревизии 1.1. затем вы удалили его, создав "мертвую" ревизию 1.2. теперь предположим, что вы хотите добавить его опять, с тем же самым содержимым, что он имел ранее. вот как сделать это: $ cvs update -j 1.2 -j 1.1 file1 u file1 $ cvs commit -m test checking in file1; /tmp/cvs-sanity/cvsroot/first-dir/file1,v <-- file1 new revision: 1.3; previous revision: 1.2 done $ при слиянии можно добавлять и удалять файлы
если изменения, которые вы сливаете, включают в себя удаление или
добавление каких-либо файлов, то команда for example: cvs update -a touch a b c cvs add a b c ; cvs ci -m "added" a b c cvs tag -b branchtag cvs update -r branchtag touch d ; cvs add d rm a ; cvs rm a cvs ci -m "added d, removed a" cvs update -a cvs update -jbranchtag после того, как эти команды выполнены, а также выполнена команда `cvs commit', файл `a' будет удален, а файл `d' будет добавлен в основной ствол. go to the first, previous, next, last section, table of contents. |