Какая инструкция git позволяет зафиксировать изменения

Запись изменений в репозиторий

Итак, у вас имеется настоящий Git-репозиторий и рабочая копия файлов для некоторого проекта.
Вам нужно делать некоторые изменения и фиксировать «снимки» состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить.

Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем (отслеживаемые) и нет (неотслеживаемые).
Отслеживаемые файлы — это те файлы, которые были в последнем снимке состояния проекта; они могут быть неизменёнными, изменёнными или подготовленными к коммиту.
Если кратко, то отслеживаемые файлы — это те файлы, о которых знает Git.

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

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

Жизненный цикл состояний файлов

Рисунок 8. Жизненный цикл состояний файлов

Определение состояния файлов

Основной инструмент, используемый для определения, какие файлы в каком состоянии находятся — это команда git status.
Если вы выполните эту команду сразу после клонирования, вы увидите что-то вроде этого:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

Это означает, что у вас чистый рабочий каталог, другими словами — в нём нет отслеживаемых изменённых файлов.
Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были перечислены здесь.
Наконец, команда сообщает вам на какой ветке вы находитесь и сообщает вам, что она не расходится с веткой на сервере.
Пока что это всегда ветка master, ветка по умолчанию; в этой главе это не важно.
В главе Ветвление в Git будут рассмотрены ветки и ссылки более детально.

Примечание

В 2020 году GitHub изменил имя ветки по умолчанию с master на main, другие же git-хостинг платформы последовали этому примеру.
Поэтому, вы можете обнаружить, что ветка по умолчанию для новых репозиториев — main, а не master.
Более того, имя ветки по умолчанию можно изменить (как вы видели в Настройка ветки по умолчанию), поэтому вам может встретиться и другое имя.
При этом Git продолжает использовать имя master, поэтому далее в книге мы используем именно его.

Предположим, вы добавили в свой проект новый файл, простой файл README.
Если этого файла раньше не было, и вы выполните git status, вы увидите свой неотслеживаемый файл вот так:

$ echo 'My Project' > README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README

nothing added to commit but untracked files present (use "git add" to track)

Понять, что новый файл README неотслеживаемый можно по тому, что он находится в секции «Untracked files» в выводе команды status.
Статус Untracked означает, что Git видит файл, которого не было в предыдущем снимке состояния (коммите); Git не станет добавлять его в ваши коммиты, пока вы его явно об этом не попросите.
Это предохранит вас от случайного добавления в репозиторий сгенерированных бинарных файлов или каких-либо других, которые вы и не думали добавлять.
Мы хотели добавить README, так давайте сделаем это.

Отслеживание новых файлов

Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add.
Чтобы начать отслеживание файла README, вы можете выполнить следующее:

Если вы снова выполните команду status, то увидите, что файл README теперь отслеживаемый и добавлен в индекс:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)

    new file:   README

Вы можете видеть, что файл проиндексирован, так как он находится в секции «Changes to be committed».
Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды git add, будет добавлена в историю снимков состояния.
Как вы помните, когда вы ранее выполнили git init, затем вы выполнили git add (файлы) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль.
Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет все файлы из указанного каталога в индекс.

Индексация изменённых файлов

Давайте модифицируем файл, уже находящийся под версионным контролем.
Если вы измените отслеживаемый файл CONTRIBUTING.md и после этого снова выполните команду git status, то результат будет примерно следующим:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README

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

    modified:   CONTRIBUTING.md

Файл CONTRIBUTING.md находится в секции «Changes not staged for commit» — это означает, что отслеживаемый файл был изменён в рабочем каталоге, но пока не проиндексирован.
Чтобы проиндексировать его, необходимо выполнить команду git add.
Это многофункциональная команда, она используется для добавления под версионный контроль новых файлов, для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния.
Вам может быть понятнее, если вы будете думать об этом как «добавить этот контент в следующий коммит», а не как «добавить этот файл в проект».
Выполним git add, чтобы проиндексировать CONTRIBUTING.md, а затем снова выполним git status:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Теперь оба файла проиндексированы и войдут в следующий коммит.
В этот момент вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в CONTRIBUTING.md до коммита.
Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту.
Но давайте-ка ещё раз выполним git status:

$ vim CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

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

    modified:   CONTRIBUTING.md

Что за чёрт?
Теперь CONTRIBUTING.md отображается как проиндексированный и непроиндексированный одновременно.
Как такое возможно?
Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add.
Если вы выполните коммит сейчас, то файл CONTRIBUTING.md попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add, а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit.
Если вы изменили файл после выполнения git add, вам придётся снова выполнить git add, чтобы проиндексировать последнюю версию файла:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Сокращённый вывод статуса

Вывод команды git status довольно всеобъемлющий и многословный.
Git также имеет флаг вывода сокращённого статуса, так что вы можете увидеть изменения в более компактном виде.
Если вы выполните git status -s или git status --short вы получите гораздо более упрощённый вывод:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

Новые неотслеживаемые файлы помечены ?? слева от них, файлы добавленные в отслеживаемые помечены A, отредактированные файлы помечены M и так далее.
В выводе содержится два столбца — в левом указывается статус файла, а в правом модифицирован ли он после этого.
К примеру в нашем выводе, файл README модифицирован в рабочем каталоге, но не проиндексирован, а файл lib/simplegit.rb модифицирован и проиндексирован.
Файл Rakefile модифицирован, проиндексирован и ещё раз модифицирован, таким образом на данный момент у него есть те изменения, которые попадут в коммит, и те, которые не попадут.

Игнорирование файлов

Зачастую, у вас имеется группа файлов, которые вы не только не хотите автоматически добавлять в репозиторий, но и видеть в списках неотслеживаемых.
К таким файлам обычно относятся автоматически генерируемые файлы (различные логи, результаты сборки программ и т. п.).
В таком случае, вы можете создать файл .gitignore. с перечислением шаблонов соответствующих таким файлам.
Вот пример файла .gitignore:

$ cat .gitignore
*.[oa]
*~

Первая строка предписывает Git игнорировать любые файлы заканчивающиеся на «.o» или «.a» — объектные и архивные файлы, которые могут появиться во время сборки кода.
Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (~), которая используется во многих текстовых редакторах, например Emacs, для обозначения временных файлов.
Вы можете также включить каталоги log, tmp или pid; автоматически создаваемую документацию; и т. д. и т. п.
Хорошая практика заключается в настройке файла .gitignore до того, как начать серьёзно работать, это защитит вас от случайного добавления в репозиторий файлов, которых вы там видеть не хотите.

К шаблонам в файле .gitignore применяются следующие правила:

  • Пустые строки, а также строки, начинающиеся с #, игнорируются.

  • Стандартные шаблоны являются глобальными и применяются рекурсивно для всего дерева каталогов.

  • Чтобы избежать рекурсии используйте символ слеш (/) в начале шаблона.

  • Чтобы исключить каталог добавьте слеш (/) в конец шаблона.

  • Можно инвертировать шаблон, использовав восклицательный знак (!) в качестве первого символа.

Glob-шаблоны представляют собой упрощённые регулярные выражения, используемые командными интерпретаторами.
Символ (*) соответствует 0 или более символам; последовательность [abc] — любому символу из указанных в скобках (в данном примере a, b или c); знак вопроса (?) соответствует одному символу; и квадратные скобки, в которые заключены символы, разделённые дефисом ([0-9]), соответствуют любому символу из интервала (в данном случае от 0 до 9).
Вы также можете использовать две звёздочки, чтобы указать на вложенные каталоги: a/**/z соответствует a/z, a/b/z, a/b/c/z, и так далее.

Вот ещё один пример файла .gitignore:

# Исключить все файлы с расширением .a
*.a

# Но отслеживать файл lib.a даже если он подпадает под исключение выше
!lib.a

# Исключить файл TODO в корневом каталоге, но не файл в subdir/TODO
/TODO

# Игнорировать все файлы в каталоге build/
build/

# Игнорировать файл doc/notes.txt, но не файл doc/server/arch.txt
doc/*.txt

# Игнорировать все .txt файлы в каталоге doc/
doc/**/*.txt

Подсказка

GitHub поддерживает довольно полный список примеров .gitignore файлов для множества проектов и языков https://github.com/github/gitignore это может стать отправной точкой для .gitignore в вашем проекте.

Примечание

В простейшем случае репозиторий будет иметь один файл .gitignore в корневом каталоге, правила из которого будут рекурсивно применяться ко всем подкаталогам.
Так же возможно использовать .gitignore файлы в подкаталогах.
Правила из этих файлов будут применяться только к каталогам, в которых они находятся.
Например, репозиторий исходного кода ядра Linux содержит 206 файлов .gitignore.

Детальное рассмотрение использования нескольких .gitignore файлов выходит за пределы этой книги; детали доступны в справке man gitignore.

Просмотр индексированных и неиндексированных изменений

Если результат работы команды git status недостаточно информативен для вас — вам хочется знать, что конкретно поменялось, а не только какие файлы были изменены — вы можете использовать команду git diff.
Позже мы рассмотрим команду git diff подробнее; вы, скорее всего, будете использовать эту команду для получения ответов на два вопроса: что вы изменили, но ещё не проиндексировали, и что вы проиндексировали и собираетесь включить в коммит.
Если git status отвечает на эти вопросы в самом общем виде, перечисляя имена файлов, git diff показывает вам непосредственно добавленные и удалённые строки — патч как он есть.

Допустим, вы снова изменили и проиндексировали файл README, а затем изменили файл CONTRIBUTING.md без индексирования.
Если вы выполните команду git status, вы опять увидите что-то вроде:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

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

    modified:   CONTRIBUTING.md

Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff без аргументов:

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if you patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's

Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса.
Результат показывает ещё не проиндексированные изменения.

Если вы хотите посмотреть, что вы проиндексировали и что войдёт в следующий коммит, вы можете выполнить git diff --staged.
Эта команда сравнивает ваши проиндексированные изменения с последним коммитом:

$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project

Важно отметить, что git diff сама по себе не показывает все изменения сделанные с последнего коммита — только те, что ещё не проиндексированы.
Такое поведение может сбивать с толку, так как если вы проиндексируете все свои изменения, то git diff ничего не вернёт.

Другой пример: вы проиндексировали файл CONTRIBUTING.md и затем изменили его, вы можете использовать git diff для просмотра как проиндексированных изменений в этом файле, так и тех, что пока не проиндексированы.
Если наше окружение выглядит вот так:

$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   CONTRIBUTING.md

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

    modified:   CONTRIBUTING.md

Используйте git diff для просмотра непроиндексированных изменений

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
 ## Starter Projects

 See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line

а так же git diff --cached для просмотра проиндексированных изменений (--staged и --cached синонимы):

$ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if you patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's

Примечание

Git Diff во внешних инструментах

