Git

Git – это распределенная система контроля версий (далее – СКВ), которая позволяет управлять исходным кодом. Изначально, Git был разработан Линусом Торвальдсом для разработки Linux Kernel. Данное руководство объясняет как использовать Git для контроля версий на проекте в распределенной среде при разработке программного обеспечения (далее – ПО). Оно должно помочь новичкам изучить базовый функционал системы Git. После изучения данного цикла статей, вы будете обладать уровнем, достаточным для работы с данной технологией, и сможете изучать более сложные возможности Git.

Для более глубокого понимания, рекомендуется обладать базовыми знаниями языка Java и общими представлениями о жизненном цикле разработки ПО.

Система контроля версий (далее – СКВ) – это программное обеспечение (далее – ПО), которое помогает разработчикам работать в команде при разработке ПО и сохранять всю историю работы над проектом.

Ниже указаны основные функции СКВ:

  • Позволяет разработчикам работать над проектом одновременно
  • Запрещает переписывать изменения друг друга
  • Сохраняет каждую версию ПО

Существует два типа СКВ:

  • Централизованные СКВ
  • Распределённые (Децентрализованные) СКВ

В рамках данного курса мы рассмотрим только распределенные СКВ на примере Git.


Распределённые СКВ (РСКВ)

Централизованные СКВ используют центральный сервер для хранения всех файлов и позволяет команде взаимодействовать. Но данный тип СКВ подвержен большой опасности – выходу из строя центрального сервера. Если с сервером что-то происходит, то работа над проектом прекращается, так как разработчики не имеют доступа к исходному коду. А если данные на сервере утеряны, то (если нет резерва) данные теряются безвозвратно.

Именно поэтому в настоящее время именно распределенные СКВ пользуются огромной популярностью.

Клиент РСКВ не только проверяет крайние изменения базовой директории, но также является и резервным хранилищем проекта. Если сервер выходит из строя, базовая версия может быть восстановлена с помощью клиентской машины. Таким образом, Git не полагается на центральный сервер, благодаря чему мы можем работать с Git и выполнять большинство операций даже тогда, когда мы находимся не в сети. Мы можем подтверждать изменения, создавать новые ветки, просматривать историю изменений и т.д. при работе оффлайн. После этого нам необходимо только подключиться к сети и опубликовать наши крайние изменения.


Базовая терминология Git

  • Рабочая директория и плацдарм (Working Directory and Staging Area)

    Рабочая директория – это место, где файлы проверяются. Git не отслеживает каждый измененный файл, когда мы выполняем операцию.
    commit,
    Git ищет все файлы, которые находятся в рабочей директории. И подтверждаются только те файлы, которые в ней находятся.

    Давайте рассмотрим небольшой пример.

  • Мы изменяем файл в рабочей директории

  • Мы добавляем эти файлы в плацдарм

  • Мы выполняем подтверждение изменений (commit), тем самым удаляя файлы из плацдарма. После выполнения операции
    push
    файлы находятся в Git репозитории. Предположим, что у нас есть два файла
    Developer.java
    и
    Project.java
    и мы хотим выполнить две разные операции
    commit
    для каждого из них. Мы добавляем один файл в плацдарм и выполняем операцию
    commit
    , после чего повторяем эту же процедуру с другим файлом. Пример:

# Первый commit
[корень_проекта]$ git add Developer.java
[корень_проекта]$ git commit -m "Adding Developer class"

