Short introduction in Git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4442 lines
119 KiB

#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 <file>..." to update what will be committed)
\end_layout
\begin_layout LyX-Code
# (use "git checkout -- <file>..." 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 <file>..." 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 <commit-to-split>^ 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