Cодержание:
1. Введение;
2. Установка Git;
3. Структура директории .git/;
4. Самые распространенные команды в Git;
5. Работа с историей;
6. Ветвление в Git;
7. Примеры ведения истории проекта;
8. Заключение.
Введение
Привет, Хабр! Меня зовут Егор, я занимаюсь разработкой мобильных приложений на Flutter. Это моя первая работа в сфере IT, и как подобает начинающим, я столкнулся с проблемой изучения систем контроля версий. В данной публикации я хочу поделиться приобретенными знаниями и подробно рассмотреть одну из таких систем, а именно Git. Итак, начнем...
“Whoah, I’ve just read this quick tuto about git and oh my god it is cool. I feel now super comfortable using it, and I’m not afraid at all to break something.” — said no one ever.
Не так страшен чёрт, как его малюют. Хотя, как мне кажется, это не касается Git. Так или иначе многие сталкиваются с необходимостью обучиться грамотной работе с этим инструментом. Несмотря на обилие информации и туториалов, это задача является не самой тривиальной. Исходя из своего опыта, могу сделать вывод: необходимо изучить самые разные ресурсы, прежде чем наступит понимание.
Полагаю, все дело в том, что изучение Git - комплексная тема, и охватить ее в одной статье, чтобы быстренько освоить азы и тут же применить знания на практике, несколько сложно.
Тем не менее, я бы хотел дополнить просторы интернета очередной статьей о Git. Постараюсь изложить все таким образом, как если бы у меня была возможность объяснить все самому себе из прошлого. Как следует из названия, я расскажу о Git очень коротко; а точнее о возможностях, которые он нам предоставляет.
Перед тем, как говорить про какую-либо конкретную систему контроля версий, необходимо понимать, что это такое и какими они бывают.
Система контроля версий - это программное обеспечение, помогающее разработчикам управлять состоянием исходного кода на протяжение всей разработки. Другими словами, это система, которая записывает ваши изменения в файл и позже позволяет откатиться к более ранней версии проекта.
Системы контроля версий можно разделить на две группы:
1. Централизованные системы контроля версий;
2. Распределенные системы контроля версий.
Централизованная система контроля версий - это система, при которой репозиторий проекта хранится на сервере и вносить изменения вы можете непосредственно только в этот репозиторий при помощи специальных клиентских приложений. Среди таких систем можно выделить: ClearCase, TFVC, SVN.
Распределенная система контроля версий - это система, при которой копия репозитория может храниться на машине у каждого разработчика, что значительно снижает риск потерять результат работы над проектом. Примером таких систем могут быть: Git, Mercurial, Bazaar.
Git является распределенной системой контроля версий, разработанной Линусом Торвальдсом для управления разработкой ядра Linux. На данный момент Git завоевал огромную популярность в IT сообществе и, как следствие, его часто можно встретить в стеке технологий различных компаний.
Далее я расскажу про структуру Git репозитория и как его завести. Познакомлю вас с основными, наиболее популярными командами в Git. Также вы узнаете о том, как инспектировать историю своего проекта и как откатить его до определенной точки. И, в заключение, я слегка затрону тему ветвления.
Установка Git
Прежде чем мы продолжим, вам необходимо установить Git.
Ниже я представлю краткую инструкцию к установке, но вы также можете пройти по этой ссылке на официальный источник и разобраться в этом самостоятельно.
Mac OS.
# Если вы используете менеджер пакетов HomeBrew,
# Вы можете выполнить следующую команду:
brew install git
# В противном случае вам достаточно ввести:
git --version
# После чего вам будет предложено установить Git
Windows. Перейдите по ссылке и скачайте Git соответствующий архитектуре вашего процессора (32 или 64-bit) и установите его.
Linux. Перейдите по ссылке для более подробной инструкции.
# Установка на Linux зависит от дистрибутива который вы используете
# Debian/Ubuntu
apt-get install git
# Fedora
yum install git
Структура директории .git/
Как правило, ваша работа с Git будет начинаться с того, что вам потребуется проинициализировать Git директорию в своем проекте. Это делается с помощью команды:
git init
Ее необходимо ввести в корне вашего проекта. Это создаст в текущем каталоге новый подкаталог .git со следующим содержанием:
В данной директории будет содержаться вся конфигурация Git и история проекта. При желании можно править эти файлы вручную, внося необходимые изменения в историю проекта.
1. config
В данном файле содержатся настройки Git репозитория. Например, здесь можно хранить email и имя пользователя.
2. description
Данный файл предназначен для GitWeb и содержит в себе информацию о проекте (название проекта и его описание). GitWeb - это веб интерфейс, написанный для просмотра Git репозитория используя веб-браузер. Если вы не пользуетесь GitWeb, то это не столь важно.
3. hooks
В этом каталоге Git предоставляет набор скриптов, которые могут автоматически запускаться во время выполнения git команд. В некоторых случаях это значительно упрощает разработку. Например, вы можете написать скрипт, который будет редактировать сообщение коммита согласно вашим требованиям.
4. info - exclude
Каталог info содержит файл exclude, в котором можно указывать любые файлы, и Git не станет добавлять их в свою историю. Это почти то же самое что и .gitingnore (возможно вы сталкивались с ним. Его можно найти в корневом каталоге вашего проекта), за тем исключением, что exclude не сохраняется в истории проекта, и вы не сможете им поделиться с другими.
5. refs
Каталог refs хранит в себе копию ссылок на объекты коммитов в локальных и удаленных ветках.
6. logs
Каталог logs хранит в себе историю проекта для всех веток в вашем проекте.
7. objects
Каталог objects хранит в себе BLOB объекты, каждый из которых проиндексирован уникальным SHA.
8. index
Промежуточная область с метаданными, такими как временные метки, имена файлов, а также SHA файлов, которые уже упакованы Git. В эту область попадают файлы, над которыми вы работали, при выполнение команды git add
.
9. HEAD
Файл содержит ссылку на текущую ветку, в которой вы работаете
10. ORIG_HEAD
Каждый раз во время слияния в этот файл попадает SHA ветки, с которой проводилось слияние
11. FETCH_HEAD
Файл хранит в себе ссылки в виде SHA на ветки, которые участвовали в git fetch
12. MERGE_HEAD
Файл хранит в себе ссылки в виде SHA на ветки, которые участвовали в git merge
13. COMMIT_EDITMSG
Файл содержит в себе последнее введенное вами сообщение коммита
Самые распространенные команды в Git.
При работе с системами контроля версий разработчики сталкиваются с определенной, повторяющейся последовательностью действий. Оно и понятно, ведь, по сути, если не брать в расчет возможности Git для управления состоянием проекта и прочие плюшки, то как правило ваша работа ограничена рядом действий:
1. Внести изменения в проект;
2. Добавить изменения в индекс(staging area) - git add
(таким образом вы сообщаете Git какие именно изменения должны быть занесены в историю.)
2. Закоммитить изменения - git commit
(сохранить изменения в историю проекта)
3. Запушить - git push
(отправить результаты работы на удаленный сервер, чтобы другие разработчики тоже имели к ним доступ)
Итак, разберемся в этом подробнее. Проинициализировав Git репозиторий, вы начинаете вносить какие-то изменения в проект. Предположим, что вы создали файл `hello_world.txt` и работаете над его редактированием.
Введем git status
и увидим следующее:
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello_world.txt
Команда git status
отображает состояние директории и индекса(staging area). Это позволяет определить, какие файлы в проекте отслеживаются Git, а также какие изменения будут включены в следующий коммит.
Так как вы создали новый файл, Git определяет его как неотслеживаемый, и тут же подсказывает, что делать дальше:
use “git add <file>...” to include in what will be committed
Так и поступим:
git add hello_world.txt
On branch master
No commits yet
Changes to be commited:
(use "git rm --cached <file>..." to unstage)
new file: hello_world.txt
Файл добавлен в индекс. Теперь можно закоммитить внесенные изменения и оставить небольшое описание. Делается это командой:
git commit -m ‘first commit
Готово! Мы сделали наш первый коммит! Далее добавим в наш файл строку “Hello, World!”, и снова проверим git status:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
no changes added to commit (use "git add" and/or "git commit -a")
Теперь Git сообщает, что у нас есть измененный файл hello_world.txt
. И теперь нам сново нужно добавить его в индекс и затем закоммитить.
Что ж, мы научились записывать и хранить изменения на своей машине, теперь нам нужно отправить версию нашей истории на удаленный сервер. В данном примере я воспользуюсь репозиторием на GitHub.
Для начала вам нужно создать удаленный репозиторий. Как это реализовать в случае с GitHub подробно описано тут.
Далее необходимо добавить удаленный репозиторий в Git:
git remote add <remote_name> <remote_repo_url>
Эта команда сопоставит удаленное хранилище с ссылкой на локальный репозиторий. С этого момента можно обращаться к удаленному репозиторию через эту ссылку. Например:
git remote add origin https://github.com/user/hello_world.git
В данном случае “origin” является коротким именем для удаленного репозитория, на которое он будет ссылаться. Вы можете выбрать совершенно любое имя - это не важно. “origin” это просто стандартное соглашение.
Осталось дело за малым - отправить результат нашей работы в репозиторий. Делается это следующим образом:
git push origin
Готово! Теперь история изменений вашего проекта будет храниться в удаленном репозитории.
Работа с историей
Итак, как записывать, сохранять и отправлять изменения в удаленное хранилище мы разобрались.
Настало время поговорить о том, как управлять историей проекта. А именно как просматривать изменения и как откатить проект до определенной точки.
Для инспектирования истории в Git предусмотрен определенный ряд команд, рассмотрим несколько из них:
git log
git show
git reflog
git reset
git log
1. git log
Данная команда предназначена для отображения всей вашей истории. Она может быть весьма удобна, если вам понадобилось узнать, какие изменения вы вносили ранее. Или если вам нужно откатиться до определенного места в истории, либо если есть нужда её отредактировать.
Если ввести git log
без каких либо параметров, выглядит это примерно так:
git log
commit 957e1132f57d83§dbd402faf3c858cf5ba8b335f (HEAD -> master)
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:25:21 1021 +0300
fourth commit
commit ekd53dkcld4dkf334r3r3sefio5dk6kfl54dkf53
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:22:25 2021 +0300
third commit
commit dslf4453lk34jk34k3h5g34u6m5n75j7kj3l345k
Date: Fri Jul 16 13:22:27 2021 +0300
second commit
commit h4k4o5jk2lhkl234jkl6nkg6j4lh4gjbh6ll45k4
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:21:32 2021 +0300
first commit
git log
имеет огромное множество дополнительных параметров, которые будут влиять на вывод в консоль. Вам предоставляется выбор на любой вкус.
Хотите просмотреть последние три коммита? Пожалуйста:
git log -3
commit ekd53dkcld4dkf334r3r3sefio5dk6kfl54dkf53
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:22:25 2021 +0300
third commit
commit dslf4453lk34jk34k3h5g34u6m5n75j7kj3l345k
Date: Fri Jul 16 13:22:27 2021 +0300
second commit
commit h4k4o5jk2lhkl234jkl6nkg6j4lh4gjbh6ll45k4
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:21:32 2021 +0300
first commit
Есть необходимость вывести все в одну линию? Запросто:
git log --oneline
957e113 (HEAD -> main) fourth commit
ekd53dk third commit
dslf445 second commit
h4k4o5j first commit
Так можно продолжать до бесконечности, поэтому я оставлю ссылочку, перейдя по которой, вы сможете с ними подробней ознакомиться.
2. git show
Команда git show
используется для отображения полной информации о любом объекте в Git, будь то коммит или ветка. По умолчанию git show
отображает информацию коммита, на который в данный момент времени указывает HEAD.
Для удобства работы git show
оснащен рядом дополнительных параметров, некоторые из них мы рассмотрим ниже.
Итак, если ввести git show
, мы получим следующий результат:
commit 957e1132f57d83§dbd402faf3c858cf5ba8b335f (HEAD -> master)
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:25:21 1021 +0300
fourth commit
diff --git a/hello_world.txt b/hello_world.txt
index b402110..d49b5d7 10044
--- a/hello_world.txt
+++ b/hello_world.txt
@@ -1,2 +1,3 @@
Hello world!
Bye, bye!
+See you soon!
Здесь представлена полная информация о последнем коммите, а также какие именно изменения он в себя включает.
Мы также можем вывести диапазон из указанных коммитов. Диапазон указывается полуоткрытым интервалом, содержащим id коммитов, не включая первый элемент. Выглядит это следующим образом:
git show 349de9d..957e113
commit 957e1132f57d83§dbd402faf3c858cf5ba8b335f (HEAD -> master)
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:25:21 1021 +0300
fourth commit
diff --git a/hello_world.txt b/hello_world.txt
index b402110..d49b5d7 10044
--- a/hello_world.txt
+++ b/hello_world.txt
@@ -1,2 +1,3 @@
Hello world!
Bye, bye!
+See you soon!
commit ekd53dkcld4dkf334r3r3sefio5dk6kfl54dkf53
Author: egor <egor@mail.ru>
Date: Fri Jul 16 13:22:25 2021 +0300
third commit
diff --git a/hello_world.txt b/hello_world.txt
index cd08755..b402110 100644
--- a/hello_world.txt
+++ b/hello_world.txt
@@ -1 +1,2 @@
Hello world!
+Bye, bye!
Для более лаконичного вывода, можно воспользоваться командой:
git show --oneline
957e113 (HEAD -> master) fourth commit
diff --git a/hello_world.txt b/hello_world.txt
index b402110..d49b5d7 10044
--- a/hello_world.txt
+++ b/hello_world.txt
@@ -1,2 +1,3 @@
Hello world!
Bye, bye!
+See you soon!
Таким образом, мы сократим id коммита, а также исключим авторство и дату коммита.
Подробнее с командой `git show` и с её параметрами можно ознакомиться перейдя по ссылке.
3. git reflog
Эта команда выводит упорядоченный список коммитов, на которые указывал HEAD. Грубо говоря, она отображает историю всех ваших перемещений по проекту.
Основное преимущество этой команды заключается в том, что если вы вдруг случайно удалили часть истории или откатились назад, вы сможете проинспектировать момент утраты нужной вам информации и откатиться обратно.
Это возможно за счет того, что git reflog
хранит свою информацию на вашей машине отдельно от коммитов, поэтому при удалении чего-либо в истории, в сможете это найти в git reflog
.
Вывод этой команды выглядит следующим образом:
957e113 (HEAD -> master) HEAD@{5}: commit: fourth commit
ekd53dk HEAD@{6}: commit: third commt
dslf445 HEAD@{7}: commit: second commit
h4k4o5j HEAD@{8}: commit (intial): first commit
4. git reset
Теперь давайте рассмотрим очень полезную команду `git reset`. Она позволяет откатить проект до определенной точки.
Эту команду можно использовать с тремя параметрами:
git reset --soft <commit>
git reset --mixed <commit>
git reset --hard <commit>
Рассмотрим их по порядку. Для этого сначала давайте вспомним, что такое index. Как я упоминал ранее, index - это временный файл, который фиксирует структуру Git проекта в определенный момент времени. Это важная деталь сейчас, поскольку команда git reset в зависимости от параметра прокидывает нас в истории проекта с соответствующими состояниями индекса.
1. В случае с --soft
, содержимое вашего индекса, а также рабочей директории, остается неизменным. Это значит, что если мы откатимся назад на пару коммитов, мы изменим ссылку указателя HEAD на указанный коммит и все изменения, которые были до этого внесены, окажутся в индексе.
2. При использовании параметра --mixed
, мы опять-таки изменим ссылку указателя HEAD, но все предыдущие изменения в индекс не попадут, а будут отслеживаться как не занесенные в индекс. Это дает возможность внести в индекс только те изменения, которые нам необходимы, что довольно удобно!
3. Если использовать команду git reset
с параметром --hard
, мы снова изменим ссылку указателя HEAD, но все предыдущие изменения не попадут ни в индекс, ни в зону отслеживаемых файлов. Это значит, что мы полностью сотрем все изменения, которые вносили ранее. Это также удобно, если вы знаете, что вам больше не пригодится ваша предыдущая работа над проектом.
Давайте вернемся к нашему репозиторию и рассмотрим следующий пример:
git log --oneline
957e113 (HEAD -> master) fourth commit
ekd53dk third commit
dslf445 second commit
h4k4o5j first commit
Итак, в ходе нашей работы, мы сделали четыре коммита. Предположим, что мы хотим откатить проект до второго коммита. Давайте посмотрим, как это будет происходить, используя разные параметры:
git reset --soft 349de9d
Далее, проверим индекс:
git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hello_world.txt
И снова git log --oneline
:
dslf445 (HEAD -> master) second commit
h4k4o5j first commit
Как и ожидалось, указатель HEAD переместился на второй коммит, а состояние индекса осталось неизменным.
Теперь повторим наши действия, но уже с параметром --mixed
:
git reset --mixed 349de9d
Проверим git status:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello_world.txt
А также git log --oneline
:
dslf445 (HEAD -> master) second commit
h4k4o5j first commit
В данном случае, указатель снова переместился на второй коммит, но предыдущие изменения попали в зону отслеживаемых файлов. Это значит, что теперь мы можем решить - оставить эти изменения, добавив их в индекс, либо избавиться от них.
И в заключении повторим ту же последовательность действий с параметром --hard
.
git reset --hard 349de9d
Снова проверяем git status
:
On branch master
nothing to commit, working tree clean
И git log --oneline
:
dslf445 (HEAD -> master) second commit
h4k4o5j first commit
Здесь указатель HEAD переместился на второй коммит, а все предыдущие изменения были стерты, что видно по пустому индексу и зоне отслеживаемых файлов.
И если посмотреть сейчас содержимое файла, то мы увидим единственную строку “Hello, world!”, которую мы с вами добавляли в файл во втором коммите.
Ветвление в Git
Почти каждая система контроля версий имеет поддержку ветвления. Ветвление означает, что у вас есть возможность работать над разными версиями проекта. То есть, если раньше история вашей разработки являла собой прямую последовательность коммитов, то теперь она может расходиться в определенных точках.
Это очень полезная функция по многим причинам, например для взаимодействия нескольких разработчиков. Представьте, вы с коллегой корпите над одним проектом. Каждый из вас работает над разными фичами, и для того чтобы не мешать друг другу, вы можете работать в разных ветках, а по окончанию работы слить эти ветки в одну.
Давайте попробуем с этим поработать на нашем примере. У нас имеется следующая последовательность коммитов.
957e113 (HEAD -> master) fourth commit
ekd53dk third commit
dslf445 second commit
h4k4o5j first commit
Git по умолчанию во время инициализации создает ветку master и уже ведет свою работу в ней. Мы можем в этом убедиться введя команду:
git branch
* master
Предположим, что нам по какой-либо причине понадобилось создать новую ветку и вести работу в ней. Для этого сначала необходимо её создать.
Делается это при помощи команды git branch <branch_name>
. Давайте создадим ветку “dev”:
git branch dev
Теперь введя команду git branch
мы увидим следующее:
dev
* master
Звёздочкой Git указывает на текущую ветку, в которой мы работаем.
Для того чтобы переключиться на другую ветку используют команду git checkout <branch_name>
. Давайте переключимся на ветку “dev”.
git checkout dev
Switched to branch 'dev'
Теперь внесем любые изменения в файл hello_world.txt
и сделаем коммит, после чего посмотрим, как выглядят наши ветки после редактирования.
Взглянем на git log --oneline
:
dece9c9 (HEAD -> dev) fifth commit
957e113 (master) fourth commit
ekd53dk third commit
dslf445 second commit
h4k4o5j first commit
Как и следовало ожидать, в нашей истории появился еще один - пятый коммит.
Теперь перейдем на ветку master
git checkout master
И просмотрим git log --oneline
, и убедимся в том что все осталось без изменений.
957e113 (HEAD -> master) fourth commit
ekd53dk third commit
dslf445 second commit
h4k4o5j first commit
Помимо разделения истории в Git мы также можем соединять воедино два потока разработки. Это значит, что нашу проделанную работу в новой ветке мы можем слить обратно в master. Такой процесс слияния можно выполнить при помощи команды git merge <branch_name>
. То есть, если мы хотим слить изменения из ветки “dev” в ветку “master”, нам необходимо перейти на ветку “master” и в ней выполнить:
git merge dev
Updating 957e113..dece9c9
Fast-forward
hello_world.txt | 1 +
1 file chaged, 1 insertion(+)
Теперь если мы проверим git log --oneline
, то убедимся в том, что новый коммит из ветки “dev” переместился в ветку “master”.
dece9c9 (HEAD -> master, dev) fifth commit
957e113 fourth commit
ekd53dk third commit
dslf445 second commit
h4k4o5j first commit
Теперь от ненужной ветки можно избавиться и удалить её с помощью команды git branch -d <branch_name>
.
В данных примерах я не учитывал того факта, что при слиянии веток иногда возможно возникновение конфликтов, которые приходится разрешать вручную. Как правило это происходит при слиянии двух веток, в которых одновременно велась какая-то работа. Или же когда в новой ветке вы задели изменения старой. Я не буду рассматривать такие примеры, т.к. разрешение конфликтов - тема не маленькая, и многие вещи в ней можно разобрать самостоятельно в ходе практики.
Примеры ведения истории проекта
Моя статья подходит к концу, но перед завершением хочу отметить, что во многих командах существуют определенные соглашения по поводу ведения истории в Git.
Например вас могут попросить соблюдать несколько правил, при написании сообщения коммита. Или перед работой вас могут ознакомить с определенной стратегией ветвления в проектах компании. Вас также могут ограничить в количестве отправляемых коммитов в удаленный репозиторий.
В качестве примера, я расскажу какие соглашения действуют в компании, в которой я работаю.
1. Сообщение коммита:
Ниже представлен шаблон наших сообщений коммита:
Мы указываем дату совершения коммита и версию приложения для удобства поиска работы в истории.
Модификаторы формата коммита предоставляют информацию о том какой фронт работы был выполнен в этом коммите.
Мы используем следующие модификаторы:
Dev:
- указывает на то, что в коммите велась разработка нового функционала.Refactoring:
- данный модификатор сообщает о рефакторинге проведенном в коде.Fix:
- в данном коммите фиксили баги.Release:
- данный коммит отправлен в ветку "release" и хранит состояние релизной версии приложения.
Также в конце сообщения мы оставляем короткое описание - над чем мы работали в этом коммите.
2. Стратегия ветвления:
В действительности можно насчитать достаточно много стратегий ветвления. Все они могут незначительно различаться, но выполнять совершенно разные задачи.
В нашем случае, мы выделяем две основные ветки master и "release". Master используется для подготовки к выкладке новых версий приложения. Код попавший в "master" проходит автоматические тесты, после которых выполняется сборка проекта, которую необходимо вручную протестировать перед дальнейшими действиями. Далее если замечаний к работе нет, мы сливаем ветку "master" в ветку "release". Там снова запускаются автоматические тесты, и собираются сборки к выкладке в маркеты.
Для ведения разработки мы создаем feature векти. Это означает, что каждая ветка отвечает за разработку какой-нибудь функциональности. Например, если мы хотим внедрить в приложение хранение данных в облаке, то программист создаст ветку "feature-cloud" и будет вести работу в ней.
Заключение
Мы рассмотрели самые основные приемы работы с Git. Моей задачей было сформировать в вас некоторое понимание - что есть система контроля версий и познакомить с одной из них. Мы разобрали структуру Git проекта, и теперь у вас есть представление о том, как он работает. Мы познакомились с самыми важными командами в Git, рассмотрели некоторые команды для инспектирования истории проекта и даже овладели несколькими приемами для перемещения HEAD указателя. Мы немного затронули тему ветвления, попробовали создать свою новую ветку и слить её с базовой.
Надеюсь, вам было интересно. Хочу снова заметить, что Git - тема комплексная, и, собирая информацию по крупицам, вы в итоге сможете работать уверенно с этим инструментом. Главное здесь - практика и желание во всем разобраться.
В качестве тренировки и закрепления имеющихся навыков, оставлю ссылку на удобный тренажер для Git.
А также на книги, которыми я пользовался и интернет ресурсы:
1. “Version control with Git” - Jon Loeliger;
2. “Pro Git” - Scott Chacon, Ben Straub.
4. git-scm.com
Также было бы интересно узнать какие практики по Git есть у вас в компаниях и какие интересные ресурсы вы можете подсказать.
Спасибо за ваше внимание!