# Второй commit
[корень_проекта]$ git add Project.java
[корень_проекта]$ git commit -m "Adding Project class"
  • Локальный репозиторий (Local Repository)

    Git предоставляет личное рабочее пространство для работы с проектом, который называется локальным репозиторием. Разработчик вносит изменения в проект в этом репозитории и, после подтверждения изменений, они становятся частью локальной копии. Пользователь может выполнить множество изменений, которые будут храниться только на его машине до тех пор, пока он не отправит их в центральный репозиторий.

  • Дерево (Tree)

    Дерево – это объект, который представляет собой директорию. Он хранит бинарные большие объекты как под-директории. Дерево – это бинарный файл, который хранит ссылки на, так называемые,
    Blobs
    и деревья, которые представлены SHA1 хэшем объекта дерева.

  • Бинарный Большой Объект (Blob)

    Binary Large Object – это файл, который представляет версию файла. Он содержит данные файла, но не хранит его метаданные. Это двоичный объект и на базе данных Git он называется SHA1 хэшем файла. В Git доступ к файлам обеспечивается не по имени, а по содержанию.

  • Коммит (Commit)
    Коммит хранит текущее состояние репозитория, он также называется SHA1 хэшем. Мы можем представить, что
    commit
    – это элемент связного списка. Каждый такой элемент имеет ссылку на родительский элемент. Из этого элемента мы можем откатиться назад с помощью ссылки на предыдущий элемент для того. Если у коммита есть несколько родительских коммитов, то это означает, что он был создан путем слияния двух ветвей.

  • Клон (Clone)
    Операция Clone создает экземпляр репозитория. Данная операция не только проверяет рабочую копию, но также становится хранилищем самого репозитория (зеркалом – mirror). Разработчик может выполнять множество операций на локальной машине, и, после подключения к сети, все данные могут быть синхронизированы.

  • Ветвь (Branch)
    Ветви используются для создания отдельной версии разработки. По умолчанию, Git имеет главную ветвь, которая называется
    master
    . Когда нам необходимо реализовать какой-либо функционал или исправить ошибку, мы создаем отдельную ветвь и выполняем необходимую работу. После того, как задача выполнена, мы выполняем слияние с основной ветвью Git и удаляем ненужную ветвь. Это позволяет всегда хранить рабочую версию проекта и вносить уже полностью готовые и протестированные изменения в основную ветвь. Каждая ветвь имеет заголовок (HEAD), который является ссылкой на крайний коммит ветви. Когда мы выполняем операцию
    commit
    , HEAD обновляется.

  • Вытягивать (Pull)
    Данная операция копирует все изменения из удаленного репозитория на локальную машину. Она используется для синхронизации локального репозитория с центральным.

  • Толчок (Push)
    Операция
    Push
    копирует изменения из локального репозитория в удаленный. Она используется для синхронизации центрального репозитория с локальным.

  • Пересмотр (Revision)
    Revision представляет собой версию исходного кода и представлена коммитами, которые, в свою очередь, определяются SHA1-хэшами.

  • URL
    URL представляет локацию репозитория и хранится в конфигурационном файле.

  • Заголовок (HEAD)
    HEAD – это ссылка, которая всегда указывает на крайний коммит ветви. Когда мы выполняем операцию
    commit
    , HEAD обновляется и переводится на крайний коммит. Заголовки ветви хранятся в директории
    .git/refs/heads/
    .

Установка Git

Прежде чем использовать Git, нам необходимо выполнить установку и некоторые настройки. Рассмотрим пример установки на ОС Linux Ubuntu 16.04 LTS.


Установка клиента Git

Для установки Git нам необходимо выполнить команду

sudo apt-get update
sudo apt-get install git

После этого проверяем нашу версию:

sud git --version
git version 2.7.4

Установка завершена.


Настройка Git

Git обеспечивает средства для конфигурирования некоторых переменных. Все глобальные настройки хранятся в файле .gitconfig, который находится в домашней директории. Для того, чтобы изменить глобальные настройки, нам необходимо использовать команду –global

Рассмотрим пример установки некоторых данных (имя и email):

git config --global user.name "Eugene Suleimanov"
git config --global user.email "[email protected]"

Теперь посмотрим нашу текущую конфигурацию:

git config --list 

[email protected]
user.name=FirstName LastName

Жизненный цикл Git.

Обычный рабочий процесс работы с Git выглядит следующим образом:

  • Создание локальной копии удаленного репозитория (операция Clone)
  • Изменение локальной копии проекта (добавление/изменение/удаление файлов)
  • Обновление локальной копии при необходимости (операция Pull)
  • Подтверждение изменений в локальном репозитории (операция Commit)
  • Добавление изменение из локального репозитория в центральный (операция Push)

Графически данный рабочий процесс можно представить следующим образом:

Рассмотрим процесс создания удалённого репозитория Git

  1. Создание удаленного репозитория

Для начала создадим репозиторий. Для этого нам прежде всего необходимо перейти на сайт https://github.com/

После регистрации нам необходимо перейти в свой профиль и создать новый репозиторий.

В нашем случае это репозиторий с именем GitTutorial, который имеет следующую URL:

https://github.com/proselytear/GitTutorial

  1. Инициализация Git в проекте

Для начала создадим простой Java-проект. Я создал консольное Java-приложение с именем GitTutorial.