Мы будем продолжать использовать команду git diff различными способами на протяжении всей книги.
Существует ещё один способ просматривать эти изменения, если вы предпочитаете графический просмотр или внешнюю программу просмотра различий, вместо консоли.
Выполнив команду git difftool вместо git diff, вы сможете просмотреть изменения в файле с помощью таких программ как emerge, vimdiff и других (включая коммерческие продукты).
Выполните git difftool --tool-help чтобы увидеть какие из них уже установлены в вашей системе.

Коммит изменений

Теперь, когда ваш индекс находится в таком состоянии, как вам и хотелось, вы можете зафиксировать свои изменения.
Запомните, всё, что до сих пор не проиндексировано — любые файлы, созданные или изменённые вами, и для которых вы не выполнили git add после редактирования — не войдут в этот коммит.
Они останутся изменёнными файлами на вашем диске.
В нашем случае, когда вы в последний раз выполняли git status, вы видели что всё проиндексировано, и вот, вы готовы к коммиту.
Простейший способ зафиксировать изменения — это набрать git commit:

Эта команда откроет выбранный вами текстовый редактор.

Примечание

Редактор устанавливается переменной окружения EDITOR — обычно это vim или emacs, хотя вы можете установить любой другой с помощью команды git config --global core.editor, как было показано в главе Введение).

В редакторе будет отображён следующий текст (это пример окна Vim):

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
#	new file:   README
#	modified:   CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C

Вы можете видеть, что комментарий по умолчанию для коммита содержит закомментированный результат работы команды git status и ещё одну пустую строку сверху.
Вы можете удалить эти комментарии и набрать своё сообщение или же оставить их для напоминания о том, что вы фиксируете.

Примечание

Для ещё более подробного напоминания, что же именно вы поменяли, можете передать аргумент -v в команду git commit.
Это приведёт к тому, что в комментарий будет также помещена дельта/diff изменений, таким образом вы сможете точно увидеть все изменения которые вы совершили.

Когда вы выходите из редактора, Git создаёт для вас коммит с этим сообщением, удаляя комментарии и вывод команды diff.

Есть и другой способ — вы можете набрать свой комментарий к коммиту в командной строке вместе с командой commit указав его после параметра -m, как в следующем примере:

$ git commit -m "Story 182: fix benchmarks for speed"
[master 463dc4f] Story 182: fix benchmarks for speed
 2 files changed, 2 insertions(+)
 create mode 100644 README

Итак, вы создали свой первый коммит!
Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит (master), какая контрольная сумма SHA-1 у этого коммита (463dc4f), сколько файлов было изменено, а также статистику по добавленным/удалённым строкам в этом коммите.

Запомните, что коммит сохраняет снимок состояния вашего индекса.
Всё, что вы не проиндексировали, так и висит в рабочем каталоге как изменённое; вы можете сделать ещё один коммит, чтобы добавить эти изменения в репозиторий.
Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить или с которым можно сравнить текущее состояние.

Игнорирование индексации

Несмотря на то, что индекс может быть удивительно полезным для создания коммитов именно такими, как вам и хотелось, он временами несколько сложнее, чем вам нужно в процессе работы.
Если у вас есть желание пропустить этап индексирования, Git предоставляет простой способ.
Добавление параметра -a в команду git commit заставляет Git автоматически индексировать каждый уже отслеживаемый на момент коммита файл, позволяя вам обойтись без git add:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'Add new benchmarks'
[master 83e38c7] Add new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

Обратите внимание, что в данном случае перед коммитом вам не нужно выполнять git add для файла CONTRIBUTING.md, потому что флаг -a включает все файлы.
Это удобно, но будьте осторожны: флаг -a может включить в коммит нежелательные изменения.

Удаление файлов

Для того чтобы удалить файл из Git, вам необходимо удалить его из отслеживаемых файлов (точнее, удалить его из вашего индекса) а затем выполнить коммит.
Это позволяет сделать команда git rm, которая также удаляет файл из вашего рабочего каталога, так что в следующий раз вы не увидите его как «неотслеживаемый».

Если вы просто удалите файл из своего рабочего каталога, он будет показан в секции «Changes not staged for commit» (изменённые, но не проиндексированные) вывода команды git status:

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    PROJECTS.md

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

Затем, если вы выполните команду git rm, удаление файла попадёт в индекс:

$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    PROJECTS.md

После следующего коммита файл исчезнет и больше не будет отслеживаться.
Если вы изменили файл и уже проиндексировали его, вы должны использовать принудительное удаление с помощью параметра -f.
Это сделано для повышения безопасности, чтобы предотвратить ошибочное удаление данных, которые ещё не были записаны в снимок состояния и которые нельзя восстановить из Git.

Другая полезная штука, которую вы можете захотеть сделать — это удалить файл из индекса, оставив его при этом в рабочем каталоге.
Другими словами, вы можете захотеть оставить файл на жёстком диске, но перестать отслеживать изменения в нём.
Это особенно полезно, если вы забыли добавить что-то в файл .gitignore и по ошибке проиндексировали, например, большой файл с логами, или кучу промежуточных файлов компиляции.
Чтобы сделать это, используйте опцию --cached:

В команду git rm можно передавать файлы, каталоги или шаблоны.
Это означает, что вы можете сделать что-то вроде:

Обратите внимание на обратный слеш (\) перед *.
Он необходим из-за того, что Git использует свой собственный обработчик имён файлов вдобавок к обработчику вашего командного интерпретатора.
Эта команда удаляет все файлы, имеющие расширение .log и находящиеся в каталоге log/.
Или же вы можете сделать вот так:

Эта команда удаляет все файлы, имена которых заканчиваются на ~.

Перемещение файлов

В отличие от многих других систем контроля версий, Git не отслеживает перемещение файлов явно.
Когда вы переименовываете файл в Git, в нём не сохраняется никаких метаданных, говорящих о том, что файл был переименован.
Однако, Git довольно умён в плане обнаружения перемещений постфактум — мы рассмотрим обнаружение перемещения файлов чуть позже.

Таким образом, наличие в Git команды mv выглядит несколько странным.
Если вам хочется переименовать файл в Git, вы можете сделать что-то вроде:

$ git mv file_from file_to

и это отлично сработает.
На самом деле, если вы выполните что-то вроде этого и посмотрите на статус, вы увидите, что Git считает, что произошло переименование файла:

$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Однако, это эквивалентно выполнению следующих команд:

$ mv README.md README
$ git rm README.md
$ git add README

Git неявно определяет, что произошло переименование, поэтому неважно, переименуете вы файл так или используя команду mv.
Единственное отличие состоит лишь в том, что mv — одна команда вместо трёх — это функция для удобства.
Важнее другое — вы можете использовать любой удобный способ для переименования файла, а затем воспользоваться командами add или rm перед коммитом.

История развития систем контроля версий берет начало в далеком 1972 году, когда компания Bell Labs разработала первую систему управления версиями под названием Source Code Control System, или сокращенно SCCS. Программа была популярна вплоть до 1982 года, когда была разработана новая система под названием Revision Control System (RCS). Дальнейшее развитие систем контроля версий продолжилось в 2000 году, когда были выпущены сразу две программы: Subversion (более известная под именем SVN) и BitKeeper. Обе программы были выпущены с целью заменить морально устаревшие утилиты, такие как CVS и RCS. Однако настоящий прорыв произошел в 2005 году, когда появился Git, который снискал популярность среди разработчиков и IT-индустрии в целом. Сегодня Git стал инструментом, де-факто выступающим в качестве основного инструмента контроля версий, а также послужил основой для создания таких веб-сервисов, как GitHub, GitLab и Bitbucket.

В Git используется контентно-адресуемая система для хранения данных, основанная на адресации по контрольной сумме (она же хеш-сумма). Хеш-сумма выступает в роли уникального идентификатора содержимого пользовательских данных — иными словами, адресом каждого объекта является хеш его содержимого.

Git осуществляет хранение файлов, используя формат снимков. На практике это выглядит следующим образом: каждый раз, внося изменения, Git фиксирует каждое внесенное изменение в файл и сохраняет ссылку на ранее созданный снимок. Если в файлы не вносились изменения, Git не будет фиксировать их и вместо этого сохранит ссылку на предыдущую версию файла.

Git оперирует тремя типами объектов: файл, дерево и «коммит» (commit). В объект «файл» вносятся необходимые изменения; дерево — иерархия файлов в репозитории, которая создает связь между директориями и содержащимися в них файлами. Под «коммитом» понимают метод фиксации изменений в файлах.

В Git используются два типа репозиториев: локальный и удаленный. Локальный репозиторий хранится на устройстве пользователя. Удаленный репозиторий располагается на удаленном устройстве — например на отдельном компьютере. Большинство действий в Git выполняются локально, так как это не централизованная система.

Установка Git

Git является кроссплатформенным инструментом — поддерживается установка на операционные системы Windows, Linux, macOS. Несмотря на то, что Git традиционно используют в командной строке (что неудивительно, так как инструмент разрабатывался для использования в терминале устройства), существует большое количество разнообразных программ с графической оболочкой под все поддерживаемые операционные системы. Существуют как бесплатные, так и платные программы.

Для операционных систем Linux/Unix установить Git можно, используя официальные репозитории дистрибутива. Отдельно для Ubuntu создан официальный репозиторий от разработчиков, который предоставляет последнюю актуальную версию Git. Процесс инсталляции Git на различные дистрибутивы Linux описана в инструкции, доступной по ссылке.

Для пользователей Windows присутствуют разнообразные программы с графическим интерфейсом, включая такие, как GitHub Desktop, Sourcetree, GitKraken Desktop. С полным списком программ для Windows можно ознакомиться по ссылке.

Для пользователей macOS можно воспользоваться менеджером пакетов Homebrew или MacPorts, а также одной из десятков различных программ с графической оболочкой, включая такие, как GitUp, Gitfox, SnailGit, GitFinder и многие другие. Ознакомиться с инструкцией по установке Git на macOS можно по ссылке.

Отдельно стоит выделить, что в некоторых IDE, например, VS Code, Xcode, PyCharm, PhpStorm, WebStorm, Git уже предустановлен и его можно использовать “из-коробки”.

vds

Основы Git

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

Предварительная настройка

Настроим базовые параметры Git, а именно зададим имя пользователя, а также адрес электронной почты. Данная информация будет отображена в каждом коммите для установления личности пользователя. Как правило, без настройки имени и адреса электронной почты нельзя взаимодействовать с Git и его функционалом. Зададим имя пользователя. выполнив в терминале команду (где Alex — это имя пользователя):

git config --global user.name "Alex"

Далее зададим адрес электронной почты, используя команду (где alex_mailbox@mail.com — это адрес электронной почты пользователя):

git config --global user.email alex_mailbox@mail.com

Если вы не хотите указывать свои настоящие данные, то можно задать любые данные, какие посчитаете нужными.

Создание репозитория Git

Как уже было упомянуто ранее, Git использует объект под названием репозиторий, представляющий собой виртуальное хранилище файлов. Со стороны пользователя репозиторий представляет собой директорию, наподобие той, что используется в операционных системах. В репозитории, помимо хранения файлов, также хранятся объекты Git — коммиты, ветки, история внесенных действий. В Git можно создать как новый репозиторий, так и создать репозиторий из уже существующей папки. Рассмотрим оба варианта на практике.

