4369 lines
117 KiB
Plaintext
4369 lines
117 KiB
Plaintext
#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 "tex,lyx,latex,texreport,texparser"
|
||
\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.2}
|
||
\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 # удалить неотслеживаемые файлы в репозитории
|
||
\end_layout
|
||
|
||
\begin_layout LyX-Code
|
||
git prune # удалить все недостижимые объекты/коммиты из базы данных
|
||
\end_layout
|
||
|
||
\begin_layout LyX-Code
|
||
git gc --aggressive --prune # удалить все бесполезные объекты и оптимизировать
|
||
локальный репозиторий
|
||
\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
|