Теперь нам необходимо инициализировать Git с помощью команды:

[project_root]$ git init
Initialized empty Git repository in [project_root]/GitTutorial/.git/
  1. Добавление удаленного репозитория

Для того, чтобы добавить удаленный репозиторий, мы должны выполнить в терминале следующую команду:

[project_root]/GitTutorial$ git remote add proselyte "https://github.com/proselytear/GitTutorial"
  1. Добавление файлов в удаленный репозиторий.
    Для начала выполним две команды, которые рассмотрим в последующих статьях:
git add --all
 git commit -m "Initial commit of the project"

[master (root-commit) 3c199cf] Initial commit of the project
 10 files changed, 818 insertions(+)
 create mode 100644 .idea/compiler.xml
 create mode 100644 .idea/copyright/profiles_settings.xml
 create mode 100644 .idea/description.html
 create mode 100644 .idea/misc.xml
 create mode 100644 .idea/modules.xml
 create mode 100644 .idea/project-template.xml
 create mode 100644 .idea/workspace.xml
 create mode 100644 GitTutorial.iml

Теперь нам осталось только “залить” проект на удаленный репозиторий:

git push proselyte master 

Username for 'https://github.com': proselytear
Password for 'https://[email protected]': 
Counting objects: 24, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (18/18), done.
Writing objects: 100% (24/24), 8.85 KiB | 0 bytes/s, done.
Total 24 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), done.
To https://github.com/proselytear/GitTutorial
 * [new branch]      master -
>
 master

Теперь, если перейдем в наш удаленный репозиторий, то увидим ,что все файлы нашего проекта добавлены в удаленный репозиторий.

Рассмотрим процесс клонирования проекта из центрального репозитория на локальную машину.

Операция clone создает экземпляр удаленного репозитория.

Предположим, что нам необходимо клонировать репозиторий, который находится по ссылке:

https://github.com/proselytear/GitTutorial

Для этого мы должны перейти в нужную нам директорию и выполнить следующую команду:

 git clone https://github.com/proselytear/GitTutorial

Cloning into 'GitTutorial'...
remote: Counting objects: 46, done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 46 (delta 7), reused 43 (delta 4), pack-reused 0
Unpacking objects: 100% (46/46), done.
Checking connectivity... done.

В результате выполнения данной команды мы создадим копию удаленного репозитория в нужной нам директории.

Внесение изменений

Предположим, что нам необходимо удалить одни файлы и добавить другие.

Так выглядит изначальная структура нашего проекта:

Удалим файл HelloWorld.java и добавим следующие два класса:

Developer.java

package net.proselyte.gittutorial;

/**
 * Simple JavaBean domain object that represents a Developer.
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */

public class Developer {
    private String firstName;
    private String lastName;
    private String specialty;
    private Integer salary;

    public Developer() {
    }

    public Developer(String firstName, String lastName, String specialty, Integer salary) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.specialty = specialty;
        this.salary = salary;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getSpecialty() {
        return specialty;
    }

    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }

    public Integer getSalary() {
        return salary;
    }

    public void setSalary(Integer salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "First Name: " + firstName +
                "\nLast Name: " + lastName +
                "\nSpecialty: " + specialty +
                "\nSalary: " + salary;
    }
}

Project.java

package net.proselyte.gittutorial;

/**
 * Main class of application
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */

public class Project {
    public static void main(String[] args) {
        Developer developer = new Developer("Eugene", "Suleimanov", "Java", 3_000);

        System.out.println("Developer Information:\n");
        System.out.println(developer.toString());
    }
}

Теперь проверим статус Git с помощью команды

 git status 

