#LyX 2.1 created this file. For more info see http://www.lyx.org/ \lyxformat 474 \begin_document \begin_header \textclass article \begin_preamble \let\stdpart\part \renewcommand\part{\newpage\stdpart} \usepackage{indentfirst} % Красная строка \sloppy % русские переносы % содержание и нумерация \setcounter{tocdepth}{4} % table of contents depth \setcounter{secnumdepth}{4} % numbering depth % Fix PDF's cross-reference jumps \restylefloat{table} \restylefloat{figure} \end_preamble \use_default_options true \begin_modules braille enumitem fix-cm initials figs-within-sections tabs-within-sections eqs-within-sections endnotes foottoend logicalmkup hanging \end_modules \maintain_unincluded_children false \language russian \language_package default \inputencoding utf8 \fontencoding global \font_roman default \font_sans default \font_typewriter default \font_math auto \font_default_family default \use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default \default_output_format default \output_sync 0 \bibtex_command default \index_command default \float_placement H \paperfontsize default \spacing single \use_hyperref true \pdf_title "Git-tutorial" \pdf_author "Kolan Sh, InSys Ltd, Moscow" \pdf_subject "Git" \pdf_keywords "git,tutorial" \pdf_bookmarks true \pdf_bookmarksnumbered true \pdf_bookmarksopen true \pdf_bookmarksopenlevel 3 \pdf_breaklinks false \pdf_pdfborder true \pdf_colorlinks true \pdf_backref false \pdf_pdfusetitle true \papersize default \use_geometry true \use_package amsmath 1 \use_package amssymb 1 \use_package cancel 1 \use_package esint 1 \use_package mathdots 1 \use_package mathtools 1 \use_package mhchem 1 \use_package stackrel 1 \use_package stmaryrd 1 \use_package undertilde 1 \cite_engine basic \cite_engine_type default \biblio_style plain \use_bibtopic false \use_indices false \paperorientation portrait \suppress_date false \justification true \use_refstyle 1 \index Index \shortcut idx \color #008000 \end_index \leftmargin 1.5cm \topmargin 1.5cm \rightmargin 1cm \bottommargin 2cm \secnumdepth 5 \tocdepth 5 \paragraph_separation indent \paragraph_indentation default \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle fancy \tracking_changes false \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict false \end_header \begin_body \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash title{Краткое введение в Git} \end_layout \begin_layout Plain Layout \backslash author{Колян Ш. \backslash \backslash \backslash normalsize Версия 1.3.5} \end_layout \begin_layout Plain Layout \backslash maketitle \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset CommandInset toc LatexCommand tableofcontents \end_inset \end_layout \begin_layout Standard \lang english \begin_inset Newpage newpage \end_inset \end_layout \begin_layout Section Начало работы \end_layout \begin_layout Subsection Регистрация в Gitorious \end_layout \begin_layout Subsubsection Создание нового пользователя \end_layout \begin_layout Standard Для регистрации нужно перейти по ссылке \begin_inset Flex URL status collapsed \begin_layout Plain Layout https://git.insysltd.ru/users/new \end_layout \end_inset . Будет предложено ввести логин, Email и пароль. Эти данные требуются исключительно для доступа к репозиториям и проектам Gitorious посредством Web-интерфейса. Вместо этих данных возможно использование OpenID ( \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://ru.wikipedia.org/wiki/OpenID \end_layout \end_inset ). \end_layout \begin_layout Subsubsection Подтверждение регистрации \end_layout \begin_layout Standard Для подтверждения вновь созданной учётной записи необходимо обратиться к любому из администраторов ресурса. Данная необходимость обусловлена защитой от несанкционированных регистраций со стороны калифорнийских школьников. \end_layout \begin_layout Subsubsection Загрузка OpenSSH-ключа \end_layout \begin_layout Standard Данный ключ требуется для защищённой передачи данных между Git-клиентом и Git-сервером. \end_layout \begin_layout Standard Сгенерировать пару ключей (приватный/общедоступный) можно посредством команды \end_layout \begin_layout LyX-Code ssh-keygen -t rsa \end_layout \begin_layout Standard из пакета OpenSSH \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://www.openssh.org/ \end_layout \end_inset . \end_layout \begin_layout Standard Установочный файл для Windows может быть найден по ссылке \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://sourceforge.net/projects/sshwindows/files/OpenSSH%20for%20Windows%20-%20Re lease/ \end_layout \end_inset . Полученный приватный ключ id_rsa следует хранить в безопасном от чужих глаз месте (в случае получения доступа к нему 3-их лиц следует сгенерировать новый, а старый публичный ключ (.pub) - удалить с Git-сервера). \end_layout \begin_layout Standard Загрузка публичного ключа id_rsa.pub выполняется в Web-интерфейсе профиля пользователя Gitorious\SpecialChar \menuseparator Dashboard\SpecialChar \menuseparator Manage SSH keys\SpecialChar \menuseparator Add SSH Key. \end_layout \begin_layout Subsection Создание нового репозитория \end_layout \begin_layout Standard Если репозиторий добавляется в уже существующий проект, то на вкладке проекта в Web-интерфейсе Gitorious достаточно нажать кнопку Add Repository, ввести имя и описание. \end_layout \begin_layout Standard Если требуется создать новый проект, то в Web-интерфейсе Gitorious нужно выбрать Gitorious\SpecialChar \menuseparator Projects\SpecialChar \menuseparator Create a new project, ввести обязательные поля Title(имя проекта), Slug(идентификатор, генерируется автоматически), Descriptio n(описание). При необходимости могут быть заданы Labels(метки для быстрого поиска), Owner(владелец проекта), License(лицензия), Home URL(домашняя страница проекта), Mailinglist URL(список рассылки), Bugtracker URL(баг-трекер). После нажатия кнопки Create project будет создан новый проект с указанными параметрами и предложено создать в нём первый репозиторий. \end_layout \begin_layout Standard В Git имеется встроенная справка по всем командам, достаточно набрать \end_layout \begin_layout LyX-Code git help command \end_layout \begin_layout Standard Для большинства опций имеются их сокращённые аналоги, например, \end_layout \begin_layout LyX-Code git rebase -i -p # эквивалентно git rebase --interactive --preserve-merges \end_layout \begin_layout Standard и значения по умолчанию: \end_layout \begin_layout LyX-Code git log --decorate # эквивалентно git log --decorate=short \end_layout \begin_layout Subsubsection Первый коммит \end_layout \begin_layout Standard Хорошей практикой считается при создании репозитория включение первым делом в него файла README с пусть даже минимальным описанием того, для чего он создан, какую цель преследует. \end_layout \begin_layout LyX-Code echo \begin_inset Quotes eld \end_inset This is my project for tests. \begin_inset Quotes erd \end_inset > README \end_layout \begin_layout LyX-Code git add README \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset Initial commit. \begin_inset Quotes erd \end_inset \end_layout \begin_layout Itemize Здесь мы создали файл с именем README; \end_layout \begin_layout Itemize Добавили этот файл в индекс Git для включения его в ближайший коммит; \end_layout \begin_layout Itemize Сделали коммит \begin_inset Quotes eld \end_inset Initial commit. \begin_inset Quotes erd \end_inset . \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Индексом в Git называется промежуточное хранилище изменений, попадающих в ближайший коммит. Таким образом, Git даёт возможность избирательно включать те или иные изменения вплоть до отдельных частей файла. Пример: \end_layout \begin_layout LyX-Code git add -p git-tutorial.lyx \end_layout \begin_layout LyX-Code diff --git a/git-tutorial.lyx b/git-tutorial.lyx \end_layout \begin_layout LyX-Code index 8c6fa34..3aaafde 100644 \end_layout \begin_layout LyX-Code --- a/git-tutorial.lyx \end_layout \begin_layout LyX-Code +++ b/git-tutorial.lyx \end_layout \begin_layout LyX-Code @@ -365,7 +365,10 @@ Initial commit. \end_layout \begin_layout LyX-Code \backslash end_layout \backslash begin_layout Standard -В качестве \end_layout \begin_layout LyX-Code +Индексом в Git называется промежуточное хранилище изменений, попадающих \end_layout \begin_layout LyX-Code + в ближайший коммит. \end_layout \begin_layout LyX-Code + Таким образом, Git даёт возможность избирательно включать те или иные изменения \end_layout \begin_layout LyX-Code + вплоть до отдельных частей файла. \end_layout \begin_layout LyX-Code \backslash end_layout \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code \backslash begin_layout Subsubsection \end_layout \begin_layout LyX-Code Stage this hunk [y,n,q,a,d,/,e,?]? y \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Параметр -m у команды commit указывает на то, что следующим аргументом команды следует описание коммита, что удобно, когда нужно коммит сделать быстро. Без указания этого параметра откроется окно редактора, куда требуется внести описание изменений. \end_layout \begin_layout Standard Также, у команды commit помимо параметра -m можно указывать параметр -a, чтобы в коммит добавились все изменения, в том числе и не включенные в индекс. Таким образом, последовательность команд \end_layout \begin_layout LyX-Code vim main.c # editing staged C-file... \end_layout \begin_layout LyX-Code vim main.h # editing staged H-file... \end_layout \begin_layout LyX-Code git commit -am \begin_inset Quotes eld \end_inset Both source and header files are changed. \begin_inset Quotes erd \end_inset \end_layout \begin_layout Standard эквивалентна \end_layout \begin_layout LyX-Code vim main.c # editing staged C-file... \end_layout \begin_layout LyX-Code vim main.h # editing staged H-file... \end_layout \begin_layout LyX-Code git add main.c main.h \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset Both source and header files are changed. \begin_inset Quotes erd \end_inset \end_layout \begin_layout Subsubsection Статус текущих \begin_inset Quotes eld \end_inset незакоммиченных \begin_inset Quotes erd \end_inset изменений \end_layout \begin_layout Standard Текущее состояние рабочей директории можно посмотреть командой status: \end_layout \begin_layout LyX-Code $ git status # вывести текущие изменения \end_layout \begin_layout LyX-Code # On branch #238feature \end_layout \begin_layout LyX-Code # Changes not staged for commit: \end_layout \begin_layout LyX-Code # (use "git add ..." to update what will be committed) \end_layout \begin_layout LyX-Code # (use "git checkout -- ..." to discard changes in working directory) \end_layout \begin_layout LyX-Code # \end_layout \begin_layout LyX-Code # modified: git-tutorial.lyx \end_layout \begin_layout LyX-Code # \end_layout \begin_layout LyX-Code # Untracked files: \end_layout \begin_layout LyX-Code # (use "git add ..." to include in what will be committed) \end_layout \begin_layout LyX-Code # \end_layout \begin_layout LyX-Code # #git-tutorial.lyx# \end_layout \begin_layout LyX-Code # git-tutorial.lyx~ \end_layout \begin_layout LyX-Code # git-tutorial.pdf \end_layout \begin_layout LyX-Code no changes added to commit (use "git add" and/or "git commit -a") \end_layout \begin_layout LyX-Code $ git status -s # использовать сокращённую запись \end_layout \begin_layout LyX-Code M git-tutorial.lyx \end_layout \begin_layout LyX-Code ?? #git-tutorial.lyx# \end_layout \begin_layout LyX-Code ?? git-tutorial.lyx~ \end_layout \begin_layout LyX-Code ?? git-tutorial.pdf \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Сами изменения можно посмотреть командой diff: \end_layout \begin_layout LyX-Code git diff # вывести изменения рабочей директории \end_layout \begin_layout LyX-Code git diff --staged # вывести изменения, добавленные в индекс \end_layout \begin_layout Subsection Синхронизация с Git-сервером \end_layout \begin_layout Subsubsection Добавление удалённого репозитория \end_layout \begin_layout Standard Для синхронизации с Git-сервером необходимо его добавить в список remote: \end_layout \begin_layout LyX-Code git remote add origin git@git.insysltd.ru:test_project/test_repo.git \end_layout \begin_layout Standard origin является удалённым репозиторием по умолчанию при выполнении команд синхронизации и может быть опущен. \end_layout \begin_layout Standard Нормальной практикой является добавление нескольких удалённых веток, например: \end_layout \begin_layout LyX-Code git remote add origin git@git.insysltd.ru:test_project/test_repo.git \end_layout \begin_layout LyX-Code git remote add github git@github.com:test_repo.git \end_layout \begin_layout LyX-Code git remote add usb /media/usb_stick/projects/test_repo.git \end_layout \begin_layout Subsubsection Принятие изменений, сделанных другими пользователями \end_layout \begin_layout Standard В отличие от других систем управления исходным кодом Git работает со слияниями гибче. Поддерживаются так называемые fast-forward слияния (рис. \begin_inset CommandInset ref LatexCommand ref reference "fig:fast-forward-слияния" \end_inset ). \end_layout \begin_layout Standard \begin_inset Float figure placement H wide false sideways false status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/vRdkr.png scale 50 rotateOrigin center \end_inset \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:fast-forward-слияния" \end_inset fast-forward слияния \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard При выполнении команды git pull скачиваются удалённые изменения (git fetch) и выполняется слияние (git merge). При указании опции --rebase коммиты из удалённого репозитория займут своё место перед локальными коммитами - теми, которые ещё не были отправлены на Git-сервер. \end_layout \begin_layout LyX-Code git pull --rebase \end_layout \begin_layout Standard Это даёт возможность пользователям работать, не мешая друг-другу, выполняя при этом коммиты тогда, когда хочется пользователю, а не тогда, когда доступен главный репозиторий. \end_layout \begin_layout Standard Иногда более целесообразно указывать, из какой удалённо ветки требуется произвести слияние коммитов: \end_layout \begin_layout LyX-Code git pull --rebase origin develop \end_layout \begin_layout Subsubsection Слияние веток \end_layout \begin_layout Standard Как правило, слияние веток необходимо по завершении той или иной фичи (от англ. feature) или исправления бага (от англ. bug). Приведём возможный сценарий для реализации некоторой возможности featureA. \end_layout \begin_layout LyX-Code git checkout -b featureA develop # ответвление featureA от develop \end_layout \begin_layout LyX-Code ... edit ... commit ... \end_layout \begin_layout LyX-Code ... edit ... commit ... \end_layout \begin_layout LyX-Code ... edit ... commit ... \end_layout \begin_layout LyX-Code git reset --soft develop # вместо develop может быть хеш коммита \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset Feature A implemented. \begin_inset Quotes erd \end_inset # получение из нескольких коммитов одного \end_layout \begin_layout LyX-Code git checkout develop # возврат в ветку разработки develop \end_layout \begin_layout LyX-Code git merge --no-ff featureA # слияние без --no-ff, если предпочитаете линейную историю \end_layout \begin_layout LyX-Code git branch -d featureA # удаление \begin_inset Quotes eld \end_inset слитой \begin_inset Quotes erd \end_inset ветки featureA \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard При работе с системами управления проектами (ChilliProject, Redmine, Trac) по завершении работы с ветвью имеет смысл добавлять в сообщение коммита отметку о решении/закрытии бага/фичи. Система управления проектами автоматически пометит тикет как решённый и свяжет его с указанным коммитом, так что любой может определить какие изменения были внесены для решения конкретной задачи. Пример: \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset Feature A implemented. Closes #238. \begin_inset Quotes erd \end_inset \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset Bug B fixed. Fixes #239. \begin_inset Quotes erd \end_inset \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Также возможно слияние изменений без создания нового коммита (следует отметить, что хеш последнего коммита всё-равно изменится, а с ним изменится и история) посредством команды: \end_layout \begin_layout LyX-Code git merge --squash \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Иногда в списке удалённых веток (git branch -r) остаются несуществующие ссылки в результате того, что кто-то удалил эту ветвь или несколько веток ссылок указывали на одну удалённую ветвь. Обновить список можно командой fetch: \end_layout \begin_layout LyX-Code git fetch \end_layout \begin_layout LyX-Code git fetch github \end_layout \begin_layout Standard или вручную удалить невалидную ссылку: \end_layout \begin_layout LyX-Code git branch -d -r origin/invalid_branch \end_layout \begin_layout LyX-Code git branch -d -r github/invalid_branch2 \end_layout \begin_layout Subsubsection Отправка изменений на сервер \end_layout \begin_layout Standard Для отправки локальных изменений из текущей ветки в репозиторий по умолчанию (origin) необходимо выполнить команду \end_layout \begin_layout LyX-Code git push \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Также возможны более сложные операции, к примеру: \end_layout \begin_layout LyX-Code git push github # отправит изменения всех веток, которые есть в локальном \end_layout \begin_layout LyX-Code # и удалённом (в данном случае GitHub) репозиториях \end_layout \begin_layout LyX-Code git push origin featureA # отправит в origin изменения в ветке featureA \end_layout \begin_layout LyX-Code git push origin localA:featureA # отправит в origin изменения локальной \end_layout \begin_layout LyX-Code # ветки localA в удалённую featureA \end_layout \begin_layout LyX-Code git push origin master develop featureB # отправит 3 указанные ветки \end_layout \begin_layout LyX-Code git push origin :featureC # удалит в удалённом репозитории ветку featureC \end_layout \begin_layout LyX-Code git push origin :v1.0.3 # удалит в origin тег v1.0.3 \end_layout \begin_layout LyX-Code \end_layout \begin_layout Subsubsection Права доступа в Gitorious \end_layout \begin_layout Standard В Web-интерфейсе Gitorious на вкладке управления проектом есть кнопка Manage Access\SpecialChar \menuseparator Make private, позволяющая сделать репозиторий \begin_inset Quotes eld \end_inset закрытым от посторонних глаз \begin_inset Quotes erd \end_inset и разрешить выборочный доступ на чтение для отдельных лиц или групп. В этом случае все репозитории, входящие в данный проект также становятся недоступными всем лицам, кроме одобренных одним из владельцев проекта/репозитор ия. \end_layout \begin_layout Standard Для репозитория, как и для проекта, также возможна установка разрешений. Для этого есть кнопка Manage Read Access\SpecialChar \menuseparator Make private. \end_layout \begin_layout Standard Для возможности внесения изменений в репозиторий несколькими разработчиками требуется добавить этих разработчиков/группы в список разрешения Manage collaborators\SpecialChar \menuseparator Add collaborators и установить для добавленных пользователей/групп их разрешения: Review, Commit, Administer. \end_layout \begin_layout Subsection Работа с чужим репозиторием, pull-requests \end_layout \begin_layout Standard Политика распределённого хранилища подразумевает возможность независимой работы с клонами без вмешательства в репозитории других пользователей. \end_layout \begin_layout Standard Как правило, у отдельно взятого репозитория имеется один или несколько коммитеро в, которым разрешён полный доступ и на ком лежит ответственность за поддержание данного репозитория в рабочем состоянии. Все остальные, кто имеет доступ на чтение данного репозитория реализуют фичи (feature) в своих клонах. По завершении работы над фичей отправляется pull-request разработчику основного репозитория, который осуществляет слияние, когда у него есть на то свободное время. Таким образом разработчики делают каждый свою работу, не мешая друг другу. \end_layout \begin_layout Standard Приведём пример такой работы. \end_layout \begin_layout Subsubsection Получение информации о репозитории \end_layout \begin_layout Standard Общая информация о репозитории может быть получена уже из Web-интерфейса Gitorious, включая ветки, список коммитов, граф коммитов, pull-реквесты и т.п. \end_layout \begin_layout Subsubsection Авторство и время редактирования строк \end_layout \begin_layout Standard Следующий пример покажет авторство, ревизии последних правок и время для нескольких строк в файле исходного кода main.c: \end_layout \begin_layout LyX-Code git blame -L 40,60 main.c # вывести информацию о строках с 40 по 60 включительн о \end_layout \begin_layout LyX-Code git blame -L 40,+21 main.c # вывести информацию о 21-ой строке, начиная с 40-ой \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Если требуется отфильтровать слишком старую историю, можно это сделать следующим образом: \end_layout \begin_layout LyX-Code git blame v2.6.18.. -- main.c # игнорировать информацию, старше версии 2.6.18 \end_layout \begin_layout LyX-Code git blame --since=3.weeks -- main.c # игнорировать информацию, старше 3-х недель \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Вот пример, как можно посчитать общий вклад разработчиков в конкретный файл проекта: \end_layout \begin_layout LyX-Code git blame --line-porcelain mainform.cpp | sed -n 's/^author //p' | sort | uniq -c | sort -rn \end_layout \begin_layout LyX-Code 1526 Kolan Sh \end_layout \begin_layout LyX-Code 691 egor_i@egor-837.insysltd.ru \end_layout \begin_layout LyX-Code 167 egor_i@EGOR-837 \end_layout \begin_layout Subsubsection Клонирование \end_layout \begin_layout Standard Более подробная информация, включая поиск по коммитам возможна после клонировани я репозитория. Если Вы не хотите отвлекать от работы владельца репозитория, но при этом хотите коммитить, будет удобно сделать удалённый клон в Gitorious (кнопка Clone repository у любого проекта в Web-интерфейсе). Будет предложено ввести имя клона, которое будет уже заполнено по умолчанию (в начало), так что его можно не менять. \end_layout \begin_layout Standard Далее выполняется стандартная процедура клонирования удалённого клона на локальный диск: \end_layout \begin_layout LyX-Code git clone git@git.insysltd.ru:~user1/test_project/user1-test_repo.git \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Если репозиторий содержит субрепозитории (submodules) необходимо их инициализиро вать и синхронизировать: \end_layout \begin_layout LyX-Code git submodule update --init --recursive \end_layout \begin_layout Subsubsection pull-request - запрос на слияние \end_layout \begin_layout Standard По завершении работы (реализации фичи или устранения бага) нужно залить в свой удалённый клон, при необходимости, обновив его (git pull --rebase) из исходного репозитория. \end_layout \begin_layout Standard Далее в Web-интерфейсе клона нажать кнопку Request merge, добавить описание pull-запроса, указать исходный репозиторий и ветки. Ваш запрос на слияние появится в списке входящих сообщений пользователя, владеющего оригиналом репозитория. \end_layout \begin_layout Subsubsection format-patch - создание патча \end_layout \begin_layout Standard Когда лень делать удалённый клон в Gitorious с pull-request-ом и есть уверенност ь, что Ваш патч примут сразу, а не спустя длительное время, когда в основном дереве накопится изменений, конфликтующих с патчем, можно использовать быстрое создание патча: \end_layout \begin_layout LyX-Code git checkout -b fix_the_bug master # создаём ответвление от master \end_layout \begin_layout LyX-Code ... edit ... \end_layout \begin_layout LyX-Code git commit -am \begin_inset Quotes eld \end_inset The bug fixed. \begin_inset Quotes erd \end_inset \end_layout \begin_layout LyX-Code git format-patch master # создать патч, включающий отличия текущей ревизии от ветки master \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Далее полученный патч может быть отправлен по email или прямо в окно Jabber-клие нта. Можно создать патч и отправить его по email одной командой: \end_layout \begin_layout LyX-Code git format-patch master --stdout | mail -s 'Please apply this patch, Leo' leo@matrix.org \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Применить полученный патч можно командой apply: \end_layout \begin_layout LyX-Code git apply --check the_bug_fixed.patch # тест на конфликты \end_layout \begin_layout LyX-Code git apply --stat # применение патча с включением в историю текущей ветви \end_layout \begin_layout LyX-Code # и выводом статистики изменений \end_layout \begin_layout Subsection Анализ истории, сравнение, поиск и фильтрация \end_layout \begin_layout Subsubsection Список ветвей \end_layout \begin_layout Standard Выводится командой branch \end_layout \begin_layout LyX-Code git branch # список локальных веток \end_layout \begin_layout LyX-Code git branch -r # список удалённых веток \end_layout \begin_layout LyX-Code git branch -a # список всех веток, включая удалённые \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard За более полным списком опций следует обратиться к справке по команде branch (git help branch). \end_layout \begin_layout Subsubsection Лог истории \end_layout \begin_layout Standard Наболее полную информацию об истории изменений можно получить командой \end_layout \begin_layout LyX-Code git log --graph --decorate --stat \end_layout \begin_layout Standard - Git выведет графическое изображение дерева истории, включая слияния, подписи и статистику изменений по каждому коммиту, где: \end_layout \begin_layout Itemize - \begin_inset space \thinspace{} \end_inset -graph -- выводить графическое дерево; \end_layout \begin_layout Itemize - \begin_inset space \thinspace{} \end_inset -decorate -- выводить у коммитов имена ссылок (ref names), например master, origin/develop; \end_layout \begin_layout Itemize - \begin_inset space \thinspace{} \end_inset -stat -- печатать статистику по изменениям в каждом файле. \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Если нужно вывести лог на определённом временном промежутке, через две точки вводится начало и конец: \end_layout \begin_layout LyX-Code git log master..develop \end_layout \begin_layout LyX-Code git log f8a32c..3ab98c \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Можно исключать из выводимого списка коммиты, входящие в какую-либо ветвь, например следующая команда выведет список коммитов из develop, не вошедшие в master: \end_layout \begin_layout LyX-Code git log develop ^master \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Более полный список опций описан в руководстве (git help log). \end_layout \begin_layout Subsubsection Сравнение ревизий \end_layout \begin_layout Standard Сравнение производится командой git diff. Примеры: \end_layout \begin_layout LyX-Code git diff # показать текущие изменения в рабочей директории \end_layout \begin_layout LyX-Code git diff --staged # показать текущие изменения в рабочей директории, добавленные в индекс \end_layout \begin_layout LyX-Code git diff master..develop main.c # показать разницу main.c между двумя ветвями \end_layout \begin_layout LyX-Code git diff 581a32..8f292a --stat # показать статистику различий между ревизиями \end_layout \begin_layout Subsubsection Поиск и фильтрация \end_layout \begin_layout Standard Для поиска используется всё та же команда log, но с параметрами: \end_layout \begin_layout LyX-Code git log --author= \begin_inset Quotes erd \end_inset Vasya Pupkin \begin_inset Quotes erd \end_inset # поиск по автору \end_layout \begin_layout LyX-Code git log --author=" \backslash (Adam \backslash ) \backslash | \backslash (Jon \backslash )" # поиск по одному из авторов \end_layout \begin_layout LyX-Code git log -Ssome_string --source --all # поиск по строке some_string с выводом ссылок на \end_layout \begin_layout LyX-Code # удалённые репозитории, из которых достижима ревизия \end_layout \begin_layout LyX-Code git log path/to/file # коммиты, затрагивающие данный файл \end_layout \begin_layout LyX-Code git log --grep=feature # коммиты с сообщениями о фичах \end_layout \begin_layout LyX-Code \end_layout \begin_layout Section Удобство в работе \end_layout \begin_layout Subsection Индекс, откат, временное хранилище \end_layout \begin_layout Standard В Git имеются команды, делающие работу более удобной. Так, в частности, можно спрятать все незакомиченные изменения рабочей директори и и достать их в любой момент обратно: \end_layout \begin_layout LyX-Code git stash # спрятать изменения \end_layout \begin_layout LyX-Code git stash pop # применить их к рабочей директории и удалить их из stash-списка \end_layout \begin_layout LyX-Code git stash --keep-index # спрятать изменения, не добавленные в индекс \end_layout \begin_layout LyX-Code git stash drop # \begin_inset Quotes eld \end_inset выбросить \begin_inset Quotes erd \end_inset спрятанные изменения \end_layout \begin_layout LyX-Code git stash save --keep-index # спрятать изменения, не добавленные в индекс \end_layout \begin_layout LyX-Code git stash apply # применить спрятанные изменения, не удаляя их из stash-списка \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Можно получить любую версию файла или директории посредством команды checkout: \end_layout \begin_layout LyX-Code git checkout README # получить README-файл, отменив изменения после последнего коммита \end_layout \begin_layout LyX-Code git checkout main.c 3f89a7f # получить main.c из ревизии 3f89a7f \end_layout \begin_layout LyX-Code git checkout . # получить из головы (HEAD) содержимое текущей директории \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Можно отменить изменения, попавшие в индекс для следующего коммита: \end_layout \begin_layout LyX-Code git reset # очистить индекс \end_layout \begin_layout LyX-Code git reset main.h # убрать из индекса main.h \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Вся история команд работы с Git хранится в локальном списке reflog: \end_layout \begin_layout LyX-Code $ git reflog \end_layout \begin_layout LyX-Code 39b103b HEAD@{2}: commit: Adding feature #238... \end_layout \begin_layout LyX-Code 8958552 HEAD@{3}: reset: moving to develop \end_layout \begin_layout LyX-Code 7e3dca9 HEAD@{4}: commit: akt_half_tv3-117vm-00.lyx added. \end_layout \begin_layout LyX-Code 8958552 HEAD@{5}: reset: moving to develop \end_layout \begin_layout Standard так, что имеется возможность локального восстановления в истории случайно удалённого коммита. Можно, к примеру, откатить голову (HEAD) ветки develop к моменту, когда был добавлен lyx-файл: \end_layout \begin_layout LyX-Code git checkout develop \end_layout \begin_layout LyX-Code git reset --hard 7e3dca9 \end_layout \begin_layout LyX-Code git push -f origin develop \end_layout \begin_layout Standard или просто получить в рабочей директории прежнее состояние, не изменяя истории: \end_layout \begin_layout LyX-Code git checkout 7e3dca9 \end_layout \begin_layout Subsection Теги и версии \end_layout \begin_layout Standard Как правило, теги создаются для определённых версий проекта, но могут и не следовать этому правилу. \end_layout \begin_layout Standard В случае создания новой версии проекта, хорошим стилем является обновление записи о версии внутри проекта, например version.h с последющим коммитом. \end_layout \begin_layout Standard Приведём типичный пример: \end_layout \begin_layout LyX-Code git checkout -b release-1.0.0 develop \end_layout \begin_layout LyX-Code vim version.h # update version number \end_layout \begin_layout LyX-Code git commit -am \begin_inset Quotes eld \end_inset Bumped version number to 1.0.0 \begin_inset Quotes erd \end_inset \end_layout \begin_layout LyX-Code git checkout master \end_layout \begin_layout LyX-Code git merge --no-ff release-1.0.0 \end_layout \begin_layout LyX-Code git tag v1.0.0 \end_layout \begin_layout LyX-Code git checkout develop \end_layout \begin_layout LyX-Code git merge --no-ff release-1.0.0 \end_layout \begin_layout LyX-Code git branch -d release-1.0.0 \end_layout \begin_layout LyX-Code git push origin master develop --tags \end_layout \begin_layout Subsection Редактирование истории \end_layout \begin_layout Subsubsection Редактирование недавних коммитов \end_layout \begin_layout Standard Изменение сообщения последнего коммита выполняется командой \end_layout \begin_layout LyX-Code git commit --amend \end_layout \begin_layout Standard - откроется текстовый редактор, в котором следует отредактировать сообщение последнего коммита. \end_layout \begin_layout Standard Для отмены последних нескольких коммитов в текущей ветви требуется выполнить команду \end_layout \begin_layout LyX-Code git reset --hard HEAD~3 # отменит последние 3 коммита \end_layout \begin_layout LyX-Code git push -f # и удалит их с центрального репозитория \end_layout \begin_layout Subsubsection Редактирование коммита в глубинах истории \end_layout \begin_layout Standard Для редактирования коммита, совершённого на более ранних этапах следует прибегнуть к команде rebase: \end_layout \begin_layout LyX-Code git rebase bbc643cd^ --interactive --preserve-merges # редактировать коммит bbc643cd \end_layout \begin_layout LyX-Code # --preserve-merges - пытаться сохранять точки слияния во время перестройки истории \end_layout \begin_layout LyX-Code vim main.c # редактирование main.c \end_layout \begin_layout LyX-Code vim main.h # редактирование main.h \end_layout \begin_layout LyX-Code git add main.c main.h # добавление main.c and main.h в индекс \end_layout \begin_layout LyX-Code git commit --amend # обновление коммита bbc643cd (теперь у него новый хеш) \end_layout \begin_layout LyX-Code git rebase --continue # обновить все последующие коммиты в данной ветке \end_layout \begin_layout LyX-Code git push -f # отправить изменённую ветвь на Git-сервер \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Также, в некоторых случаях бывает необходимо отредактировать самый первый коммит (root-commit): \end_layout \begin_layout LyX-Code git rebase -i -p --root # редактировать самый первый коммит \end_layout \begin_layout LyX-Code mkdir tmp && mv * tmp # разобьём первый коммит на 2 \end_layout \begin_layout LyX-Code touch README && git add README # и добавим README-файл \end_layout \begin_layout LyX-Code git commit -am \begin_inset Quotes eld \end_inset Initial commit. \begin_inset Quotes erd \end_inset \end_layout \begin_layout LyX-Code mv tmp/* . && rmdir tmp && git add . # добавим то, что было прежде 1-ым коммитом \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset 2nd commit. \begin_inset Quotes erd \end_inset # во второй коммит. \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Объединение нескольких коммитов в один можно выполнить ещё проще: \end_layout \begin_layout LyX-Code git rebase -i -p HEAD~5 \end_layout \begin_layout LyX-Code # редактирование: заменить 'pick' на 'squash' для коммитов, \end_layout \begin_layout LyX-Code # которые хотим объединить, сохранить. \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Разбить произвольный коммит на два последовательных коммита можно следующими командами: \end_layout \begin_layout LyX-Code git rebase -i ^ branch_name \end_layout \begin_layout LyX-Code git rebase HEAD^ \end_layout \begin_layout LyX-Code git add -p # add changes for the 1th commit \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset 1st commit \begin_inset Quotes erd \end_inset # make 1st commit \end_layout \begin_layout LyX-Code git commit -am \begin_inset Quotes eld \end_inset 2nd commit \begin_inset Quotes erd \end_inset # make 2nd commit \end_layout \begin_layout LyX-Code git rebase --continue # complete rebase operation \end_layout \begin_layout Subsubsection Выделение поддиректории в отдельный репозиторий \end_layout \begin_layout Standard Информация взята со \begin_inset CommandInset href LatexCommand href name "stackoverflow.com" target "http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository" \end_inset . \end_layout \begin_layout Standard Предположим, имеется репозиторий со структурой директорий \end_layout \begin_layout LyX-Code XYZ/ \end_layout \begin_deeper \begin_layout LyX-Code .git/ \end_layout \begin_layout LyX-Code XY1/ \end_layout \begin_layout LyX-Code ABC/ \end_layout \begin_layout LyX-Code XY2/ \end_layout \end_deeper \begin_layout Standard и требуется его разбить на 2 репозитория, чтобы истории их не пересекались: \end_layout \begin_layout LyX-Code XYZ/ \end_layout \begin_deeper \begin_layout LyX-Code .git/ \end_layout \begin_layout LyX-Code XY1/ \end_layout \begin_layout LyX-Code XY2/ \end_layout \end_deeper \begin_layout LyX-Code ABC/ \end_layout \begin_deeper \begin_layout LyX-Code .git/ \end_layout \begin_layout LyX-Code ABC/ \end_layout \end_deeper \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Для этого воспользуемся командой filter-branch, изменяющей историю. \end_layout \begin_layout LyX-Code git clone XYZ ABC # клонируем XYZ в ABC \end_layout \begin_layout LyX-Code for branch in develop master; do git branch -t $branch origin/$branch; done # интересующие \end_layout \begin_layout LyX-Code # нас ветви \end_layout \begin_layout LyX-Code git remote rm origin # удаляем ссылку на родительский репозиторий, \end_layout \begin_layout LyX-Code # чтобы обезопасить себя от изменений в нём \end_layout \begin_layout LyX-Code git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch XY1 XY2" \backslash \end_layout \begin_layout LyX-Code --prune-empty --tag-name-filter cat -- --all # удалить из истории дир-рии XY1 и XY2, \end_layout \begin_layout LyX-Code # оставив ABC \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Аналогично создаётся репозиторий для XYZ \end_layout \begin_layout LyX-Code git clone XYZ XYZ-new && cd XYZ-new \end_layout \begin_layout LyX-Code for branch in develop master; do git branch -t $branch origin/$branch; done \end_layout \begin_layout LyX-Code git remote rm origin \end_layout \begin_layout LyX-Code git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ABC" \backslash \end_layout \begin_layout LyX-Code --prune-empty --tag-name-filter cat -- --all \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard По опциям команды filter-branch смотрите документацию (git help filter-branch). \end_layout \begin_layout Subsubsection Удаление коммита из истории \end_layout \begin_layout Standard Удаление последнего созданного коммита осуществляется одной командой и всегда завершается успехом. \end_layout \begin_layout LyX-Code git reset --hard HEAD~1 # удалить последний коммит \end_layout \begin_layout LyX-Code git reset --soft HEAD~1 # удалить последний коммит, сохранив изменения в \begin_inset Quotes eld \end_inset незакомиченными \begin_inset Quotes erd \end_inset \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Удаление коммита из глубин истории не всегда может быть выполнено успешно, может потребоваться разрешение конфликтов. \end_layout \begin_layout LyX-Code git rebase -i --preserve-merges HEAD~10 # редактировать последние 10 коммитов, сохраняя слияния \end_layout \begin_layout LyX-Code # В редакторе отметить удаляемый коммит для редактирования \begin_inset Quotes eld \end_inset edit \begin_inset Quotes erd \end_inset \end_layout \begin_layout LyX-Code git reset --hard HEAD~1 # удалить требуемый коммит \end_layout \begin_layout LyX-Code git rebase --continue # продолжить перепостроение истории, начиная с удалённого коммита \end_layout \begin_layout Subsubsection Удаление тега в репозитории на сервере \end_layout \begin_layout Standard Следующая команда удалит тег v0.1.2 на сервере: \end_layout \begin_layout LyX-Code git push origin :refs/tags/v0.1.2 \end_layout \begin_layout Standard Следует не забыть также удалить тег локально: \end_layout \begin_layout LyX-Code git tag -d v0.1.2 \end_layout \begin_layout Standard Иначе - при следующей отправки изменений он также попадёт на сервер. \end_layout \begin_layout Subsubsection Обновление указателя головы ветки на сервере без локальных изменений \end_layout \begin_layout Standard Следующая команда обновит указатель головы на сервере: \end_layout \begin_layout LyX-Code git update-ref refs/heads/master 573f69d \end_layout \begin_layout Standard Теперь голова ветки \begin_inset Quotes eld \end_inset master \begin_inset Quotes erd \end_inset в репозитории на сервере будет указывать на коммит с хешем 573f69d. Это бывает полезно, когда хочется поработать над частью локальных коммитов, отправляя невсе их сразу на сервер, а частями. \end_layout \begin_layout Subsubsection Синхронизация веток \end_layout \begin_layout Standard По аналогии с командой git pull --rebase для принятия удалённых изменений с перемещением локальных коммитов на вершину истории синхронизация веток может осуществляться и локально. \end_layout \begin_layout LyX-Code # Синхронизировать текущую ветку с веткой branch1, переместив коммиты, \end_layout \begin_layout LyX-Code # отсутствующие в branch1 на вершину истории \end_layout \begin_layout LyX-Code git rebase branch1 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Синхронизировать текущую ветку с удалённой, переместив коммиты, \end_layout \begin_layout LyX-Code # отсутствующие в origin/master на вершину истории \end_layout \begin_layout LyX-Code git fetch origin master \end_layout \begin_layout LyX-Code git rebase origin/master \end_layout \begin_layout Subsection Пример использования gitflow \end_layout \begin_layout LyX-Code # Создание веток master/developer/release/hotfix \end_layout \begin_layout LyX-Code $ git flow init \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Начинаем работать над функционалом feature1 (ответвление от develop) \end_layout \begin_layout LyX-Code $ git flow feature start feature1 \end_layout \begin_layout LyX-Code # делаем изменения \end_layout \begin_layout LyX-Code $ git add ...изменения... \end_layout \begin_layout LyX-Code $ git commit -m "изменения для feature1" \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Эта команда сделает слияние feature1 с develop и удалит ветку \end_layout \begin_layout LyX-Code $ git flow feature finish feature1 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Давайте начнём работу над релизом \end_layout \begin_layout LyX-Code $ git flow release start release1 \end_layout \begin_layout LyX-Code # делаем изменения \end_layout \begin_layout LyX-Code $ git add ...изменения... \end_layout \begin_layout LyX-Code $ git commit -m "release1" \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Эта команда сделает слияние release1 с master \end_layout \begin_layout LyX-Code $ git flow release finish release1 \end_layout \begin_layout Subsection Двоичный поиск ошибок \end_layout \begin_layout Standard Выполняется командой bisect, пример: \end_layout \begin_layout LyX-Code git bisect start \end_layout \begin_layout LyX-Code git bisect bad # текущая ревизия плохая \end_layout \begin_layout LyX-Code git bisect good v1.0.3 # в версии 1.0.3 проблема не наблюдалась \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code git bisect bad # пометить текущую ревизию как плохую \end_layout \begin_layout LyX-Code git bisect good # пометить текущую ревизию как хорошую \end_layout \begin_layout LyX-Code git bisect skip # пропустить текущую ревизию \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code git bisect reset # закончить двоичный поиск \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Как только bisect нашёл источник ошибки - ревизию, в которой она была внесена, для нахождения ошибки остаётся проанализировать изменения в одном текущем коммите. \end_layout \begin_layout Standard Дальнейшие действия зависят от вкусов/стиля разработки: \end_layout \begin_layout Itemize ошибка может быть исправлена прямо в текущей ревизии и \begin_inset Quotes eld \end_inset смержена \begin_inset Quotes erd \end_inset в нужные ветви; \end_layout \begin_layout Itemize может быть сделано ответвление от ветки develop или исправлено прямо в ней; \end_layout \begin_layout Itemize может быть сделан хотфикс (hotfix) ответвлением от master с последующим выпуском новой версии и слиянием исправлений в master и develop. \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Случаются ситуации, когда в дереве истории Git нужно найти коммит, где ошибка была исправлена, например, чтобы сообщить мэнтайнеру проекта для отметки в баг-трекере или бэкпортирования (cherry-pick) в другие долгие \begin_inset Quotes eld \end_inset longtime \begin_inset Quotes erd \end_inset ветки проекта. Для этого используются все те же самые команды, только вместо git bisect bad нужно вводить git bisect good и наоборот, так как вместо \begin_inset Quotes eld \end_inset плохого \begin_inset Quotes erd \end_inset ( \begin_inset Quotes eld \end_inset bad \begin_inset Quotes erd \end_inset ) коммита с ошибкой мы ищем \begin_inset Quotes eld \end_inset хороший \begin_inset Quotes erd \end_inset ( \begin_inset Quotes eld \end_inset good \begin_inset Quotes erd \end_inset ) коммит с нужным исправлением. \end_layout \begin_layout Subsection cherry-pick - обмен коммитами между ветками \end_layout \begin_layout Standard Команда cherry-pick позволяет скопировать определённые коммиты из одной ветки в другую как если бы они были созданы изначально в ней. Например: \end_layout \begin_layout LyX-Code git cherry-pick master # скопирует последний коммит из master в текущую ветвь \end_layout \begin_layout LyX-Code git cherry-pick ..master # применить все коммиты из master, отсутствующие в текущей ветке \end_layout \begin_layout LyX-Code git cherry-pick master~4 master~2 # скопировать 2 коммита из master \end_layout \begin_layout LyX-Code # (3-ий и 4-ый, начиная с головы) \end_layout \begin_layout LyX-Code git cherry-pick -n master~1 next # применить предпоследний из master и последний из next коммиты \end_layout \begin_layout LyX-Code # к рабочей директории и индексу, не создавая новой ревизии \end_layout \begin_layout LyX-Code git cherry-pick --ff ..next # если история линейная и HEAD является предшественником master, \end_layout \begin_layout LyX-Code # обновить рабочую директорию и переустановить HEAD на последний \end_layout \begin_layout LyX-Code # коммит master, в противном случае - скопировать все коммиты \end_layout \begin_layout LyX-Code # из master \end_layout \begin_layout LyX-Code git rev-list --reverse master -- README | git cherry-pick -n --stdin # вывести хеши ревизий \end_layout \begin_layout LyX-Code # в master, затрагивающие файл README и применить их одним коммитом к текущей ветви \end_layout \begin_layout Subsection Субрепозитории \end_layout \begin_layout Subsubsection Субмодули \end_layout \begin_layout Standard Или так называемые Git submodules. Применяются для включения одних проектов в другие или для создания суперпроекто в. При этом обновления в подпроектах не затрагивают основной проект до тех пор, пока владелец проекта не захочет это сделать явно, убедившись, что эти изменения оставляют проект в рабочем состоянии. \end_layout \begin_layout Standard Создать Git submodule очень просто, например добавим в некоторый проект my-project библиотеку my-lib: \end_layout \begin_layout LyX-Code cd my-project \end_layout \begin_layout LyX-Code git submodule add git@git.github.com:mynickname/my-lib.git \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset Added my-lib submodule. \begin_inset Quotes erd \end_inset \end_layout \begin_layout LyX-Code git push \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Команда \end_layout \begin_layout LyX-Code git submodule update --init --recursive \end_layout \begin_layout Standard рекурсивно обновляет всем субмодули, которые в свою очередь могут содержать другие субмодули из origin remote. Следует отметить, что после выполнения данной команды сурепозитории могут оказаться в \begin_inset Quotes eld \end_inset detached state \begin_inset Quotes erd \end_inset , то есть не привязанными к какой-либо ветке. \end_layout \begin_layout Standard Если требуется внести изменения в субрепозиторий, то это делается как и с обычным проектом (edit, commit, push). Важно отметить, что изменения в субрепозитории не влияют на главный репозиторий до тех пор, пока в нём это явно не будет указано: \end_layout \begin_layout LyX-Code git add my-lib \end_layout \begin_layout LyX-Code git commit -m \begin_inset Quotes eld \end_inset my-lib submodule updated. \begin_inset Quotes erd \end_inset \end_layout \begin_layout Subsubsection Поддеревья \end_layout \begin_layout Standard Или так называемые Git subtrees. \end_layout \begin_layout Standard Вначале нужно добавить репозиторий, который будет использоваться как subtree: \end_layout \begin_layout LyX-Code git remote add mylib_remote git@git.insysltd.ru:insys/mylib.git \end_layout \begin_layout LyX-Code git fetch mylib_remote \end_layout \begin_layout LyX-Code git checkout -b mylib_branch mylib_remote/master \end_layout \begin_layout LyX-Code git checkout master \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Допустим, мы хотим поместить проект mylib в подкаталог с тем же именем: \end_layout \begin_layout LyX-Code git read-tree --prefix=mylib/ -u mylib_branch \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard В отличие от субмодулей данные поддерева хранятся физически в репозитории. Субмодули же, по своей сути, лишь ссылаются на данные в другом репозитории. \end_layout \begin_layout Standard Обновление поддерева происходит довольно легко: \end_layout \begin_layout LyX-Code git checkout mylib_branch # переключиться на ветку поддерева \end_layout \begin_layout LyX-Code git pull # принять удалённые изменения \end_layout \begin_layout LyX-Code git checkout master # переключиться на версию основного проекта \end_layout \begin_layout LyX-Code git merge --squash -s subtree --no-commit mylib_branch # смержить в mylib/, не создавая коммита \end_layout \begin_layout LyX-Code git commit # зафиксировать изменения \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Узнать о наличии разницы между подкаталогом mylib/ и кодом в mylib_branch можно при помощи \begin_inset Quotes eld \end_inset git diff-tree \begin_inset Quotes erd \end_inset : \end_layout \begin_layout LyX-Code git diff-tree -p mylib_branch # сравнить с локальной веткой \end_layout \begin_layout LyX-Code git diff-tree -p mylib_remote/master # сравнить с удалённой веткой \end_layout \begin_layout Section Администрирование \end_layout \begin_layout Subsection Свободное место на диске \end_layout \begin_layout Standard Для удаления временных файлов и сжатия истории можно использовать следующие команды: \end_layout \begin_layout LyX-Code git clean -fd # удалить неотслеживаемые файлы в репозитории \end_layout \begin_layout LyX-Code git prune # удалить все недостижимые объекты/коммиты из базы данных \end_layout \begin_layout LyX-Code git prune-packed # удалить также уже упакованные недостижимые объекты \end_layout \begin_layout LyX-Code git gc --aggressive --prune=all # удалить все бесполезные объекты и оптимизирова ть локальный репозиторий \end_layout \begin_layout Subsection shallow-репозиторий \end_layout \begin_layout Standard Это такой репозиторий, который хранит лишь часть истории, что позволяет сэкономить место на диске и входящий трафик при его создании, но запрещает клонирование и другие операции с ним. \end_layout \begin_layout Standard Для создания shallow-репозитория можно выполнить клонирование обычного с опцией --depth, например: \end_layout \begin_layout LyX-Code git clone --depth=1 git://github.com/gentoo-mirror/gentoo.git /var/portage/portage \end_layout \begin_layout Standard Для создания shallow-репозитория \begin_inset Quotes eld \end_inset на месте \begin_inset Quotes erd \end_inset ( \begin_inset Quotes eld \end_inset inplace \begin_inset Quotes erd \end_inset ) без клонирования и передачи данных по сети подходит следующий вариант (взято со \begin_inset CommandInset href LatexCommand href name "stackoverflow" target "http://stackoverflow.com/a/7937916/5218714" \end_inset ): \end_layout \begin_layout LyX-Code git show-ref -s HEAD > .git/shallow \end_layout \begin_layout LyX-Code git reflog expire --expire=0 \end_layout \begin_layout LyX-Code git prune \end_layout \begin_layout LyX-Code git prune-packed \end_layout \begin_layout Standard Последняя последовательность команд совместно с git gc --aggressive --prune=all может быть использована для периодической чистки shallow-репозитория от старой истории. \end_layout \begin_layout Subsection Создание архива \end_layout \begin_layout Standard Иногда для передачи снимка исходного кода третьим лицам требуется создать архив, не включая Git-специфичных данных и временных файлов, созданных в процессе сборки проекта. Для этой цели существует команда \begin_inset Quotes eld \end_inset git archive \begin_inset Quotes erd \end_inset . \end_layout \begin_layout LyX-Code git archive -o myproject-1.0.0.zip v1.0.0 > # создать Zip-архив 1-ой стабильной версии проекта \end_layout \begin_layout LyX-Code git archive --format=tgz --prefix=myproject-master/ master > myproject-master.tgz # архивировать \end_layout \begin_layout LyX-Code # ветку master \end_layout \begin_layout LyX-Code git archive -o myproject-doc.zip HEAD:Documentation/ # создать архив с документац ией \end_layout \begin_layout Subsection Проверка целостности репозитория \end_layout \begin_layout Standard Git являет по своей сути файловую систему, расположенную внутри другой файловой системы (на диске). Иногда в работе компьютера случаются сбои и файловая система компьютера может быть повреждена. Также существует ненулевая вероятность повреждения системы объектов репозитория в результате типовой работы (напр., использование нестабильной версии Git), хотя она крайне мала. \end_layout \begin_layout Standard Для проверки целостности объектов бд и истории репозитория имеется команда \begin_inset Quotes eld \end_inset git fsck \begin_inset Quotes erd \end_inset . Примеры использования: \end_layout \begin_layout LyX-Code git fsck # выполнить проверку \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Иногда случается, что объект добавлен в индекс \begin_inset Quotes eld \end_inset git add \begin_inset Quotes erd \end_inset , а впоследствии удалён по ошибке, например командой \begin_inset Quotes eld \end_inset git reset --hard \begin_inset Quotes erd \end_inset . В Git предусмотрена возможность восстановления данных и на этот случай, пример: \end_layout \begin_layout LyX-Code git add main.c # добавили изменения в индекс \end_layout \begin_layout LyX-Code git reset --hard # случайно откатились к вершине истории \end_layout \begin_layout LyX-Code git fsck --lost-found # с большой долей вероятности изменённый main.c находится \end_layout \begin_layout LyX-Code # в .git/lost-found/other, только в место имени хеш ревизии \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Бывает также, что пользователь отключил \begin_inset Quotes eld \end_inset reflog \begin_inset Quotes erd \end_inset в настройках Git по ошибке или по неопределённым личным обстоятельствам. В таких случаях может буквально спасти опция \begin_inset Quotes eld \end_inset --dangling \begin_inset Quotes erd \end_inset у \begin_inset Quotes eld \end_inset git fsck \begin_inset Quotes erd \end_inset : \end_layout \begin_layout LyX-Code $ git fsck --dangling \end_layout \begin_layout LyX-Code Checking object directories: 100% (256/256), done. \end_layout \begin_layout LyX-Code Checking objects: 100% (84/84), done. \end_layout \begin_layout LyX-Code dangling blob cd0120b458d5ab07efed5bb690b0eec8c1801b55 \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard В конце выхлопа команды указаны хеши некогда существующих объектов, которые никогда не использовались (не добавлялись в репозиторий). Для восстановления требуемых объектов используется та же команда Git \begin_inset Quotes eld \end_inset checkout \begin_inset Quotes erd \end_inset . \end_layout \begin_layout Section Удачная модель ветвления \end_layout \begin_layout Standard Материал взят с \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://habrahabr.ru/post/106912/ \end_layout \end_inset \end_layout \begin_layout Standard В этой статье я представляю модель разработки, которую использую для всех моих проектов (как рабочих, так и частных) уже в течение года, и которая показала себя с хорошей стороны. Я давно собирался написать о ней, но до сих пор не находил свободного времени. Не буду рассказывать обо всех деталях проекта, коснусь лишь стратегии ветвления и управления релизами. \end_layout \begin_layout Standard \begin_inset Float figure placement H wide false sideways false status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/782a1be3.png scale 80 \end_inset \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:Удачная-модель-ветвления" \end_inset Удачная модель ветвления \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard В качестве инструмента управления версиями всего исходного кода она использует Git. \end_layout \begin_layout Subsection Почему Git? \end_layout \begin_layout Standard За полноценным обсуждением всех достоинств и недостатков Git в сравнении с централизованными системами контроля версий \begin_inset CommandInset href LatexCommand href name "обращайтесь" target "http://whygitisbetterthanx.com/" \end_inset \begin_inset CommandInset href LatexCommand href name "к всемирной" target "http://mercurial.selenic.com/wiki/GitConcepts#Command_equivalence_table" \end_inset \begin_inset CommandInset href LatexCommand href name "сети" target "http://git.or.cz/gitwiki/GitSvnComparsion" \end_inset . Там Вы найдёте достаточное количество споров на эту тему. Лично же я, как разработчик, на данный момент предпочитаю Git всем остальным инструментам. Git реально смог изменить отношение разработчиков к процессам слияния и ветвления. В классическом мире CVS/Subversion, из которого я пришёл, ветвление и слияние обычно считаются опасными («опасайтесь конфликтов слияния, они больно кусаются! »), и потому проводятся как можно реже. \end_layout \begin_layout Standard Но с Git эти действия становятся исключительно простыми и дешёвыми, и потому на деле они становятся центральными элементами обычного \shape slanted ежедневного \shape default рабочего процесса. Просто сравните: в \begin_inset CommandInset href LatexCommand href name "книгах" target "http://svnbook.red-bean.com/" \end_inset по CVS/Subversion ветвление и слияние обычно рассматриваются в последних главах (для продвинутых пользователей), в то время как в \begin_inset CommandInset href LatexCommand href name "любой" target "http://book.git-scm.com/" \end_inset \begin_inset CommandInset href LatexCommand href name "книге" target "http://pragprog.com/titles/tsgit/pragmatic-version-control-using-git" \end_inset \begin_inset CommandInset href LatexCommand href name "про Git" target "http://github.com/progit/progit" \end_inset они бывают упомянуты уже к третьей главе (основы). \end_layout \begin_layout Standard Благодаря своей простоте и предсказуемости, ветвление и слияние больше не являются действиями, которых стоит опасаться. Теперь инструменты управления версиями способны помочь в ветвлении и слиянии больше, чем какие-либо другие. \end_layout \begin_layout Standard Но хватит говорить об инструментах, давайте перейдём к модели разработки. Модель, которую я хочу представить, — это, по сути, просто набор процедур, которые исполняет каждый член команды, чтобы все вместе могли достичь высокой управляемости процесса разработки. \end_layout \begin_layout Subsection Децентрализованный, но централизованный \end_layout \begin_layout Standard Предлагаемая модель ветвления опирается на конфигурацию проекта, содержащую один центральный «истинный» репозиторий. Замечу, что этот репозиторий только \shape slanted считается \shape default центральным (так как Git является DVCS, у него нет такой вещи, как главный репозиторий, на техническом уровне). Мы будем называть этот репозиторий термином origin, т.к. это имя и так знакомо всем пользователям Git. \end_layout \begin_layout Standard \begin_inset Float figure placement H wide false sideways false status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/1d1e8f1a.png scale 50 \end_inset \begin_inset Caption Standard \begin_layout Plain Layout Децентрализованный, но централизованный \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard Каждый разработчик забирает и публикует изменения (pull & push) в origin. Но, помимо централизованных отношений push-pull, каждый разработчик также может забирать изменения от остальных коллег внутри своей микро-команды. Например, этот способ может быть удобен в ситуации, когда двое или более разработчиков работают вместе над большой новой фичей, но не могут издать незавершённую работу в origin раньше времени. На картинке выше изображены подгруппы Алисы и Боба, Алисы и Дэвида, Клэр и Дэвида. \end_layout \begin_layout Standard Технически это реализуется несложно: Алиса создаёт удалённую ветку Git под названием bob, которая указывает на репозиторий Боба, а Боб делает то же самое с её репозиторием. \end_layout \begin_layout Subsection Главные ветви \end_layout \begin_layout Standard \begin_inset Wrap figure lines 0 placement R overhang 0in width "30col%" status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/00eb029a.png scale 50 \end_inset \begin_inset Caption Standard \begin_layout Plain Layout Главные ветви \end_layout \end_inset \end_layout \end_inset Ядро модели разработки не отличается от большинства существующих моделей. Центральный репозиторий содержит две главные ветки, существующие всё время. \end_layout \begin_layout Itemize master \end_layout \begin_layout Itemize develop \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Ветвь master создаётся при инициализации репозитория, что должно быть знакомо каждому пользователю Git. Параллельно ей также мы создаём ветку для разработки под названием develop. \end_layout \begin_layout Standard Мы считаем ветку origin/master главной. То есть, исходный код в ней должен находиться в состоянии \shape slanted production-ready \shape default в любой произвольный момент времени. \end_layout \begin_layout Standard Ветвь origin/develop мы считаем главной ветвью для разработки. Хранящийся в ней код в любой момент времени должен содержать самые последние изданные изменения, необходимые для следующего релиза. Эту ветку также можно назвать «интеграционной». Она служит источником для сборки автоматических ночных билдов. \end_layout \begin_layout Standard Когда исходный код в ветви разработки (develop) достигает стабильного состояния и готов к релизу, все изменения должны быть определённым способом влиты в главную ветвь (master) и помечены тегом с номером релиза. Ниже мы рассмотрим этот процесс в деталях. \end_layout \begin_layout Standard Следовательно, каждый раз, когда изменения вливаются в главную ветвь (master), мы \shape slanted по определению \shape default получаем новый релиз. Мы стараемся относиться к этому правилу очень строго, так что, в принципе, мы могли бы использовать хуки Git, чтобы автоматически собирать наши продукты и выкладывать их на рабочие сервера при каждом коммите в главную ветвь (master). \end_layout \begin_layout Subsection Вспомогательные ветви \end_layout \begin_layout Standard Помимо главных ветвей master и develop, наша модель разработки содержит некоторое количество типов вспомогательных ветвей, которые используются для распараллеливания разработки между членами команды, для упрощения внедрения нового функционала (features), для подготовки релизов и для быстрого исправлени я проблем в производственной версии приложения. В отличие от главный ветвей, эти ветви всегда имеют ограниченный срок жизни. Каждая из них в конечном итоге рано или поздно удаляется. \end_layout \begin_layout Standard Мы используем следующие типы ветвей: \end_layout \begin_layout Itemize Ветви функциональностей (Feature branches) \end_layout \begin_layout Itemize Ветви релизов (Release branches) \end_layout \begin_layout Itemize Ветви исправлений (Hotfix branches) \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard У каждого типа ветвей есть своё специфическое назначение и строгий набор правил, от каких ветвей они могут порождаться, и в какие должны вливаться. Сейчас мы рассмотрим их по очереди. \end_layout \begin_layout Standard Конечно же, с технической точки зрения, у этих ветвей нет ничего «специфического ». Разбиение ветвей на категории существует только с точки зрения того, как они используются. А во всём остальном это старые добрые ветви Git. \end_layout \begin_layout Subsubsection Ветви функциональностей (feature branches) \end_layout \begin_layout Standard \begin_inset Wrap figure lines 0 placement R overhang 0in width "30col%" status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/968a9100.png scale 50 \end_inset \begin_inset Caption Standard \begin_layout Plain Layout Ветви функциональностей (feature branches) \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard Могут порождаться от: develop \end_layout \begin_layout Standard Должны вливаться в: develop \end_layout \begin_layout Standard Соглашение о наименовании: всё, за исключением master, develop, release-* или hotfix-* \end_layout \begin_layout Standard Ветви функциональностей (feature branches), также называемые иногда тематическим и ветвями (topic branches), используются для разработки новых функций, которые должны появиться в текущем или будущем релизах. При начале работы над функциональностью (фичей) может быть ещё неизвестно, в какой именно релиз она будет добавлена. Смысл существования ветви функциональности (feature branch) состоит в том, что она живёт так долго, сколько продолжается разработка данной функциональност и (фичи). Когда работа в ветви завершена, последняя вливается обратно в главную ветвь разработки (что означает, что функциональность будет добавлена в грядущий релиз) или же удаляется (в случае неудачного эксперимента). \end_layout \begin_layout Standard Ветви функциональностей (feature branches) обычно существуют в репозиториях разработчиков, но не в главном репозитории (origin). \end_layout \begin_layout Paragraph Создание ветви функциональности (feature branch) \end_layout \begin_layout Standard При начале работы над новой функциональностью делается ответвление от ветви разработки (develop). \end_layout \begin_layout LyX-Code $ git checkout -b myfeature develop \end_layout \begin_layout LyX-Code Switched to a new branch "myfeature" \end_layout \begin_layout Paragraph Добавление завершённой функциональности в develop \end_layout \begin_layout Standard Завершённая функциональность (фича) вливается обратно в ветвь разработки (develop) и попадает в следующий релиз. \end_layout \begin_layout LyX-Code $ git checkout develop \end_layout \begin_layout LyX-Code Switched to branch 'develop' \end_layout \begin_layout LyX-Code $ git merge --no-ff myfeature \end_layout \begin_layout LyX-Code Updating ea1b82a..05e9557 \end_layout \begin_layout LyX-Code (Отчёт об изменениях) \end_layout \begin_layout LyX-Code $ git branch -d myfeature \end_layout \begin_layout LyX-Code Deleted branch myfeature (was 05e9557). \end_layout \begin_layout LyX-Code $ git push origin develop \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Флаг --no-ff вынуждает Git всегда создавать новый объект коммита при слиянии, даже если слияние может быть осуществлено алгоритмом fast-forward. Это позволяет не терять информацию о том, что ветка существовала, и группирует вместе все внесённые изменения. Сравните: \end_layout \begin_layout Standard \begin_inset Float figure placement H wide false sideways false status collapsed \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/572137b0.png scale 50 \end_inset \begin_inset Caption Standard \begin_layout Plain Layout no-fast-forward VS fast-forward \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard Во втором случае невозможно увидеть в истории изменений, какие именно объекты коммитов совместно образуют функциональность, — для этого придётся вручную читать все сообщения в коммитах. Отменить функциональность целиком (т.е., группу коммитов) в таком случае невозможно без головной боли, а с флагом --no-ff это делается элементарно. \end_layout \begin_layout Standard Конечно, такой подход создаёт некоторое дополнительное количество (пустых) объектов коммитов, но получаемая выгода более чем оправдывает подобную цену. \end_layout \begin_layout Standard К сожалению, я ещё не нашёл, как можно настроить Git так, чтобы --no-ff было поведением по-умолчанию при слияниях. Но этот способ должен быть реализован. \end_layout \begin_layout Subsubsection Ветви релизов (release branches) \end_layout \begin_layout Standard Могут порождаться от: develop \end_layout \begin_layout Standard Должны вливаться в: develop и master \end_layout \begin_layout Standard Соглашение о наименовании: release-* \end_layout \begin_layout Standard Ветви релизов (release branches) используются для подготовки к выпуску новых версий продукта. Они позволяют расставить финальные точки над i перед выпуском новой версии. Кроме того, в них можно добавлять минорные исправления, а также подготавливать метаданные для очередного релиза (номер версии, дата сборки и т.д.). Когда вся эта работа выносится в ветвь релизов, главная ветвь разработки (develop) очищается для добавления последующих фич (которые войдут в следующий большой релиз). \end_layout \begin_layout Standard Новую ветку релиза (release branch) надо порождать в тот момент, когда состояние ветви разработки полностью или почти полностью соответствует требованиям, соответствующим новому релизу. По крайней мере, вся необходимая функциональность, предназначенная к этому релизу, уже влита в ветвь разработки (develop). Функциональность, предназначенная к следующим релизам, может быть и не влита. Даже лучше, если ветки для этих функциональностей подождут, пока текущая ветвь релиза не отпочкуется от ветви разработки (develop). \end_layout \begin_layout Standard Очередной релиз получает свой номер версии только в тот момент, когда для него создаётся новая ветвь, но ни в коем случае не раньше. Вплоть до этого момента ветвь разработки содержит изменения для «нового релиза», но пока ветка релиза не отделилась, точно неизвестно, будет ли этот релиз иметь версию 0.3, или 1.0, или какую-то другую. Решение принимается при создании новой ветви релиза и зависит от принятых на проекте правил нумерации версий проекта. \end_layout \begin_layout Paragraph Создание ветви релиза (release branch) \end_layout \begin_layout Standard Ветвь релиза создаётся из ветви разработки (develop). Пускай, например, текущий изданный релиз имеет версию 1.1.5, а на подходе новый большой релиз, полный изменений. Ветвь разработки (develop) готова к «следующему релизу», и мы решаем, что этот релиз будет иметь версию 1.2 (а не 1.1.6 или 2.0). В таком случае мы создаём новую ветвь и даём ей имя, соответствующее новой версии проекта: \end_layout \begin_layout LyX-Code $ git checkout -b release-1.2 develop \end_layout \begin_layout LyX-Code Switched to a new branch "release-1.2" \end_layout \begin_layout LyX-Code $ ./bump-version.sh 1.2 \end_layout \begin_layout LyX-Code Files modified successfully, version bumped to 1.2. \end_layout \begin_layout LyX-Code $ git commit -a -m "Bumped version number to 1.2" \end_layout \begin_layout LyX-Code [release-1.2 74d9424] Bumped version number to 1.2 \end_layout \begin_layout LyX-Code 1 files changed, 1 insertions(+), 1 deletions(-) \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Мы создали новую ветку, переключились в неё, а затем выставили номер версии (bump version number). В нашем примере bump-version.sh — это вымышленный скрипт, который изменяет некоторые файлы в рабочей копии, записывая в них новую версию. (Разумеется, эти изменения можно внести и вручную; я просто обращаю Ваше внимание на то, что \shape slanted некоторые \shape default файлы изменяются.) Затем мы делаем коммит с указанием новой версии проекта. \end_layout \begin_layout Standard Эта новая ветвь может существовать ещё некоторое время, до тех пор, пока новый релиз окончательно не будет готов к выпуску. В течение этого времени к этой ветви (а не к develop) могут быть добавлены исправления найденных багов. Но добавление крупных новых изменений в эту ветвь строго запрещено. Они всегда должны вливаться в ветвь разработки (develop) и ждать следующего большого релиза. \end_layout \begin_layout Paragraph Закрытие ветви релиза \end_layout \begin_layout Standard Когда мы решаем, что ветвь релиза (release branch) окончательно готова для выпуска, нужно проделать несколько действий. В первую очередь ветвь релиза вливается в главную ветвь (напоминаю, каждый коммит в master — это \shape slanted по определению \shape default новый релиз). Далее, этот коммит в master должен быть помечен тегом, чтобы в дальнейшем можно было легко обратиться к любой существовавшей версии продукта. И наконец, изменения, сделанные в ветви релиза (release branch), должны быть добавлены обратно в разработку (ветвь develop), чтобы будущие релизы также содержали внесённые исправления багов. \end_layout \begin_layout Standard Первые два шага в Git: \end_layout \begin_layout LyX-Code $ git checkout master \end_layout \begin_layout LyX-Code Switched to branch 'master' \end_layout \begin_layout LyX-Code $ git merge --no-ff release-1.2 \end_layout \begin_layout LyX-Code Merge made by recursive. \end_layout \begin_layout LyX-Code (Отчёт об изменениях) \end_layout \begin_layout LyX-Code $ git tag -a 1.2 \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Теперь релиз издан и помечен тегом. \end_layout \begin_layout Standard \series bold Замечание: \series default при желании, Вы также можете использовать флаги -s или -u <ключ>, чтобы криптографически подписать тег. \end_layout \begin_layout Standard Чтобы сохранить изменения и в последующих релизах, мы должны влить эти изменения обратно в разработку. Делаем это так: \end_layout \begin_layout LyX-Code $ git checkout develop \end_layout \begin_layout LyX-Code Switched to branch 'develop' \end_layout \begin_layout LyX-Code $ git merge --no-ff release-1.2 \end_layout \begin_layout LyX-Code Merge made by recursive. \end_layout \begin_layout LyX-Code (Отчёт об изменениях) \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Этот шаг, в принципе, может привести к конфликту слияния (нередко бывает, что к причиной конфликта является изменение номера версии проекта). Если это произошло, исправьте их и издайте коммит. \end_layout \begin_layout Standard Теперь мы окончательно разделались с веткой релиза. Можно её удалять, потому что она нам больше не понадобится: \end_layout \begin_layout LyX-Code $ git branch -d release-1.2 \end_layout \begin_layout LyX-Code Deleted branch release-1.2 (was ff452fe). \end_layout \begin_layout Subsubsection Ветви исправлений (hotfix branches) \end_layout \begin_layout Standard \begin_inset Wrap figure lines 0 placement R overhang 0in width "44col%" status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename pic/3f8cbad4.png scale 50 \end_inset \begin_inset Caption Standard \begin_layout Plain Layout Ветви исправлений (hotfix branches) \end_layout \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Могут порождаться от: master \end_layout \begin_layout Standard Должны вливаться в: develop и master \end_layout \begin_layout Standard Соглашение о наименовании: hotfix-* \end_layout \begin_layout Standard Ветви для исправлений (hotfix branches) весьма похожи на ветви релизов (release branches), так как они тоже используются для подготовки новых выпусков продукта, разве лишь незапланированных. Они порождаются необходимостью немедленно исправить нежелательное поведение производственной версии продукта. Когда в производственной версии находится баг, требующий немедленного исправлен ия, из соответствующего данной версии тега главной ветви (master) порождается новая ветвь для работы над исправлением. \end_layout \begin_layout Standard Смысл её существования состоит в том, что работа команды над ветвью разработки (develop) может спокойно продолжаться, в то время как кто-то один готовит быстрое исправление производственной версии. \end_layout \begin_layout Paragraph Создание ветви исправлений (hotfix branch) \end_layout \begin_layout Standard Ветви исправлений (hotfix branches) создаются из главной (master) ветви. Пускай, например, текущий производственный релиз имеет версию 1.2, и в нём (внезапно!) обнаруживается серьёзный баг. А изменения в ветви разработки (develop) ещё недостаточно стабильны, чтобы их издавать в новый релиз. Но мы можем создать новую ветвь исправлений и начать работать над решением проблемы: \end_layout \begin_layout LyX-Code $ git checkout -b hotfix-1.2.1 master \end_layout \begin_layout LyX-Code Switched to a new branch "hotfix-1.2.1" \end_layout \begin_layout LyX-Code $ ./bump-version.sh 1.2.1 \end_layout \begin_layout LyX-Code Files modified successfully, version bumped to 1.2.1. \end_layout \begin_layout LyX-Code $ git commit -a -m "Bumped version number to 1.2.1" \end_layout \begin_layout LyX-Code [hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1 \end_layout \begin_layout LyX-Code 1 files changed, 1 insertions(+), 1 deletions(-) \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Не забывайте обновлять номер версии после создания ветви! \end_layout \begin_layout Standard Теперь можно исправлять баг, а изменения издавать хоть одним коммитом, хоть несколькими. \end_layout \begin_layout LyX-Code $ git commit -m "Fixed severe production problem" \end_layout \begin_layout LyX-Code [hotfix-1.2.1 abbe5d6] Fixed severe production problem \end_layout \begin_layout LyX-Code 5 files changed, 32 insertions(+), 17 deletions(-) \end_layout \begin_layout Paragraph Закрытие ветви исправлений \end_layout \begin_layout Standard Когда баг исправлен, изменения надо влить обратно в главную ветвь (master), а также в ветвь разработки (develop), чтобы гарантировать, что это исправление окажется и в следующем релизе. Это очень похоже на то, как закрывается ветвь релиза (release branch). \end_layout \begin_layout Standard Прежде всего надо обновить главную ветвь (master) и пометить новую версию тегом. \end_layout \begin_layout LyX-Code $ git checkout master \end_layout \begin_layout LyX-Code Switched to branch 'master' \end_layout \begin_layout LyX-Code $ git merge --no-ff hotfix-1.2.1 \end_layout \begin_layout LyX-Code Merge made by recursive. \end_layout \begin_layout LyX-Code (Отчёт об изменениях) \end_layout \begin_layout LyX-Code $ git tag -a 1.2.1 \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard \series bold Замечание: \series default при желании, Вы также можете использовать флаги -s или -u <ключ>, чтобы криптографически подписать тэг. \end_layout \begin_layout Standard Следующим шагом переносим исправление в ветвь разработки (develop). \end_layout \begin_layout LyX-Code $ git checkout develop \end_layout \begin_layout LyX-Code Switched to branch 'develop' \end_layout \begin_layout LyX-Code $ git merge --no-ff hotfix-1.2.1 \end_layout \begin_layout LyX-Code Merge made by recursive. \end_layout \begin_layout LyX-Code (Отчёт об изменениях) \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard У этого правила есть одно исключение: \series bold если в данный момент существует ветвь релиза (release branch), то ветвь исправления (hotfix branch) должна вливаться в неё, а не в ветвь разработки (develop \series default ). В этом случае исправления войдут в ветвь разработки вместе со всей ветвью релиза, когда та будет закрыта. (Хотя, если работа в develop требует немедленного исправления бага и не может ждать, пока будет завершено издание текущего релиза, Вы всё же можете влить исправления (bugfix) в ветвь разработки (develop), и это будет вполне безопасно). \end_layout \begin_layout Standard И наконец, удаляем временную ветвь: \end_layout \begin_layout LyX-Code $ git branch -d hotfix-1.2.1 \end_layout \begin_layout LyX-Code Deleted branch hotfix-1.2.1 (was abbe5d6). \end_layout \begin_layout Subsection Заключение \end_layout \begin_layout Standard Хотя в этой модели ветвления совершенно нет ничего принципиально нового, «большая картинка», с которой начинается эта статья, зарекомендовала себя в наших проектах с самой лучшей стороны. Она формирует элегантную мысленную модель, которую легко полностью охватить одним взглядом, и которая позволяет сформировать у команды совместное понимание процессов ветвления и слияния, действующих на проекте. \end_layout \begin_layout Standard Высококачественная PDF-версия этой картинки свободна для скачивания \begin_inset CommandInset href LatexCommand href name "здесь" target "http://github.com/downloads/nvie/gitflow/Git-branching-model.pdf" \end_inset . Распечатайте её и повесьте у себя на стену, чтобы к ней можно было обратиться в любой момент. \end_layout \begin_layout Standard \series bold \shape slanted Прим. переводчика: \series default статья не новая, ссылка на оригинал \begin_inset CommandInset href LatexCommand href name "уже появлялась на хабре" target "http://habrahabr.ru/blogs/development_tools/104993/" \end_inset . Этот перевод — для тех, кому английский ещё даётся не так легко (а также для моих коллег, среди которых я занимаюсь пропагандой, хехе). Для автоматизации описанных в статье процедур автор создал проект gitflow, \begin_inset CommandInset href LatexCommand href name "который можно найти на github" target "http://github.com/nvie/gitflow" \end_inset . \end_layout \begin_layout Section Рекомендуемая литература \end_layout \begin_layout Enumerate Документация на официальном сайте Git (англ.) \begin_inset Flex URL status open \begin_layout Plain Layout http://git-scm.com/documentation \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset \end_layout \begin_layout Section \start_of_appendix Пример Git-конфигурации ~/.gitconfig \end_layout \begin_layout Standard Приведём пример типичного файла конфигурации. Все опции могут быть вписаны вручную, но могут быть заданы через команду git config, например: \end_layout \begin_layout LyX-Code git config --global user.email "you@example.com" \end_layout \begin_layout LyX-Code git config --global user.name "Your Name" \end_layout \begin_layout Standard \begin_inset space ~ \end_inset \end_layout \begin_layout Standard Опция --global указывает, что настройки должны быть применены глобально, а не только к текущему репозиторию. \end_layout \begin_layout Standard Пример файла конфигурации, расположенного в домашней директории пользователя ~/.gitconfig: \end_layout \begin_layout LyX-Code [user] \end_layout \begin_deeper \begin_layout LyX-Code email = vasya.pupkin@gmail.com \end_layout \begin_layout LyX-Code name = Vasya P \end_layout \end_deeper \begin_layout LyX-Code [color] \end_layout \begin_deeper \begin_layout LyX-Code ui = auto \end_layout \begin_layout LyX-Code branch = auto \end_layout \begin_layout LyX-Code diff = auto \end_layout \begin_layout LyX-Code status = auto \end_layout \end_deeper \begin_layout LyX-Code [color "branch"] \end_layout \begin_deeper \begin_layout LyX-Code current = yellow reverse \end_layout \begin_layout LyX-Code local = yellow \end_layout \begin_layout LyX-Code remote = green \end_layout \end_deeper \begin_layout LyX-Code [color "diff"] \end_layout \begin_deeper \begin_layout LyX-Code meta = yellow bold \end_layout \begin_layout LyX-Code frag = magenta bold \end_layout \begin_layout LyX-Code old = red bold \end_layout \begin_layout LyX-Code new = green bold \end_layout \end_deeper \begin_layout LyX-Code [color "status"] \end_layout \begin_deeper \begin_layout LyX-Code added = yellow \end_layout \begin_layout LyX-Code changed = green \end_layout \begin_layout LyX-Code untracked = cyan \end_layout \end_deeper \begin_layout LyX-Code [alias] \end_layout \begin_deeper \begin_layout LyX-Code unstage = reset HEAD -- \end_layout \begin_layout LyX-Code st = status \end_layout \begin_layout LyX-Code s = status -uno \end_layout \begin_layout LyX-Code ci = commit \end_layout \begin_layout LyX-Code di = diff -b \end_layout \begin_layout LyX-Code co = checkout \end_layout \begin_layout LyX-Code up = checkout \end_layout \begin_layout LyX-Code update = checkout \end_layout \begin_layout LyX-Code l = log \end_layout \begin_layout LyX-Code hgrevert = checkout \end_layout \begin_layout LyX-Code strip = reset --hard \end_layout \begin_layout LyX-Code branches = branch -a \end_layout \begin_layout LyX-Code pull = fetch \end_layout \end_deeper \begin_layout LyX-Code [instaweb] \end_layout \begin_deeper \begin_layout LyX-Code local = true \end_layout \begin_layout LyX-Code httpd = lighttpd -f \end_layout \begin_layout LyX-Code port = 4321 \end_layout \begin_layout LyX-Code browser = firefox \end_layout \end_deeper \begin_layout LyX-Code [merge] \end_layout \begin_deeper \begin_layout LyX-Code tool = vimdiff \end_layout \end_deeper \begin_layout LyX-Code [core] \end_layout \begin_deeper \begin_layout LyX-Code quotepath = false \end_layout \end_deeper \begin_layout LyX-Code [push] \end_layout \begin_deeper \begin_layout LyX-Code default = matching \end_layout \end_deeper \begin_layout Standard \end_layout \end_body \end_document