Создадим новую директорию:

mkdir stage-file-for-futher-projeect

Далее переходим в созданную директорию:

cd  stage-file-for-futher-projeect

И выполним команду:

git init

1

При выполнении git init в пустой директории команда сообщит о том, что репозиторий был успешно создан, однако он не содержит в себе никаких файлов. При создании нового репозитория в его корне будет создана скрытая папка (папка, имя которой начинается с символа точки) с именем .git. Внутри папки .git расположены конфигурационные файлы Git и структура репозитория:

2

Копирование Git-репозитория

Также присутствует возможность скопировать уже существующий репозиторий. Такие репозитории называются удаленными. Обычно такую возможность используют при работе с такими веб-сервисами, как GitHub и GitLab. Чтобы скопировать удаленный репозиторий, необходимо знать его URL. Для скачивания используют команду git clone. В приведенном примере мы скачаем репозиторий с исходным кодом утилиты curl:

git clone https://github.com/curl/curl.git

3

После скачивания нам будет доступна папка с исходным кодом curl:

4

Состояние репозитория Git

Одной из главных функциональных особенной Git является состояние (или статус) репозитория. Статус используется не только для проверки состояния репозитория, но и для того, чтобы узнать статус индексного раздела. Рассмотрим данную команду, используя репозиторий curl, скачанный ранее. При выполнение команды git status после того, как был скачан репозиторий, в ответ будет выведено сообщение:

5

Git сообщил, что в качестве основной ветки в репозитории используется ветка master, которая находится в одинаковом состоянии и синхронизирована с удаленной веткой master.

Теперь попробуем создать в текущем каталоге curl новый файл:

touch new-test-file.txt

После создания файла выведем статус репозитория:

git status

6

На скриншоте выше в репозитории появился новый статус, который сообщает о том, что были обнаружены неотслеживаемые изменения. Git сообщил нам об обнаружении нового файла, которого ранее не было в репозитории. Также было выведено сообщение, что Git не будет отслеживать данный файл, пока он не будет добавлен в индексную область Git. Индекс представляет собой область, в которую сохраняются все добавляемые файлы перед тем, как они будут добавлены в репозиторий. Чтобы добавить файл в индекс, воспользуемся командой:

git add new-test-file.txt

Статус репозитория был изменен. Проверим:

git status

7

Как можно увидеть, у репозитория появился новый статус, означающий добавление в индекс нового файла. Следующим шагом его можно “закоммитить”. Выполним коммит:

git commit -m "Added new-test-file.txt"

8

и убедимся что статус репозитория был также изменен:

git status

9

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

Добавление файлов

Чтобы Git начал отслеживать файлы, находящиеся в рабочем каталоге, их необходимо переместить в индексную область. Для этого используется команда git add. Например, вот так можно добавить один файл:

git add file1.txt

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

git add .

git add поддерживает работу с символами регулярных выражений.

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

git add *.txt

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

git reset file2.txt

Работа с коммитами

Все внесенные изменения в репозиторий, включая добавление файлов, необходимо фиксировать. Это реализуется с помощью команды git commit. С ее помощью можно зафиксировать изменения, внесенные в репозиторий. Также коммиты можно использовать как инструмент для отката, чтобы вернуться на последний или нужный коммит. Выполнить коммит можно только тогда, когда добавлены все файлы. 

Коммит снабжается сообщением (комментарием), в котором указывается, что за изменения были внесены. Выполним коммит, добавив к нему сообщение:

git commit -m "Added first file"

10

История коммитов

Git ведет историю коммитов. Для просмотра истории воспользуйтесь командой git log:

git log

11

Работа с ветками

Одна из самых мощных функций в Git — это ветвление. При помощи процедуры ветвления можно отделиться от основной версии проекта и начать работу в новом окружение, не затрагивая файлы основной ветки. Простыми словами, при помощи веток мы создаем копию файлов, присутствующих в репозитории, и изолируем их в новой ветке. Обратите внимание, что изменения, сделанные в одной ветке, не будут перенесены в другую ветку, пока вы сами не сделаете это вручную (про merge request мы поговорим в следующем разделе).

При помощи функционала веток можно протестировать новую версию проекта, не изменяя файлы в основной ветке. 

Создадим новую ветку new_function:

git branch new_function

 Выведем все доступные ветки:

git branch

12

git branch выводит только те ветки, которые доступны локально. Для вывода всех веток (локальных и удаленных) необходимо использовать:

git branch -a

 Переключимся на ранее созданную ветку:

git checkout new_function

13

Создадим новый файл:

touch new-branch-file.txt

И добавим его:

git add new-branch-file.txt

Выполняем коммит:

git commit -m "Added new-branch-file.txt file"

Файл будет отображаться только в ветке new_function:

14

Убедимся, переключившись обратно на ветку main:

git checkout main

15

Как можно увидеть, ранее созданный файл new-branch-file.txt в ветке new_function недоступен в ветке main.

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

Ветки можно удалять. Для этого используется команда git branch -d. При удалении ветки необходимо учитывать, что нельзя удалить текущую ветку. При попытке удаления текущей ветки Git вернет ошибку:

git branch -d new_function

16

Чтобы удалить текущую ветку, необходимо переключиться на любую другую доступную ветку, например, на ветку main:

git checkout main

Далее ветку можно удалить:

git branch -d new_function

Image18

Если удаляемая ветка не была объединена, то при удаление такой ветки будет выведено предупреждение:

18

Чтобы удалить такую ветку, необходимо использовать опцию -D:

git branch -D new_function

19

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

Особенностью использования веток является изоляция внесенных изменений — изменения доступные в одной ветке автоматически не появляются в других. В Git существует процесс слияния двух веток, который называется merge request. При слиянии все изменения, которые были внесены в одну ветку, переносятся в другую. Рассмотрим на примере слияния изменений из ветки new_function в ветку main. 

1) Создаем новую ветку:

git branch new_function

И переключаемся на нее:

git checkout new_function

2) Создаем новый файл:

touch new-branch-file.txt

3) Добавляем созданный файл в индекс:

git add new-branch-file.txt

4) Делаем коммит:

git commit -m "Added new-branch-file.txt file"

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

git checkout main

6) Выполняем merge request:

git merge new_function

20

Теперь ранее внесенные изменения в ветке new_function появились в ветке main:

21

Работа с удаленными репозиториями Git

Ранее мы работали только с локальными репозиториями. Но Git поддерживает работу и с удаленными репозиториями. Удаленный репозиторий — это репозиторий, который хранится на сервере. 

Подключение к удаленному репозиторию

Локальный репозиторий можно подключить к удаленному репозиторию с помощью git remote add. Рассмотрим подключение на примере сервиса GitHub.

1) Открываем GitHub, авторизуемся в аккаунте и создаем новый репозиторий:

22

2) Возвращаемся на сервер, переходим в локальный репозиторий и подключаем его к удаленному:

git remote add origin https://github.com/AlexFromMoscow6/demo-repo.git

Отправка изменений в удаленный репозиторий

Отправим ранее добавленные изменения в удаленный репозиторий при помощи git push: 

git push -u origin main

23

При использование команды git push система запросит логин и пароль от учетной записи того сервиса, на котором хранится репозиторий. Ранее GitHub использовал пароли для процесса аутентификации, однако теперь вместо паролей используются только токены. Также важным моментом является то, что при использование GitHub, вместо пароля от учетной записи необходимо ввести токен. Если у вас отсутствует токен, то его необходимо создать. Инструкция по созданию токена приведена по ссылке.

Переходим в GitHub и смотрим, чтобы файлы были опубликованы:

24

Получение изменений из удаленного репозитория

Чтобы поддерживать скачанный удаленный репозиторий в актуальном состоянии, используется команда git pull, которая соединятся с удаленным репозиторием и запрашивает изменения. Если изменения присутствуют, Git скачает их.

Минимальный набор команд git для начала работы с проектом

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

1) Инициализируем репозиторий Git:

git init

25

2) Добавляем все файлы (символ точки), которые располагаются в репозитории:

git add .

26

3) Делаем коммит:

git commit -m "Initial commit"

27

4) Переходим в веб-версию GitHub, авторизуемся в своем аккаунте и создаем новый репозиторий (зеленая кнопка New):

28

Задаем имя репозиторию и выбираем тип репозитория (публичный, который будет доступен для всех пользователей, или приватный, доступ до которого будет только у владельца репозитория; доступ для остальных пользователей необходимо будет настраивать отдельно):

29

5) Возвращаемся в терминал и подключаем наш ранее созданный локальный репозиторий к удаленному: 

git remote add origin https://github.com/AlexFromMoscow6/simple-js-app.git

6) Наконец, отправляем изменения в удаленный репозиторий:

git push -u origin main

30

Далее возвращаемся на страницу репозитория в GitHub и проверяем, что все файлы были добавлены в репозиторий:

31

Сегодня мы подробно познакомились с системой контроля версий Git. Git является мощным инструментом с большим функционалом, который одинаково хорошо работает как с небольшими, так и объемными проектами. При помощи Git можно легко отслеживать внесенные изменения, а также откатиться назад.

Git Commit — это команда в системе контроля версий Git, которая фиксирует изменения в репозитории. Когда пользователь использует ее, создается «снимок» (коммит) текущего состояния проекта, включая все внесенные изменения. Каждое такое сохранение имеет уникальный идентификатор, который позволяет отслеживать историю изменений в проекте. Коммиты в Git дают возможность откатить проект к предыдущим версиям, сравнивать изменения, объединять ветки и выполнять другие операции управления исходным кодом.

Что такое commit?

Коммит в Git — это одна из основных операций в системе контроля версий Git. Commit (в переводе с английского «зафиксировать») означает сохранение изменений в файловой системе и создание новой ревизии, которая отражает состояние проекта на данный момент.

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

Сообщение коммита — это важная часть процесса, так как оно описывает, какие изменения были внесены и почему. Хорошее сообщение коммита является ясным, кратким и информативным, чтобы другие разработчики могли понять изменения без необходимости анализировать код.

Для понимания, что такое коммит, рассмотрим основные элементы такого сохранения:

  • Идентификатор. Каждый коммит имеет уникальный хеш-код. Он формируется на основе содержимого коммита и его «родителей», что обеспечивает ему уникальность и неизменяемость.
  • Автор и метаинформация. Коммит содержит информацию об авторе, включая имя и адрес электронной почты. Также может быть указан коммитер (человек, сделавший последнее сохранение) — например, если происходит изменение прав собственности на код. Помимо этого, метаинформация содержит дату и время создания коммита и сообщение-комментарий, в котором разработчик описывает внесенные изменения.
  • Содержимое файлов. Коммит включает снимок текущего состояния репозитория, в том числе все измененные, добавленные или удаленные данные. Внутри него хранится информация о каждом файле, включая его имя, содержимое и режим доступа.
  • Дополнительные метаданные. Внутри коммита могут храниться теги, указывающие на специфические моменты в истории репозитория, или ссылки на другие ветки.