On branch master
Changes not staged for commit:
  (use "git add/rm ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

        modified:   .idea/workspace.xml
        deleted:    out/production/GitTutorial/net/proselyte/gittutorial/HelloWorld.class
        deleted:    src/net/proselyte/gittutorial/HelloWorld.java

Untracked files:
  (use "git add ..." to include in what will be committed)

        out/production/GitTutorial/net/proselyte/gittutorial/Developer.class
        out/production/GitTutorial/net/proselyte/gittutorial/Project.class
        src/net/proselyte/gittutorial/Developer.java
        src/net/proselyte/gittutorial/Project.java

no changes added to commit (use "git add" and/or "git commit -a")

Для того, чтобы добавить наши изменения в локальный репозиторий git, нам необходимо выполнить следующие две команды в терминале:

  1. Добавить файлы в Git
 git add --all
  1. Подтвердить изменения
git commit -m "Adding classes Developer.java and Project.java"

[master 97d5de4] Adding classes Developer.java and Project.java
 7 files changed, 156 insertions(+), 42 deletions(-)
 create mode 100644 out/production/GitTutorial/net/proselyte/gittutorial/Developer.class
 delete mode 100644 out/production/GitTutorial/net/proselyte/gittutorial/HelloWorld.class
 create mode 100644 out/production/GitTutorial/net/proselyte/gittutorial/Project.class
 create mode 100644 src/net/proselyte/gittutorial/Developer.java
 delete mode 100644 src/net/proselyte/gittutorial/HelloWorld.java
 create mode 100644 src/net/proselyte/gittutorial/Project.java

И добавим файл .gitignore, который позволят нам игнорировать некоторые файлы и папки (классы, конфигурационные файлы IDE, jar-файлы и т.д.):

# Folders
.idea/*
out/*

# Files
*.class

В данном случае мы игнорируем содержимое папок .idea/иout/, а также все файлы с расширением *.class.

Повторим процедуру добавления файлов в локальный репозиторий и подтверждения изменений:

git add --all
git commit -m "Adding .gitignore file"

[master 5e0298b] Adding .gitignore file
 2 files changed, 28 insertions(+), 4 deletions(-)
 create mode 100644 .gitignore

Проверим статус git еще раз:

git status 

On branch master
nothing to commit, working directory clean

Все файлы добавлены и изменения подтверждены.

Просмотр истории изменений

В процессе разработки мы можем столкнуться с ситуацией, когда нам необходимо просмотреть историю изменений в Git репозитории.

Для этих целей в Git предусмотрена команда:

 git log

Попробуем выполнить эту команду в нашем проекте:

git log

commit 11f75b7bc8884203624ba1d552438d57a7c3559d
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 19:15:53 2016 +0300

    Adding .gitignore file.

commit 5e0298b007582bec3a8f4f68db74ba4ddfa40838
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 19:15:21 2016 +0300

    Adding .gitignore file

commit 97d5de493ac15f821b109b7b0375d4f94e1f2dd1
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 19:10:41 2016 +0300

    Adding classes Developer.java and Project.java

commit a0f051aa654aa43db508f460b5bd28e8a41fe2ae
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 17:43:12 2016 +0300

    Initial commit of the project.

commit 0853db5f06305eae525b954f587ecc49c62debd9
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 17:41:35 2016 +0300

    Initial commit of the project

commit 5e8179a97b971f8fd11118e64f4d624b5ddf3ea6
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 17:20:53 2016 +0300

    Initial commit of the project

commit 3c199cf96dba9131bb3df299aa819b9cbef6a870
Author: Eugene Suleimanov 
<[email protected]>

Date:   Wed Aug 17 17:20:27 2016 +0300

    Initial commit of the project
(END)

Здесь число рядом со словом commit– это SHA-1 идентификатор ID- коммита.

Для того, чтобы просмотреть более подробную информацию по коммиту (используя SHA-1 ID коммита), мы можем использовать следующую команду:

git show 11f75b7bc8884203624ba1d552438d57a7c3559d

commit 11f75b7bc8884203624ba1d552438d57a7c3559d
Author: Eugene Suleimanov 
<
[email protected]
>

Date:   Wed Aug 17 19:15:53 2016 +0300

Adding .gitignore file.

diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index a4cab11..b0392f8 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -1,9 +1,7 @@

<
?xml version="1.0" encoding="UTF-8"?
>
<
project version="4"
>
<
component name="ChangeListManager"
>

-    
<
list default="true" id="09375eb2-79d2-4940-a2f0-04b9c4c4c09b" name="Default" comment=""
>

-      
<
change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" /
>

-    
<
/list
>

+    
<
list default="true" id="09375eb2-79d2-4940-a2f0-04b9c4c4c09b" name="Default" comment="" /
>
<
ignored path="GitTutorial.iws" /
>
<
ignored path=".idea/workspace.xml" /
>
<
ignored path="$PROJECT_DIR$/out/" /
>

@@ -690,12 +688,12 @@

<
option name="number" value="Default" /
>
<
option name="presentableId" value="Default" /
>
<
updated
>
1471442570577
<
/updated
>

-      
<
workItem from="1471442574162" duration="5174000" /
>

+      
<
workItem from="1471442574162" duration="5219000" /
>
<
/task
>
<
servers /
>
<
/component
>
<
component name="TimeTrackingManager"
>

-    
<
option name="totallyTimeSpent" value="5174000" /
>

+    
<
option name="totallyTimeSpent" value="5219000" /
>
<
/component
>
<
component name="ToolWindowManager"
>
<
frame x="0" y="24" width="1366" height="744" extended-state="6" /
>

Таким образом, мы всегда можем получить подробную информацию по всем изменениям в репозитории.

Подтверждение изменений

Предположим, что мы хотим добавить новый класс Team, который имеет следующий вид:

Team.java

package net.proselyte.gittutorial;

import java.util.List;

/**
 * Simple JavaBean domain object that represents a Team of {@link Developer}s.
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */

public class Team {
    private String teamName;
    private List
 developers;

    public String getTeamName() {
        return teamName;
    }

    public void setTeamName(String teamName) {
        this.teamName = teamName;
    }

    public List
 getDevelopers() {
        return developers;
    }

    public void setDevelopers(List
 developers) {
        this.developers = developers;
    }

    public void addDeveloperToTeam(Developer developer) {
        this.developers.add(developer);
    }

    public void removeDeveloperFromTeam(Developer developer) {
        this.developers.remove(developer);
    }

    public void shotTeam() {
        System.out.println(developers);
    }

    @Override
    public String toString() {
        return "Team{" +
                "teamName='" + teamName + '\'' +
                ", developers=" + developers +
                '}';
    }
}

Добавим данный файл в Git и подтвердим изменения:

git add src/net/proselyte/gittutorial/Team.java
 git commit -m "Adding some class to project"

[master 424e9e1] Adding some class to project
 1 file changed, 51 insertions(+)
 create mode 100644 src/net/proselyte/gittutorial/Team.java

Теперь посмотрим историю коммитов:

git log 

commit 424e9e151e84805a2637afe4deb729d14c2c1c28
Author: Eugene Suleimanov 

Date:   Wed Aug 17 19:46:55 2016 +0300

    Adding some class to project

commit 11f75b7bc8884203624ba1d552438d57a7c3559d
Author: Eugene Suleimanov 

Date:   Wed Aug 17 19:15:53 2016 +0300

    Adding .gitignore file.

commit 5e0298b007582bec3a8f4f68db74ba4ddfa40838
Author: Eugene Suleimanov 

Date:   Wed Aug 17 19:15:21 2016 +0300

    Adding .gitignore file

commit 97d5de493ac15f821b109b7b0375d4f94e1f2dd1
Author: Eugene Suleimanov 

Date:   Wed Aug 17 19:10:41 2016 +0300

    Adding classes Developer.java and Project.java

commit a0f051aa654aa43db508f460b5bd28e8a41fe2ae
Author: Eugene Suleimanov 

Date:   Wed Aug 17 17:43:12 2016 +0300

    Initial commit of the project.

commit 0853db5f06305eae525b954f587ecc49c62debd9
Author: Eugene Suleimanov 

Date:   Wed Aug 17 17:41:35 2016 +0300

    Initial commit of the project

commit 5e8179a97b971f8fd11118e64f4d624b5ddf3ea6
Author: Eugene Suleimanov 

Date:   Wed Aug 17 17:20:53 2016 +0300

    Initial commit of the project

commit 3c199cf96dba9131bb3df299aa819b9cbef6a870
Author: Eugene Suleimanov 

Date:   Wed Aug 17 17:20:27 2016 +0300

    Initial commit of the project

Несколько поразмыслив, мы решили изменить комментарий и указать более подробно характер изменений, а именно – указать, что был добавлен класс Team, который содержит коллекцию разработчиков. Для этого нам необходимо использовать следующую команду:

 git commit --amend -m "Adding class Team that contains collection of Developers"

[master c0b6471] Adding class Team that contains collection of Developers
 Date: Wed Aug 17 19:46:55 2016 +0300
 1 file changed, 51 insertions(+)
 create mode 100644 src/net/proselyte/gittutorial/Team.java

Теперь снова просмотрим историю коммитов:

git log 

commit c0b64715ee2ca606921e7a14a325d3a9c8aa3db7
Author: Eugene Suleimanov 

Date:   Wed Aug 17 19:46:55 2016 +0300

    Adding class Team that contains collection of Developers

commit 11f75b7bc8884203624ba1d552438d57a7c3559d
Author: Eugene Suleimanov 

Date:   Wed Aug 17 19:15:53 2016 +0300

    Adding .gitignore file.

Как мы видим, комментарий крайнего коммита изменился на необходимый

Добавление изменений в репозиторий (Push)

Теперь нам необходимо синхронизировать удаленный репозиторий с нашим локальным.

Для этого нам необходимо выполнить несколько команд:

    1. Создать удаленный репозиторий (в нашем случае мы уже создали репозиторий на Github)
    2. Скопировать ссылку репозитория (в данном случае – https://github.com/proselytear/GitTutorial\
    3. Добавить удаленный репозиторий в Git
git remote add proselyte https://github.com/proselytear/GitTutorial
    1. Выполнить команду – Push
git push proselyte master 

Username for 'https://github.com': proselytear
Password for 'https://[email protected]': 
Counting objects: 34, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (22/22), done.
Writing objects: 100% (34/34), 5.19 KiB | 0 bytes/s, done.
Total 34 (delta 9), reused 0 (delta 0)
remote: Resolving deltas: 100% (9/9), completed with 2 local objects.
To https://github.com/proselytear/GitTutorial
   a0f051a..c0b6471  master -
>
 master

После ввода имени пользователя и пароля, наши данные “заливаются” на удаленный репозиторий.

Теперь наш удаленный репозиторий синхронизирован с нашим локальным.

Сокрытие изменений

Предположим, что пытаемся реализовать новую функцию в нашем приложении. Внезапно нас просят быстро исправить какой-то баг. Для этого мы должны на время прекратить работу над новой функцией. Мы, конечно, можем закоммитить часть проделанной работы, но не коммитить часть работы не является хорошей практикой.

Для таких случаев в Git предусмотрена команда stash, которая отслеживает все файлы, которые были изменены, и сохраняет их в стек незавершенных изменений, которые могут быть подтверждены в любой момент.

Рассмотрим пример:

Мы работает над классом Developer.java и хотим добавить поле команды, к которой он относится:

package net.proselyte.gittutorial;

/**
 * Simple JavaBean domain object that represents a Technology (Spring, JSF, JPA, etc.)
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */

public class Technology {

}

Мы только начали работу над классом и тут нас просят добавить новый класс Technology.java:

package net.proselyte.gittutorial;

/**
 * Simple JavaBean domain object that represents Technology (JSF, JPA, Spring, etc.)
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */

public class Technology {
    private String technologyName;

    public Technology() {
    }

    public Technology(String technologyName) {
        this.technologyName = technologyName;
    }

    public String getTechnologyName() {
        return technologyName;
    }

    public void setTechnologyName(String technologyName) {
        this.technologyName = technologyName;
    }

    @Override
    public String toString() {
        return "Technology: " + this.technologyName;
    }
}

Мы вынуждены отложить работу над классом Developer, но не хотим потерять сделанные изменения.
С этой целью мы используем команду stash:

git stash

Saved working directory and index state WIP on master: f681617 Some style changes.
HEAD is now at f681617 Some style changes.

После добавления нового класса, мы подтверждаем изменения:

git add --all
git commit -m "Adding class Technology"

[master fc5cb38] Adding class Technology
 1 file changed, 2 insertions(+), 4 deletions(-)

Теперь мы хотим вернуться к работе над классом Developer.java. Для этого нам достаточно выполнить следующую команду:

git stash pop 

On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

        modified:   src/net/proselyte/gittutorial/Developer.java

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (b6d4879ab8f01834abf7514acfcc5bfe4a62b5da)

Проверим статус git:

git status 

On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

        modified:   src/net/proselyte/gittutorial/Developer.java

no changes added to commit (use "git add" and/or "git commit -a")

После этого заканчиваем работу над нашим класс Developer.java и делаем новый коммит:

Класс Developer.java

package net.proselyte.gittutorial;

/**
 * Simple JavaBean domain object that represents a Developer.
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */

public class Developer {
    private String firstName;
    private String lastName;
    private String specialty;
    private Integer salary;
    private Team team;

    public Developer() {
    }

    public Developer(String firstName, String lastName, String specialty, Integer salary) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.specialty = specialty;
        this.salary = salary;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getSpecialty() {
        return specialty;
    }

    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }

    public Integer getSalary() {
        return salary;
    }

    public void setSalary(Integer salary) {
        this.salary = salary;
    }

    public Team getTeam() {
        return team;
    }

    public void setTeam(Team team) {
        this.team = team;
    }

    @Override
    public String toString() {
        return "First Name: " + firstName +
                "\nLast Name: " + lastName +
                "\nSpecialty: " + specialty +
                "\nSalary: " + salary +
                "\nTeam: " + team.getTeamName();
    }
}

Подтверждение изменений:

git commit -m "Adding Team property to Developer class"

[master 8d2847d] Adding Team property to Developer class
 2 files changed, 16 insertions(+), 6 deletions(-)

И повторно проверяем статус:

git status 

On branch master
nothing to commit, working directory clean

Управление ветками

Операция branch позволяет создавать новую линию разработки. Мы можем использовать данную операцию для разделения процесса разработки на несколько различных направлений. Например, у нас есть готовый проект с версией 1.0 и мы хотим начать работу над новой версией 2.0. При этом мы хотим, чтобы наша версия 1.0 была неизменной, поэтому имеет смысл вести разработку новой версии отдельно от версии 1.0


Создание новой ветки

Для создания новой ветки нам необходимо использовать следующую команду:

git branch version_2.0

Теперь посмотрим, какие именно ветки есть в нашем проекте:

git branch 
* master
  version_2.0

Звёздочкой отмечена активная ветка master, которая является главной веткой проекта по умолчанию.


Переключение между ветками
Для переключения между ветками используется следующая операция:

 git checkout version_2.0 
Switched to branch 'version_2.0'

Графически это можно представить следующим образом:

Мы можем объединить процесс создания новой ветки и переключения на нее.

Для этого используется следующая команда:

 git checkout -b new_branch
Switched to a new branch 'new_branch'

Проверим, какие ветки есть в проекте и какая из них активна:

git branch 
  master
* new_branch
  version_2.0

Предположим, что мы внесем изменения в ветке new_branch.
Структура проекта в ветке master выглядит так:

Добавим новый класс в ветке new_branch, а именно, добавим новый класс:

Customer.java

package net.proselyte.gittutorial.company;

import java.util.Set;

/**
 * Simple JavaBean domain object that represents a Customer
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */
public class Customer {
    private String name;
    private Set projects;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set getProjects() {
        return projects;
    }

    public void setProjects(Set projects) {
        this.projects = projects;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", projects=" + projects +
                '}';
    }
}

И подтвердим данные изменения:

 git add --all
 git commit -m "Adding class Customer.java"
[new_branch 8d9522c] Adding class Customer.java
 2 files changed, 155 insertions(+), 20 deletions(-)
 create mode 100644 src/net/proselyte/gittutorial/company/Customer.java

Посмотрим структуру проекта в ветке new_branch:

Переключаемся на ветку master:

 git checkout master 
Switched to branch 'master'

И проверим структуру проекта:

Как видим, ветка master осталась неизменной.

Для того, чтобы применить изменения в данной ветке, нам необходимо выполнить слияние ветки master с веткой new_branch.


Слияние веток

Для слияния двух веток используется команда merge.
Переключаемся на ветку, с которой хотим выполнить слияние:

git checkout master 
Switched to branch 'master'

И выполняем следующую команду:

git merge new_branch 
Updating 3dab8e0..ef74ec7
Fast-forward
 src/net/proselyte/gittutorial/company/Customer.java |  38 +++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+), 19 deletions(-)
 create mode 100644 src/net/proselyte/gittutorial/company/Customer.java

Проверим структуру проекта в основной ветке после слияния:


Удаление веток

На данный момент в нашем проекте есть следующие ветки:

git branch 
* master
  new_branch
  version_2.0

Ветки new_branch и version_2.0 нам больше не нужны и мы можем их удалить.
Для удаления веток используется следующая команда:

 git branch -D new_branch 
Deleted branch new_branch (was ef74ec7).

Повторим процесс для ветки version_2.0

git branch -D version_2.0 
Deleted branch version_2.0 (was d27f1a0).

Теперь проверим ветки проекта:

git branch 
* master

На этом мы заканчиваем изучение управления ветками и изучение технологии Git.

results matching ""

    No results matching ""