Git быстрый старт

2022.11.07
Рассмотрим основы работы с системой контроля версий git - как начать работать и как продолжить использовать
git

Создание локального репозитория и синхронизация с удаленным

Для начала нужно создать пустой репозиторий на аккаунте хостинга git-репозиториев.

Github и GitLab в пустом репозитории показывают информацию о том что делать дальше.

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

$ git init

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

$ git add .
$ git commit -m 'init repository'

Теперь нужно добавить удаленный репозиторий (на аккаунте хостинга):

$ git remote add origin <url>

Но если нужно сменить ранее добавленный адрес на новый, тогда нужно:

$ git remote set-url origin <url>

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

$ git remote -v

Должно быть что-то типа:

origin <url> (fetch)
origin <url> (push)

Затем нужно перенести все изменения на удаленный репозиторий так:

git push -u origin main

Узнать о текущем статусе локального репозитория:

$ git status
На ветке main
Ваша ветка обновлена в соответствии с «origin/main».

Неотслеживаемые файлы:
  (используйте «git add <файл>…», чтобы добавить в то, что будет включено в коммит)
        content/development/127_git.md

ничего не добавлено в коммит, но есть неотслеживаемые файлы (используйте «git add», чтобы отслеживать их)

Клонирование и субмодули

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

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

$ git clone <url>
$ cd <dir>
$ git add .
$ git commit -m 'init repository'
$ git push

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

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

$ git clone --recursive <url>

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

$ git submodule update --recursive --remote

Инициализировать и/или обновить все субмодули репозитория за одну команду:

$ git submodule update --init --recursive

Добавить субмодуль в репозиторий:

$  git submodule add <url> <path>

Где:

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

Как не коммитить изменения прав на файлы?

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

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

Решается это при помощи команды:

$ git config core.filemode false

HEAD

HEAD это специальный указатель на определенный (текущий) коммит. Этот коммит может быть в какой-то ветке, например в main, или быть вне ветки - это и есть detached HEAD.

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

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

HEAD detached

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

$ git push
fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)
state now, use

    git push origin HEAD:<name-of-remote-branch>

Конечно же git предупреждал ранее в команде status:

$ git status
HEAD detached at 6b4f07f
...

НАДО БЫЛО в этот момент переключиться на нужную ветку (например на main) и все было бы без проблем (при отсутсвии коммитов):

$ git checkout master

Относительно проблемы, если коммит вне ветки (detached HEAD), то прямым образом он никак не может быть отправлен на сервер, один из способов решения:

Еще почитать можно здесь или тут или там.

Сводка коммитов

В самом простом варианте, историю коммитов можно посмотреть так:

$ git log --oneline
68d24e3 (HEAD -> main, origin/main) updated flatness, fixed service page
28fa96e added post 68
d3fa0c0 added integrations category, added posts 48, 67, 71, 80, 89, 93
508407f added posts 61, 88
c7ef705 fixed volume php_error.log

Но есть другие варианты.

Смотрим как работать с историей коммитов (вот еще), находим там интересную опцию --pretty. Эта опция позволяет настроить вывод информации о коммите. Например так:

$ git log --pretty=format:"%h - %an/%cn, %ar : %s"

506dca7 - Byurrer/Byurrer, 4 часа назад : adapted table names for tests
edd43d0 - Byurrer/Byurrer, 7 часов назад : small fixeds
18575eb - Byurrer/Byurrer, 7 часов назад : added select db redis

Или так:

$ git log --pretty=oneline

506dca7724f2c94511f0128d34b57c919abd70f0 (HEAD -> dev, origin/dev) adapted table names for tests
edd43d00722a835a6ec24df14c38e103894d4128 (master) small fixeds
18575eb3c91f6ac298b9a7e0113471f0f5ddff59 added select db redis

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

$ git log --pretty=format:'%h - %an/%cn, %ar : %s' from..to

Где [from, to] это коммиты "от и до" куда (включительно) нужно показать историю.

Хэш последнего коммита

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

Получить полный SHA-1 хэш коммита:

$ git rev-parse HEAD

edd43d00722a835a6ec24df14c38e103894d4128

Или так:

$ git log -n 1 --pretty=format:"%H"

edd43d00722a835a6ec24df14c38e103894d4128

Получить короткий хэш:

$ git log -n 1 --pretty=format:"%h"

edd43d0

Получить хэш последнего коммита в нужной ветке:

$ git show-ref --heads --hash master

edd43d00722a835a6ec24df14c38e103894d4128
В телеграм канале DevOps от первого лица можно оставить комментарий или почитать интересные истории из практики DevOps