Каждый коммит, кроме первого в репозитории, имеет один или несколько «родительских», то есть предшествующих ему. В Git коммиты формируют дерево или граф, где каждый из них указывает на одного или нескольких «родительских». Оно позволяет отслеживать историю изменений и перемещаться по разным версиям кода.

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

После добавления файлов в индекс можно использовать команду git commit, чтобы сохранить изменения. Git откроет редактор, где можно написать сообщение о внесенных изменениях. Обычно оно содержит краткое описание того, что именно было сделано разработчиком и как теперь работает по-другому.

Как изменить коммит в Git?

При работе с Git часто возникает необходимость изменить последний коммит. Это может произойти по разным причинам: например, вы забыли добавить какой-то файл в Git, ввели неправильное сообщение и т.д. Изменить коммит в Git можно следующим способом:

  • Команда git commit -amend. Если нужно изменить последний коммит, но вы не внесли новые изменения, введите команду git commit -amend в терминале. Она открывает текстовый редактор по умолчанию, где можно отредактировать сообщение коммита. После внесения изменений просто сохраните файл. Если вам нужно добавить новые правки к последнему коммиту, сначала внесите их в свои файлы, затем выполните команду git add, чтобы указать их в индексе. Затем запустите команду git commit -amend, которая объединит новые правки с предыдущим коммитом. 
  • Команда git rebase -i. Для изменения коммита, который не является последним, введите команду git rebase -i HEAD~N, где N — количество сохранений до того, который вы хотите изменить. После выполнения этой команды откроется текстовый редактор, где вы увидите список коммитов. Найдите нужное вам сохранение и замените слово «pick» (выполнять) перед коммитом на «edit» (редактировать). Сохраните файл и закройте редактор. Теперь Git автоматически переключится на коммит, который вы хотите скорректировать. Внесите нужные изменения в ваш файл, затем используйте команду git add, чтобы добавить изменения в индекс, а затем git commit -amend, чтобы исправить коммит. 

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

Преимущества коммитов

Отслеживание изменений. Коммиты позволяют точно отслеживать изменения, внесенные в проект. Благодаря уникальным идентификаторам и дереву коммитов можно легко найти, кто, когда и что изменил в файле или проекте.

Легкое сравнение версий. Пользователь может сравнить два коммита или версии проекта, чтобы увидеть различия между ними. Это упрощает обнаружение ошибок или просмотр внесенных изменений.

Работа в коллективе. Коммиты обеспечивают эффективное сотрудничество в команде разработчиков. С помощью разных веток можно работать над разными функциями параллельно и затем объединить изменения с другими разработчиками.

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

Быстрый доступ к предыдущим версиям. Благодаря истории коммитов можно быстро получить доступ к предыдущим версиям проекта. Разработчик имеет возможность анализировать изменения и возвращаться к старым версиям кода, что может быть полезно для отладки или воспроизведения более стабильных состояний проекта.

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

Хранение и отслеживание конфигурации. С помощью команды commit можно сохранять и отслеживать конфигурационные файлы и настройки проекта. Это особенно полезно при развертывании проекта на разных серверах или устройствах, так как можно быстро переключаться между различными конфигурациями.

Недостатки коммитов

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

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

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

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

Таким образом, коммит — это удобная функция репозитория Git, упрощающая контроль над внесением изменений в проект. С ее помощью можно сохранять, отслеживать и анализировать проделанную работу, а также, если это необходимо, устранять нежелательные изменения кода. Хотя этот инструмент имеет свои слабые стороны, он существенно облегчает выполнение задач как одному разработчику, так и команде. 

В последние годы популярность git демонстрирует взрывной рост. Эта система контроля версий используется различными проектами с открытым исходным кодом.

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

Основы

Git — это набор консольных утилит, которые отслеживают и фиксируют изменения в файлах (чаще всего речь идет об исходном коде программ, но вы можете использовать его для любых файлов на ваш вкус). Изначально Git был создан Линусом Торвальдсом при разработке ядра Linux. Однако инструмент так понравился разработчикам, что в последствии, он получил широкое распространение и его стали использовать в других проектах. С его помощью вы можете сравнивать, анализировать, редактировать, сливать изменения и возвращаться назад к последнему сохранению. Этот процесс называется контролем версий.

Для чего он нужен? Ну во-первых, чтобы отследить изменения, произошедшие с проектом, со временем. Проще говоря, мы можем посмотреть как менялись файлы программы, на всех этапах разработки и при необходимости вернуться назад и что-то отредактировать. Часто бывают ситуации, когда, во вполне себе работающий код, вам нужно внести определенные правки или улучшить какой-то функционал, по желанию заказчика. Однако после внедрения нововведений, вы с ужасом понимаете, что все сломалось. У вас начинается судорожно дергаться глаз, а в воздухе повисает немой вопрос: “Что делать?” Без системы контроля версий, вам надо было бы долго напряженно просматривать код, чтобы понять как было до того, как все перестало работать. С Гитом же, все что нужно сделать — это откатиться на коммит назад.

Во-вторых он чрезвычайно полезен при одновременной работе нескольких специалистов, над одним проектом. Без Гита случится коллапс, когда разработчики, скопировав весь код из главной папки и сделав с ним задуманное, попытаются одновременно вернуть весь код обратно.
Git является распределенным, то есть не зависит от одного центрального сервера, на котором хранятся файлы. Вместо этого он работает полностью локально, сохраняя данные в директориях на жестком диске, которые называются репозиторием. Тем не менее, вы можете хранить копию репозитория онлайн, это сильно облегчает работу над одним проектом для нескольких людей. Для этого используются сайты вроде github и bitbucket.

Установка

Установить git на свою машину очень просто:

  • Linux — нужно просто открыть терминал и установить приложение при помощи пакетного менеджера вашего дистрибутива. Для Ubuntu команда будет выглядеть следующим образом:
    sudo apt-get install git
  • Windows — мы рекомендуем git for windows, так как он содержит и клиент с графическим интерфейсом, и эмулятор bash.
  • OS X — проще всего воспользоваться homebrew. После его установки запустите в терминале:
    brew install git

Если вы новичок, клиент с графическим интерфейсом(например GitHub Desktop и Sourcetree) будет полезен, но, тем не менее, знать команды очень важно.

Настройка

Итак, мы установили git, теперь нужно добавить немного настроек. Есть довольно много опций, с которыми можно играть, но мы настроим самые важные: наше имя пользователя и адрес электронной почты. Откройте терминал и запустите команды:

git config --global user.name "My Name"
git config --global user.email myEmail@example.com

Теперь каждое наше действие будет отмечено именем и почтой. Таким образом, пользователи всегда будут в курсе, кто отвечает за какие изменения — это вносит порядок.
Git хранит весь пакет конфигураций в файле .gitconfig, находящемся в вашем локальном каталоге. Чтобы сделать эти настройки глобальными, то есть применимыми ко всем проектам, необходимо добавить флаг –global. Если вы этого не сделаете, они будут распространяться только на текущий репозиторий.
Для того, чтобы посмотреть все настройки системы, используйте команду:

git config --list

Для удобства и легкости зрительного восприятия, некоторые группы команд в Гит можно выделить цветом, для этого нужно прописать в консоли:

git config --global color.ui true
git config --global color.status auto
git config --global color.branch auto

Если вы не до конца настроили систему для работы, в начале своего пути — не беда. Git всегда подскажет разработчику, если тот запутался, например:

  1. Команда git —help — выводит общую документацию по git
  2. Если введем git log —help — он предоставит нам документацию по какой-то определенной команде (в данном случае это — log)
  3. Если вы вдруг сделали опечатку — система подскажет вам нужную команду
  4. После выполнения любой команды — отчитается о том, что вы натворили
  5. Также Гит прогнозирует дальнейшие варианты развития событий и всегда направит разработчика, не знающего, куда двигаться дальше

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

Создание нового репозитория

Как мы отметили ранее, git хранит свои файлы и историю прямо в папке проекта. Чтобы создать новый репозиторий, нам нужно открыть терминал, зайти в папку нашего проекта и выполнить команду init. Это включит приложение в этой конкретной папке и создаст скрытую директорию .git, где будет храниться история репозитория и настройки.
Создайте на рабочем столе папку под названием git_exercise. Для этого в окне терминала введите:

$ mkdir Desktop/git_exercise/
$ cd Desktop/git_exercise/
$ git init

Командная строка должна вернуть что-то вроде:

Initialized empty Git repository in /home/user/Desktop/git_exercise/.git/

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

Определение состояния

status — это еще одна важнейшая команда, которая показывает информацию о текущем состоянии репозитория: актуальна ли информация на нём, нет ли чего-то нового, что поменялось, и так далее. Запуск git status на нашем свежесозданном репозитории должен выдать:

$ git status
On branch master
Initial commit
Untracked files:
(use "git add ..." to include in what will be committed)
hello.txt

Сообщение говорит о том, что файл hello.txt неотслеживаемый. Это значит, что файл новый и система еще не знает, нужно ли следить за изменениями в файле или его можно просто игнорировать. Для того, чтобы начать отслеживать новый файл, нужно его специальным образом объявить.

Подготовка файлов

В git есть концепция области подготовленных файлов. Можно представить ее как холст, на который наносят изменения, которые нужны в коммите. Сперва он пустой, но затем мы добавляем на него файлы (или части файлов, или даже одиночные строчки) командой add и, наконец, коммитим все нужное в репозиторий (создаем слепок нужного нам состояния) командой commit.
В нашем случае у нас только один файл, так что добавим его:

$ git add hello.txt

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

$ git add -A

Проверим статус снова, на этот раз мы должны получить другой ответ:

$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: hello.txt

Файл готов к коммиту. Сообщение о состоянии также говорит нам о том, какие изменения относительно файла были проведены в области подготовки — в данном случае это новый файл, но файлы могут быть модифицированы или удалены.

Фиксация изменений

Как сделать коммит

Представим, что нам нужно добавить пару новых блоков в html-разметку (index.html) и стилизовать их в файле style.css. Для сохранения изменений, их необходимо закоммитить. Но сначала, мы должны обозначить эти файлы для Гита, при помощи команды git add, добавляющей (или подготавливающей) их к коммиту. Добавлять их можно по отдельности:

git add index.html
git add css/style.css

или вместе — всё сразу:

git add .

Конечно добавлять всё сразу удобнее, чем прописывать каждую позицию отдельно. Однако, тут надо быть внимательным, чтобы не добавить по ошибке ненужные элементы. Если же такое произошло изъять оттуда ошибочный файл можно при помощи команды

git reset:
git reset css/style.css

Теперь создадим непосредственно сам коммит

git commit -m 'Add some code'

Флажок -m задаст commit message — комментарий разработчика. Он необходим для описания закоммиченных изменений. И здесь работает золотое правило всех комментариев в коде: «Максимально ясно, просто и содержательно обозначь написанное!»

Как посмотреть коммиты

Для просмотра все выполненных фиксаций можно воспользоваться историей коммитов. Она содержит сведения о каждом проведенном коммите проекта. Запросить ее можно при помощи команды:

git log

В ней содержится вся информация о каждом отдельном коммите, с указанием его хэша, автора, списка изменений и даты, когда они были сделаны. Отследить интересующие вас операции в списке изменений, можно по хэшу коммита, при помощи команды git show :

git show hash_commit

Ну а если вдруг нам нужно переделать commit message и внести туда новый комментарий, можно написать следующую конструкцию:

git commit --amend -m 'Новый комментарий'

В данном случае сообщение последнего коммита перезапишется. Но злоупотреблять этим не стоит, поскольку эта операция опасная и лучше ее делать до отправки коммита на сервер.

Удаленные репозитории

Сейчас наш коммит является локальным — существует только в директории .git на нашей файловой системе. Несмотря на то, что сам по себе локальный репозиторий полезен, в большинстве случаев мы хотим поделиться нашей работой или доставить код на сервер, где он будет выполняться.

1. Что такое удаленный репозиторий

Репозиторий, хранящийся в облаке, на стороннем сервисе, специально созданном для работы с git имеет ряд преимуществ. Во-первых — это своего рода резервная копия вашего проекта, предоставляющая возможность безболезненной работы в команде. А еще в таком репозитории можно пользоваться дополнительными возможностями хостинга. К примеру -визуализацией истории или возможностью разрабатывать вашу программу непосредственно в веб-интерфейсе.
Клонирование
Клонирование — это когда вы копируете удаленный репозиторий к себе на локальный ПК. Это то, с чего обычно начинается любой проект. При этом вы переносите себе все файлы и папки проекта, а также всю его историю с момента его создания. Чтобы склонировать проект, сперва, необходимо узнать где он расположен и скопировать ссылку на него. В нашем руководстве мы будем использовать адрес https://github.com/tutorialzine/awesome-project, но вам посоветуем, попробовать создать свой репозиторий в GitHub, BitBucket или любом другом сервисе:

git clone https://github.com/tutorialzine/awesome-project

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

git clone https://github.com/tutorialzine/awesome-project new-folder

2. Подключение к удаленному репозиторию

Чтобы загрузить что-нибудь в удаленный репозиторий, сначала нужно к нему подключиться. Регистрация и установка может занять время, но все подобные сервисы предоставляют хорошую документацию.
Чтобы связать наш локальный репозиторий с репозиторием на GitHub, выполним следующую команду в терминале. Обратите внимание, что нужно обязательно изменить URI репозитория на свой.

# This is only an example. Replace the URI with your own repository address.
$ git remote add origin https://github.com/tutorialzine/awesome-project.git

Проект может иметь несколько удаленных репозиториев одновременно. Чтобы их различать, мы дадим им разные имена. Обычно главный репозиторий называется origin.

3. Отправка изменений на сервер

Сейчас самое время переслать наш локальный коммит на сервер. Этот процесс происходит каждый раз, когда мы хотим обновить данные в удаленном репозитории.
Команда, предназначенная для этого — push. Она принимает два параметра: имя удаленного репозитория (мы назвали наш origin) и ветку, в которую необходимо внести изменения (master — это ветка по умолчанию для всех репозиториев).

$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 212 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/tutorialzine/awesome-project.git
* [new branch] master -> master

Эта команда немного похожа на git fetch, с той лишь разницей, что при помощи fetch мы импортируем коммиты в локальную ветку, а применив push, мы экспортируем их из локальной в удаленную. Если вам необходимо настроить удаленную ветку используйте git remote. Однако пушить надо осторожно, ведь рассматриваемая команда перезаписывает безвозвратно все изменения. В большинстве случаев, ее используют, чтобы опубликовать выгружаемые локальные изменения в центральный репозиторий. А еще ее применяют для того, чтобы поделиться, внесенными в локальный репозиторий, нововведениями, с коллегами или другими удаленными участниками разработки проекта. Подытожив сказанное, можно назвать git push — командой выгрузки, а git pull и git fetch — командами загрузки или скачивания. После того как вы успешно запушили измененные данные, их необходимо внедрить или интегрировать, при помощи команды слияния git merge.
В зависимости от сервиса, который вы используете, вам может потребоваться аутентифицироваться, чтобы изменения отправились. Если все сделано правильно, то когда вы посмотрите в удаленный репозиторий при помощи браузера, вы увидите файл hello.txt

4. Запрос изменений с сервера

Если вы сделали изменения в вашем удаленном репозитории, другие пользователи могут скачать изменения при помощи команды pull.

$ git pull origin master
From https://github.com/tutorialzine/awesome-project
* branch master -> FETCH_HEAD
Already up-to-date.

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

Как удалить локальный репозиторий

Вам не понравился один из ваших локальных Git-репозиториев и вы хотите стереть его со своей машины. Для этого вам всего лишь надо удалить скрытую папку «.git» в корневом каталоге репозитория. Сделать это можно 3 способами:

  1. Проще всего вручную удалить эту папку «.git» в корневом каталоге «Git Local Warehouse».
  2. Также удалить, не устраивающий вас, репозиторий можно на github. Открываете нужный вам объект и переходите в пункт меню Настройки. Там, прокрутив ползунок вниз, вы попадете в зону опасности, где один из пунктов будет называться «удаление этого хранилища».
  3. Последний метод удаления локального хранилища через командную строку, для этого в терминале необходимо ввести следующую команду:
cd repository-path/
rm -r .git

Ветвление

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

  • Уже рабочая, стабильная версия кода сохраняется.
  • Различные новые функции могут разрабатываться параллельно разными программистами.
  • Разработчики могут работать с собственными ветками без риска, что кодовая база поменяется из-за чужих изменений.
  • В случае сомнений, различные реализации одной и той же идеи могут быть разработаны в разных ветках и затем сравниваться.

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

Основная ветка в каждом репозитории называется master. Чтобы создать еще одну ветку, используем команду branch <name>

$ git branch amazing_new_feature

Это создаст новую ветку, пока что точную копию ветки master.

2. Переключение между ветками

Сейчас, если мы запустим branch, мы увидим две доступные опции:

$ git branch
amazing_new_feature
* master

master — это активная ветка, она помечена звездочкой. Но мы хотим работать с нашей “новой потрясающей фичей”, так что нам понадобится переключиться на другую ветку. Для этого воспользуемся командой checkout, она принимает один параметр — имя ветки, на которую необходимо переключиться.

$ git checkout amazing_new_feature

В Git ветка — это отдельная линия разработки. Git checkout позволяет нам переключаться как между удаленными, так и меду локальными ветками. Это один из способов получить доступ к работе коллеги или соавтора, обеспечивающий более высокую продуктивность совместной работы. Однако тут надо помнить, что пока вы не закомитили изменения, вы не сможете переключиться на другую ветку. В такой ситуации нужно либо сделать коммит, либо отложить его, при помощи команды git stash, добавляющей текущие незакоммиченные изменения в стек изменений и сбрасывающей рабочую копию до HEAD’а репозитория.

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

Наша “потрясающая новая фича” будет еще одним текстовым файлом под названием feature.txt. Мы создадим его, добавим и закоммитим:

$ git add feature.txt
$ git commit -m "New feature complete.”

Изменения завершены, теперь мы можем переключиться обратно на ветку master.

$ git checkout master

Теперь, если мы откроем наш проект в файловом менеджере, мы не увидим файла feature.txt, потому что мы переключились обратно на ветку master, в которой такого файла не существует. Чтобы он появился, нужно воспользоваться merge для объединения веток (применения изменений из ветки amazing_new_feature к основной версии проекта).

$ git merge amazing_new_feature

Теперь ветка master актуальна. Ветка amazing_new_feature больше не нужна, и ее можно удалить.

$ git branch -d awesome_new_feature

Если хотите создать копию удаленного репозитория — используйте git clone. Однако если вам нужна только определенная его ветка, а не все хранилище — после git clone выполните следующую команду в соответствующем репозитории:

git checkout -b <имя ветки> origin/<имя ветки>

После этого, новая ветка создается на машине автоматически.

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

git branch -d local_branch_name

где флажок -d являющийся опцией команды git branch — это сокращенная версия ключевого слова —delete, предназначенного для удаления ветки, а local_branch_name – название ненужной нам ветки.
Однако тут есть нюанс: удалить текущую ветку, в которую вы, в данный момент просматриваете — нельзя. Если же вы все-таки попытаетесь это сделать, система отругает вас и выдаст ошибку с таким содержанием:

Error: Cannot delete branch local_branch_name checked out at название_директории

Так что при удалении ветвей, обязательно переключитесь на другой branch.

Дополнительно

В последней части этого руководства мы расскажем о некоторых дополнительных трюках, которые могут вам помочь.

1. Отслеживание изменений, сделанных в коммитах

У каждого коммита есть свой уникальный идентификатор в виде строки цифр и букв. Чтобы просмотреть список всех коммитов и их идентификаторов, можно использовать команду log:

Вывод git log

$ git log
commit ba25c0ff30e1b2f0259157b42b9f8f5d174d80d7
Author: Tutorialzine
Date: Mon May 30 17:15:28 2016 +0300
New feature complete
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author: Tutorialzine
Date: Mon May 30 16:30:04 2016 +0300
Added content to hello.txt
commit 09bd8cc171d7084e78e4d118a2346b7487dca059
Author: Tutorialzine
Date: Sat May 28 17:52:14 2016 +0300
Initial commit


Как вы можете заметить, идентификаторы довольно длинные, но для работы с ними не обязательно копировать их целиком — первых нескольких символов будет вполне достаточно. Чтобы посмотреть, что нового появилось в коммите, мы можем воспользоваться командой show [commit]
Вывод git show

$ git show b10cc123
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author: Tutorialzine
Date: Mon May 30 16:30:04 2016 +0300
Added content to hello.txt
diff --git a/hello.txt b/hello.txt
index e69de29..b546a21 100644
--- a/hello.txt
+++ b/hello.txt
@@ -0,0 +1 @@
+Nice weather today, isn't it?


Чтобы увидеть разницу между двумя коммитами, используется команда diff (с указанием промежутка между коммитами):
Вывод git diff

$ git diff 09bd8cc..ba25c0ff
diff --git a/feature.txt b/feature.txt
new file mode 100644
index 0000000..e69de29
diff --git a/hello.txt b/hello.txt
index e69de29..b546a21 100644
--- a/hello.txt
+++ b/hello.txt
@@ -0,0 +1 @@
+Nice weather today, isn't it?


Мы сравнили первый коммит с последним, чтобы увидеть все изменения, которые были когда-либо сделаны. Обычно проще использовать git difftool, так как эта команда запускает графический клиент, в котором наглядно сопоставляет все изменения.

2. Возвращение файла к предыдущему состоянию

Гит позволяет вернуть выбранный файл к состоянию на момент определенного коммита. Это делается уже знакомой нам командой checkout, которую мы ранее использовали для переключения между ветками. Но она также может быть использована для переключения между коммитами (это довольно распространенная ситуация для Гита — использование одной команды для различных, на первый взгляд, слабо связанных задач).
В следующем примере мы возьмем файл hello.txt и откатим все изменения, совершенные над ним к первому коммиту. Чтобы сделать это, мы подставим в команду идентификатор нужного коммита, а также путь до файла:

$ git checkout 09bd8cc1 hello.txt

3. Исправление коммита

Если вы опечатались в комментарии или забыли добавить файл и заметили это сразу после того, как закоммитили изменения, вы легко можете это поправить при помощи commit —amend. Эта команда добавит все из последнего коммита в область подготовленных файлов и попытается сделать новый коммит. Это дает вам возможность поправить комментарий или добавить недостающие файлы в область подготовленных файлов.
Для более сложных исправлений, например, не в последнем коммите или если вы успели отправить изменения на сервер, нужно использовать revert. Эта команда создаст коммит, отменяющий изменения, совершенные в коммите с заданным идентификатором.
Самый последний коммит может быть доступен по алиасу HEAD:

$ git revert HEAD

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

$ git revert b10cc123

При отмене старых коммитов нужно быть готовым к тому, что возникнут конфликты. Такое случается, если файл был изменен еще одним, более новым коммитом. И теперь git не может найти строчки, состояние которых нужно откатить, так как они больше не существуют.

4. Разрешение конфликтов при слиянии

Помимо сценария, описанного в предыдущем пункте, конфликты регулярно возникают при слиянии ветвей или при отправке чужого кода. Иногда конфликты исправляются автоматически, но обычно с этим приходится разбираться вручную — решать, какой код остается, а какой нужно удалить.
Давайте посмотрим на примеры, где мы попытаемся слить две ветки под названием john_branch и tim_branch. И Тим, и Джон правят один и тот же файл: функцию, которая отображает элементы массива.
Джон использует цикл:

// Use a for loop to console.log contents.
for(var i=0; i<arr.length; i++) {
console.log(arr[i]);
}

Тим предпочитает forEach:

// Use forEach to console.log contents.
arr.forEach(function(item) {
console.log(item);
});

Они оба коммитят свой код в соответствующую ветку. Теперь, если они попытаются слить две ветки, они получат сообщение об ошибке:

$ git merge tim_branch
Auto-merging print_array.js
CONFLICT (content): Merge conflict in print_array.js
Automatic merge failed; fix conflicts and then commit the result.

Система не смогла разрешить конфликт автоматически, значит, это придется сделать разработчикам. Приложение отметило строки, содержащие конфликт:

Вывод

<<<<<<< HEAD // Use a for loop to console.log contents. for(var i=0; i<arr.length; i++) { console.log(arr[i]); } ======= // Use forEach to console.log contents. arr.forEach(function(item) { console.log(item); }); >>>>>>> Tim's commit.


Над разделителем ======= мы видим последний (HEAD) коммит, а под ним — конфликтующий. Таким образом, мы можем увидеть, чем они отличаются и решать, какая версия лучше. Или вовсе написать новую. В этой ситуации мы так и поступим, перепишем все, удалив разделители, и дадим git понять, что закончили.

// Not using for loop or forEach.
// Use Array.toString() to console.log contents.
console.log(arr.toString());

Когда все готово, нужно закоммитить изменения, чтобы закончить процесс:

$ git add -A
$ git commit -m "Array printing conflict resolved."

Как вы можете заметить, процесс довольно утомительный и может быть очень сложным в больших проектах. Многие разработчики предпочитают использовать для разрешения конфликтов клиенты с графическим интерфейсом. (Для запуска нужно набрать git mergetool).

5. Настройка .gitignore

В большинстве проектов есть файлы или целые директории, в которые мы не хотим (и, скорее всего, не захотим) коммитить. Мы можем удостовериться, что они случайно не попадут в git add -A при помощи файла .gitignore

  1. Создайте вручную файл под названием .gitignore и сохраните его в директорию проекта.
  2. Внутри файла перечислите названия файлов/папок, которые нужно игнорировать, каждый с новой строки.
  3. Файл .gitignore должен быть добавлен, закоммичен и отправлен на сервер, как любой другой файл в проекте.

Вот хорошие примеры файлов, которые нужно игнорировать:

  • Логи
  • Артефакты систем сборки
  • Папки node_modules в проектах node.js
  • Папки, созданные IDE, например, Netbeans или IntelliJ
  • Разнообразные заметки разработчика.

Файл .gitignore, исключающий все перечисленное выше, будет выглядеть так:

*.log
build/
node_modules/
.idea/
my_notes.txt

Символ слэша в конце некоторых линий означает директорию (и тот факт, что мы рекурсивно игнорируем все ее содержимое). Звездочка, как обычно, означает шаблон.

Git bash и git.io

Руководствуясь часто встречающимися, при изучении системы, вопросами новичков, разберем еще несколько непонятных словосочетаний.

  • Git Bash(Bourne Again Shell) — это приложение, являющееся эмулятором командной строки и предоставляющее, операционной системе, некоторые распространенные утилиты bash и собственно саму систему Git. Это терминал, используемый для взаимодействия с персональным компьютером, посредством письменных команд.
  • URL-адреса хранилищ на Гитхабе могут быть довольно длинными, из-за больших имен репозиториев и файлов. Работать с такими ссылками очень не удобно. Поэтому сайт github.io создал git.io — неплохой сервис по преобразованию этих длинных и беспорядочных URL-адресов в более короткие и понятные. Сайт был создан в 2011 году и вплоть до недавнего времени отлично справлялся со своими обязанностями. Однако в начале этого года компания Гитхаб, из-за участившихся попыток хакеров использовать сайт в злонамеренных целях, остановила работу сервиса, а чем известила пользователей в своем блоге. Разработчики популярного ресурса рекомендуют пользоваться другими URL-cutter’ами, пока работа сервиса не будет налажена.

Заключение.

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

  • Официальная документация, включающая книгу и видеоуроки – тут.
  • “Getting git right” – Коллекция руководств и статей от Atlassian – тут.
  • Список клиентов с графическим интерфейсом – тут.
  • Онлайн утилита для генерации .gitignore файлов – тут.

Оригинал статьи доступен на сайте http://tutorialzine.com

Другие статьи по теме

10 полезных Git команд, которые облегчат работу

Шпаргалка по Git, в которой представлены основные команды

Из этой статьи вы узнаете

  • Зачем нужны системы контроля версий

  • Откуда взялся Git

  • Как создать свой репозиторий на GitHub и внести в него изменения

  • Что такое fork, branch и другие интересные слова из мира Git

  • Как создать свой Pull Request

Вступление

Бывает, что начинающие разработчики проблематично осваивают Git и не с первого захода понимают логику работы сервиса. Но стоит создать пару репозиториев или, ещё лучше, погрузиться в реальную историю по установке стартапа на рельсы DevOps, как работа с ветками станет дружелюбной, а PR и MR больше не вызовут путаницы. Ошибки в любом случае появятся, но вы будете к ним готовы!

Начало

Когда вы пишете первую программу, всё кажется таким лаконичным, простым и понятным. Но по мере развития ваша программа обрастает новой функциональностью, становится сложнее и больше. Потом и вовсе появляются первые баги. И было бы здорово помнить или иметь возможность смотреть историю изменений, что добавили или убрали в коде, по какой причине мог появиться баг.

Первое и самое просто решение — «А давайте перед каждым изменением сохранять копию программы (просто копировать папку с кодом)?»

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

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

Про Git

Существует несколько систем контроля версий: Git, Subversion, Team Foundation Server, Mercurial. Сегодня познакомимся с Git — самой популярной из них, по скромному признанию более 90% разработчиков.

Git появился 7 апреля 2005 года и был создан для управления разработкой ядра Linux. Кстати, создал его тот самый Линус Торвальдс, а сегодня его развитием и поддержкой занимается Дзюн Хамано.

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

История и копия проекта хранятся локально и чаще всего не нужна дополнительная информация с других клиентов. Вы можете работать с репозиторием и при отсутствии интернета (например, в самолёте), а когда он появится, просто загрузить изменения в удалённый репозиторий на выделенном сервере.

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

GitHub — крупнейший веб-сервис, который позволяет заниматься совместной разработкой с использованием Git и сохранять изменения на своих серверах. На самом деле функциональность GitHub намного больше, но сейчас нас интересует только совместная разработка и история изменений. Ещё есть Gitlab, Bitbucket и другие, но мы будем использовать GitHub как самый популярный в настоящее время.

Предварительная настройка

Займёмся предполётной подготовкой.

Для начала зарегистрируйтесь на GitHub: задайте логин, почту и придумайте пароль. После «Создать аккаунт» не забудьте проверить почту и подтвердить её (опрос от Github после подтверждения почты можно пропустить).

Если всё ок, экран GitHub будет выглядеть вот так

Если всё ок, экран GitHub будет выглядеть вот так

В GitHub есть разграничение прав на работу с репозиториями. Можно задавать различные политики: сделать репозиторий публичным и приватным, ограничить права кругу пользователей или кому-то одному, например, разрешить просматривать репозиторий, но не изменять в нём данные.

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

GitHub поддерживает безопасность за счёт двух сетевых протоколов, HTTPS и SSH, и вся работа с сервисом происходит через один из них.

Работать с GitHub будем через терминал по SSH. Для этого один раз сгенерируем специальные ключи и добавим один из них в наш аккаунт на GitHub.

Можно работать и через HTTPS, но нужно будет каждый раз вводить пароль и специальный token.

Пара слов про SSH и как он работает. SSH — это сетевой протокол для зашифрованного соединения между клиентом и сервером, через который можно безопасно передавать данные.

При подключении используется пара ключей — открытый (публичный, public) и закрытый (приватный, private). Пользователь создаёт пару ключей при помощи специальной команды и сохраняет закрытый ключ у себя, а открытый кладёт на сервер (в нашем случае на GitHub). А работает это всё благодаря асимметричному шифрованию.

Алгоритм следующий: отправитель (GitHub) шифрует сообщение публичным ключом и передаёт сообщение клиенту (нам), а мы его расшифровываем при помощи приватного ключа, который предусмотрительно сохранили у себя. То, что зашифровано публичным ключом, расшифровать сможет только приватный ключ.

Давайте создадим пару ключей и добавим открытый ключ на GitHub.

Чтобы создать пару ключей, в терминале нужно ввести команду, задать путь для хранения ключей и указать пароль к ключу (необязательно).

Далее будем опираться на то, что путь для ключей дефолтный и пароль на ключи не установлен.

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

$ ssh-keygen
Generating public/private rsa key pair.
# путь до ключей, в скобках путь по умолчанию
Enter file in which to save the key (/Users/ifireice/.ssh/id_rsa):  
# пароль для ключей, при задании пароля в консоли не отображается ничего, даже звёздочки
# если нажать Enter, ничего не вводя, пароль будет пустым
Enter passphrase (empty for no passphrase):
# повторите пароль
Enter same passphrase again:
# после появится сообщение такого вида
Your identification has been saved in /Users/ifireice/.ssh/id_rsa
Your public key has been saved in /Users/ifireice/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:Zu+HkZPC4ZP0veRmVjuKgylVvljHBNO8mHs+ieFFPvs ifireice@ifireice-osx
The key's randomart image is:
+---[RSA 3072]----+
|           o     |
|          o o    |
|           = .   |
|        o + +    |
|       +S* X     |
|       oB.@ X .  |
|       . O.# * . |
|      . +.*.% o  |
|       .  o*.+E. |
+----[SHA256]-----+

Бинго, ключи сгенерированы: в заданной директории появятся два файла, id_rsa и id_rsa.pub.

Теперь надо добавить публичный ключ в аккаунт на GitHub:

# выведите содержимое публичного ключа в консоль
$ cat ~/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDJfHIi73sKd6cqm3RwKuY1zl46aAaE6X9Gp
/6zJiY3BiJj95oJjPdpfpPhVFWLIbmT8zFAtOLbX9N4C3b0enHUzgMacP/Kl4AbrAkhLqaua9iD
VNxxiTVxADG1M5525oc/eAvx7y0pXIb9ouWdYJSKa8/TUYFhWlCzV2quY9SA0FaMs7eY41+KWYpG.....
tA0oGxv+7WmXQmQzleLIRG13KQ+VAbL2vabdPcRoGuZavh0smOr/GtVSnLdspZ5RgONMSPWlF2I1YHMR
Q7CIKPs= ifireice@ifireice-osx
$

Скопируйте ключ от символов ssh-rsa и до конца файла и вставьте его в ваш аккаунт на GitHub.

Перейдите сюда: иконка пользователя (1) → Settings (2)

Перейдите сюда: иконка пользователя (1) → Settings (2)
→ SSH and GPG keys (3) → New SSH key (4)

→ SSH and GPG keys (3) → New SSH key (4)
→ в Title дайте имя ключу, чтобы понимать, откуда он (может, в будущем у вас появится несколько ключей) (5) → в Key вставляем скопированный из консоли ключ (6) → нажимаем кнопку «Add SSH key» (7)

→ в Title дайте имя ключу, чтобы понимать, откуда он (может, в будущем у вас появится несколько ключей) (5) → в Key вставляем скопированный из консоли ключ (6) → нажимаем кнопку «Add SSH key» (7)
После этого в ваших SSH-ключах появится новый ключ, и вы сможете работать с компьютера, где лежит приватный ключ с GitHub

После этого в ваших SSH-ключах появится новый ключ, и вы сможете работать с компьютера, где лежит приватный ключ с GitHub

Ну что, с настройкой GitHub пока закончили, осталось установить Git на компьютер. Сделать это можно по официальной инструкции (выберите пункт для вашей ОС).

Терминология

Самое время пополнить ваш Git-словарик, прежде чем создадим первый Pull Request.

Репозиторий (repository) — директория проекта, который отслеживается Git. В директории хранится проект, история изменений и мета-информация проекта (в скрытой директории .git).

Индекс — хранилка, где лежат имена файлов и их изменения, которые должны быть в следующем коммите. По факту индекс — просто файл. В индекс файлы сами не попадают, их нужно явно добавлять при помощи git add.

Коммит (commit) — это фиксация изменений в истории проекта (изменения, которые внесены в индекс). Коммит хранит изменённые файлы, имя автора коммита и время, в которое был сделан коммит. Кроме того, каждый коммит имеет уникальный идентификатор, который позволяет в любое время к нему откатиться. Можете считать коммит этакой точкой сохранения.

Ветка (branch) — последовательность коммитов. По сути — ссылка на последний коммит в этой ветке. Ветки не зависят друг от друга — можно вносить изменения в одну, и они не повлияют на другую (если вы явно этого не попросите). Работать вы начинаете в одной ветке — main, увидите чуть позже.

Форк (Fork) — собственное ответвление (fork) какого-то проекта. Это означает, что GitHub создаст вашу собственную копию проекта, данная копия будет находиться в вашем пространстве имён, и вы сможете легко делать изменения путём отправки (push) изменений.

Пул-реквест — pull request PR (пиар, он же merge request MR(мр)) — предложение изменения кода в чужом репозитории. Допустим, вы забрали к себе чужой репозиторий, поработали с ним и теперь хотите, чтобы ваши изменения попали в оригинальный репозиторий — тогда вы создаёте создаёте PR с просьбой добавить ваши изменения в репозиторий.

Начало работы

Начнём с простого — создадим свой репозиторий и сделаем наш первый коммит.

Открываем repositories (1) и создаём новый (2)

Открываем repositories (1) и создаём новый (2)
Задаём параметры репозитория

Задаём параметры репозитория

Зададим параметры:

  • (1) Repository name: имя репозитория.

  • (2) Description: описание репозитория.

  • (3) Тип репозитория: Public (публичный) или Private (приватный). Сейчас выберем публичный — кто угодно может видеть содержимое репозитория.

  • (4) Ставим галку на «Создать README файл». В этом файле в формате MarkDown описывают проект или прочую документацию. Именно содержимое этого файла можно увидеть, когда заходим на главную страницу репозитория. Примеры 1, 2, 3.

  • (5) Если известно, на каком языке будет проект, можем добавить шаблон .gitignore для этого языка. Сейчас у нас нет какого-то языка, поэтому не будем создавать .gitignore.

  • (6) Выбираем тип лицензии для нашего кода. В лицензии оговариваются права на проект. Стоит обратить внимание на BSD 3 или MIT, так как они предоставляют хороший баланс прав и ответственности.

(7) По умолчанию имя основной ветки в GitHub носит имя main, но до недавнего времени было master.

Получаем наш первый репозиторий

Получаем наш первый репозиторий

И нажимаем кнопку «Create repository». Успех, у нас есть первый репозиторий!

А что будет, если не добавим README и .gitignore?

На самом деле ничего страшного не произойдёт, но придётся выполнить ещё ряд шагов, чтобы проинициализировать git-репозиторий, прежде чем начать с ним работать.

Не переживайте, Git очень дружелюбный и сам расскажет, как это сделать.

Не переживайте, Git очень дружелюбный и сам расскажет, как это сделать.

Итак, мы создали репозиторий на удалённом сервере, теперь пора «забрать» его к себе на локальную машину и внести какие-то изменения.

Чтобы забрать репозиторий, его надо склонировать к себе при помощи команды git clone и пути до репозитория.

Для начала получим путь до репозитория.

Заходим в созданный репозиторий и находим кнопку «Code» (1) → нажимаем её → выбираем SSH (2) → и копируем строку (3)

Заходим в созданный репозиторий и находим кнопку «Code» (1) → нажимаем её → выбираем SSH (2) → и копируем строку (3)

Теперь идём в консоль, переходим в директорию, где хотим хранить проекты, и выполним (git@github.com:ifireiceya/MyFirstRepo.git — путь, который мы скопировали ранее):

$ git clone git@github.com:ifireiceya/MyFirstRepo.git
Cloning into 'MyFirstRepo'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.

Переходим в новый каталог, где теперь лежит копия нашего проекта с GitHub:

$ cd MyFirstRepo

Можем посмотреть, что уже есть в этой директории:

$ ls -a
.git      LICENSE   README.md

Видим два знакомых файла,LICENSE и README.md, а также одну скрытую директорию .git.

В .git хранится метаинформация и вся история для проекта. На каждый проект есть только одна директория .git, и лежит она в корне проекта.

$ ls .git
HEAD                 # указатель на вашу активную ветку
config               # персональные настройки для проекта
description          # описание проекта
hooks                # pre/post action hooks
index                # индексный файл
logs                 # история веток проекта (где они располагались)        
objects              # ваши объекты (коммиты, теги и тд)
packed-refs refs     # указатели на ваши ветки разработки

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

При установке Git была добавлена утилита git config, которая позволяет просматривать и изменять большинство параметров работы Git’а. Если речь о данных пользователя или способе работы репозитория — git config будет самым удобным способом настройки.

Настроим имя пользователя и адрес электронной почты. Эта информация важна, потому что включается в каждый коммит.

Поэтому в терминале переходим в Git-репозиторий, для которого задаём настройки, и выполняем:

$ git config user.name "Дарья Меленцова"
$ git config user.email ifireice@example.com


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

Чтобы настраивать ещё больше параметров с помощью git config, прочитайте эту документацию.

Вносим изменения

Теперь нужно внести изменения в проект. Но перед этим посмотрим две полезных команды:

  • git status — показывает текущее состояние файлов в репозитории (какие файлы изменились, удалились, добавились);

  • git log — показывает историю изменений (это про зафиксированные изменения, то есть коммиты).

Выполним эти команды и посмотрим, что они выведут для нашего репозитория.

Вбиваем git status:

$ git status                                  
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

И видим, что у нас нет изменений. Говорят, «нет коммитов в репозитории». Конечно, мы успели только клонировать репозиторий и ещё ничего не делали.

Идём дальше и пробуем git log, который покажет, что в проекте был только один Initial commit — когда мы создавали репозиторий с README.md:

$ git log
commit 9ae1cbcc77f3b64d604612d4a599bdbb8b1cf204 (HEAD -> main, origin/main, origin/HEAD)
Author: ifireiceya <117034707+ifireiceya@users.noreply.github.com>
Date:   Mon Oct 31 00:01:05 2022 +0300

    Initial commit
(END)

Убедились, что у нас нет неучтённых изменений. Пора бы уже что-то сделать!

Открываем любимый текстовый редактор и создаём новый файл с именем hw.py.

Это будет небольшая программа на Python, которая при запуске печатает «Hello World!» (внезапно):

$ vi hw.py
print("Hello World!")

Отлично, код написан и даже хранится локально в нашем репозитории (мы же в директории проекта всё делали).

Теперь наша задача — сохранить изменения в «оригинальный» (удалённый) репозиторий. Для этого нужно:

  1. Познакомить Git с новым файлом, то есть добавить файл в индекс — git add.

  2. Зафиксировать (закоммитить) изменения — git commit.

  3. Синхронизировать изменения с сервером — git push.

  4. Посмотреть в репозиторий и убедиться, что всё сработало.

Делаем!

Мы уже создали файл и теперь можем посмотреть, в каком статусе Git

Мы уже создали файл и теперь можем посмотреть, в каком статусе Git

Появился файл hw.py, но он красный. Паника! Всё сломалось?!

Нет, всё идёт по плану, но прежде чем продолжить, стоит обсудить состояние файлов с точки зрения Git’а.

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

  1. Неотслеживаемый (untracked).

  2. Изменённый (modified) — файл, в котором есть изменения, но он ещё не добавлен в коммит (не зафиксирован).

  3. Отслеживаемый (staged) — файл, который добавили в индекс.

  4. Зафиксированный (committed) — файл уже сохранён в локальной базе, и в нём не было изменений с последнего коммита.

Три секции проекта, с которыми работают в Git

Три секции проекта, с которыми работают в Git

В связке с состоянием файлов используют три основных секции проекта:

  • Рабочая директория (working directory) — это директория, которая содержит в себе то, с чем вы работаете, или то, что вы извлекли из истории проекта в данный момент. Рабочая директория — это временное место, где вы можете модифицировать файлы, а затем выполнить коммит.

  • Область индексирования (staging area) — индекс-файл в каталоге Git, который содержит информацию о том, что попадёт в следующий коммит.

  • Каталог Git — место, где Git хранит метаданные и базу объектов вашего проекта. Помните ещё про .git?

Что происходит на практике

Мы добавили новый файл hw.py и видим, что у него состояние untracked, то есть неважно, что мы делаем с файлом, Git проигнорирует любые изменения в нём.

Чтобы Git начал следить за изменениями в файле, его нужно добавить в индекс.

Для этого используем команду git add <имя файла>.

Кстати, вы заметили, что Git довольно дружелюбный и часто подсказывает команды, которые нужно выполнить?

$ git add hw.py
# если нужно добавить много файлов и не хочется описывать, можно использовать команду
# git add .
# но стоит точно понимать, что добавляем, иначе придётся потом удалять файлы из индекса
# кстати, для удаления используется команда git rm, но стоит почитать доку перед использованием

И ещё не забывайте о файле .gitignore, где перечислены папки и файлы репозитория, которые Git не должен отслеживать и синхронизировать их состояние (не добавлять их в индекс). Обычно в него добавляют файлы логов, результаты сборки и другое. Поддерживает шаблоны. Кстати, .gitignore — тоже файл, который надо добавить в индекс.

  • Если файл попадает в правила.gitignore, то он не появится в git status.

  • Если файл был добавлен в индекс, а потом добавлено правило для файла в .gitignore — файл всё равно будет отслеживаться и его надо явно удалить из индекса.

Посмотрим, как изменилось состояние нашего файла:

Смотрите, наш файл стал зелёным, и сообщение от Git изменилось. Сам файл теперь имеет состояние staged

Смотрите, наш файл стал зелёным, и сообщение от Git изменилось. Сам файл теперь имеет состояние staged

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

Для этого нужно закоммитить файл с помощью команды git commit.

При создании обычно лаконично описывают коммит, используя ключ -m:

$ git commit -m "add python hello world"     
[main 6d8a5c3] add python hello world
 1 file changed, 1 insertion(+)
 create mode 100644 hw.py

Пара слов о том, как писать сообщения для коммитов:

  • максимум 50 символов;

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

  • сообщение стоит начинать с заглавной буквы;

  • если меняли код, пишите исходный код в сообщении.

$ git log
Осталось отправить наши изменения на удалённый сервер. Используем git push:

Осталось отправить наши изменения на удалённый сервер. Используем git push:
$ git push
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 341 bytes | 341.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:ifireiceya/MyFirstRepo.git
   9ae1cbc..6d8a5c3  main -> main

Предлагаем проверить, что наши изменения есть на GitHub. Идём в репозиторий и смотрим на него.

Появился наш файл и commit message, который задали

Появился наш файл и commit message, который задали

Задача немного посложнее

Всё здорово, но мы не всегда создаём репозитории, и часто нам нужно добавлять новые фичи или исправления в уже существующий репозиторий, да ещё и в чужой.

Например, есть у нас любимый опенсорсный проект, в который мы хотим принести добро и закрыть им какой-нибудь Issue.

В учебных целях используем репозиторий из этой статьи на GitHub. Там нужно исправить опечатку, которую нашли в статье. Например, вот эту очепятку.

Но будем делать это с позиции внешних пользователей в чужом репозитории.

Репозиторий хранится в ifireice/git, а изменения делает пользователь ifireiceya.

Пользователь ifireiceya не имеет доступа в ifireice/git, и ему придётся работать через Fork, то есть нужно сперва сделать копию этого репозитория к себе и вести разработку у себя, а потом отправить в основной репозиторий запрос на изменения — Pull Request.

Но обо всём по порядку. Сначала делаем Fork.

Заходим под пользователем ifireiceya в репозиторий ifireice/git и нажимаем на Fork(1)

Заходим под пользователем ifireiceya в репозиторий ifireice/git и нажимаем на Fork(1)

Откроется окно для создания нового форка (fork).

Изменится владелец репозитория (1), и опционально можно изменить описание проекта.

Нажимаем «Create fork» и получаем новенький форк

Нажимаем «Create fork» и получаем новенький форк
Можно увидеть новый репозиторий в списке наших репозиториев

Можно увидеть новый репозиторий в списке наших репозиториев

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

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

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

В нашем репозитории мы работали в ветке main и все изменения сохраняли в ней.

А теперь у нас большой проект, и над ним одновременно могут трудиться несколько разработчиков. Чтобы разные изменения не смешивались в кучу и чтобы один разработчик не мешал другому, разработка ведётся в разных независимых версиях продукта — ветках (branch). Когда работа закончена, все изменения сливаются в одну главную ветку.

Клонируем репозиторий и создаём отдельную ветку, в которой будем устранять опечатку:

$ git clone git@github.com:ifireiceya/git.git
$ cd git
# создадим новую ветку и сразу же переключимся на неё, чтобы работать там
$ git checkout -b fix-misprint
Switched to a new branch 'fix-misprint'

Чтобы посмотреть, какие ветки есть в проекте и какая сейчас активна, используется команда git branch:

$ git branch
* fix-misprint
  main
# * помечена текущая активная ветка

На самом деле практика работать с ветками распространена не только при разработке в чужих репозиториях (collaborators), куда у вас нет доступа, но и в своих. Есть несколько стратегий выделения веток, но об этом не сейчас. Просто знайте, что есть ветки и с их помощью удобно вести разработку.

Можем посмотреть, что изменилось с последнего коммита, при помощи команды git diff (красным с “-” то, что было, зелёным с “+” — то, что стало):

$ git diff
Правим опечатку и всё по накатанной: смотрим status, делаем коммит и пушим изменения

Правим опечатку и всё по накатанной: смотрим status, делаем коммит и пушим изменения
$ git status
On branch fix-misprint
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:   README.md

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

$ git commit -am "Поправили опечатку"
[fix-misprint 188caa7] Поправили опечатку
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git push
fatal: The current branch fix-misprint has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin fix-misprint

Упс, fatal. Читаем подсказку от Git и выполняем:

$ git push --set-upstream origin fix-misprint
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 402 bytes | 402.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote:
remote: Create a pull request for 'fix-misprint' on GitHub by visiting:
remote:      https://github.com/ifireiceya/git/pull/new/fix-misprint
remote:
To github.com:ifireiceya/git.git
 * [new branch]      fix-misprint -> fix-misprint
Branch 'fix-misprint' set up to track remote branch 'fix-misprint' from 'origin'.

Успех!

Почему произошёл fatal: простой git push предполагает, что ветка, которую отслеживает текущая локальная ветвь, уже существует на удалённом сервере. У нас ветка новая и была создана только локально, поэтому нам нужно её создать, указав --set-upstream.

Проверим, что ветка появилась на GitHub.

Заходим в репозиторий и нажимаем на кнопку «ветки» (1) → видим в списке нашу ветку (2)

Заходим в репозиторий и нажимаем на кнопку «ветки» (1) → видим в списке нашу ветку (2)

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

Для этого создаём Pull request.

Здесь живут пулл реквесты... когда они, конечно, есть

Здесь живут пулл реквесты… когда они, конечно, есть

И увидим такую картину.

(1) репозиторий, в который хотим добавить изменения. — ifireice/git

(2) ветка, в которую хотим добавить изменения — main

(3) репозиторий, из которого хотим добавить изменения — ifireiceya/git

(4) ветка, из которой хотим добавить изменения — main

Не пугайтесь, что GitHub считает, будто нет изменений: их нет, потому что мы работали в ветке fix-misprint. Меняем ветку, из которой вносим изменения (4), на нужную — и видим изменения

Не пугайтесь, что GitHub считает, будто нет изменений: их нет, потому что мы работали в ветке fix-misprint. Меняем ветку, из которой вносим изменения (4), на нужную — и видим изменения
Нажимаем кнопку «Create pull request» и пишем описание. Просматриваем ещё раз изменения. Если всё так, как нужно, ещё раз нажимаем «Create pull request»

Нажимаем кнопку «Create pull request» и пишем описание. Просматриваем ещё раз изменения. Если всё так, как нужно, ещё раз нажимаем «Create pull request»
Готово! У нас появился первый PR (ищите его в оригинальном репозитории в разделе Pull Requests)

Готово! У нас появился первый PR (ищите его в оригинальном репозитории в разделе Pull Requests)

На этом сейчас наша работа завершена. Ответственные за репозиторий посмотрят ваши изменения, примут их, или попросят что-то дописать, или отклонят изменения.

Будем считать, что у нас всё хорошо и наши изменения приняли без вопросов.

Как это выглядит на стороне ревьюверов:

Перешли в Pull Requests

Перешли в Pull Requests
Зашли в PR. Посмотрели описание, коммиты, какие изменения будут, и нажали кнопочку «Merge pulll request», если всё устраивает — нас всё устраивает

Зашли в PR. Посмотрели описание, коммиты, какие изменения будут, и нажали кнопочку «Merge pulll request», если всё устраивает — нас всё устраивает
Изменения помёржились

Изменения помёржились
В main ветке тоже можно увидеть и изменения из нашего ПР, и автора этих изменений. Надо лишь зайти в коммит

В main ветке тоже можно увидеть и изменения из нашего ПР, и автора этих изменений. Надо лишь зайти в коммит
Конец

Конец

На этом пока всё. Увидимся в следующих выпусках про Git и не только.

Что изучили

  • Поговорили про системы контроля версий

  • Настроили себе GitHub

  • Создали первый репозиторий и внесли в него изменения

  • Узнали про ветки, форки и остальное

  • Сделали первый ПР

Что НЕ изучили

  • Конфликты

  • Откат изменений (reset, revert)

  • Как забрать файл из другой ветки (Cherry-pick)

  • rebase

Что ещё почитать

  • Отличная книга Pro Git (есть на русском и английском)

  • Курс «DevOps для эксплуатации и разработки»

  • Trunk-Based Development — стратегия отведения веток

  • GitFlow — другая стратегия отведения веток

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Беговое колесо для кошек своими руками пошаговая инструкция
  • Шумоизоляция днища автомобиля изнутри своими руками пошаговая инструкция
  • Ангримакс нео инструкция по применению капсулы взрослым
  • Инструкция по ремонту двигателя ваз 2107
  • Кротонол патроны от кротов инструкция по применению