GIT: Обо всём по не многу

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

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

Конфигурирование Git

В Git настройки берутся из трех мест, это (local перекрывает global, а global перекрывает system):

  • Общий для всех пользователей системы, параметр: –system
  • Настройки для пользователя системы, параметр: –global
  • Настройки для конкретного репозитория, параметр: –local

Настраиваем имя пользователя и email (эти данные используются при комитах):

1
2
git config --global user.name "Test"
git config --global user.email test@test.com

Просмотр настроек Git: git config --global --list

Для редактирования global конфига, можно воспользоваться командой nano ~/.gitconfig
Таким образом можно например настроить сокрашения, достаточно добавить:

1
2
3
4
5
6
7
8
[alias]
co = checkout
ci = commit
st = status
br = branch
hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short
type = cat-file -t
dump = cat-file -p

Основные команды GIT

git init


git add

git add hello.html

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


commit и reset

git commit -m "First Commit" - сделает коммит с комментарием ‘First Commit’, если просто ввести git commit, то git перенесет вас в редактор по вашему выбору (настраивается в конфигах). По умолчанию это Vim (Linux и Mac). В первой строке вводим сообщение, затем, чтобы выйти нужно нажать клавишу ESC, ввести :wq и нажать Enter.

git commit --amend - изменение последнего коммита. Команда возьмёт текущий индекс и перезапишет последний коммит с нужным комменатрием, если добавить -m 'comment'

git revert HEAD или git revert 8e46951 --no-edit - (–no-edit генерирует выходные данные без открытия редактора) создает коммит, в котором отменены изменения комита с хэшом 8e46951. Комментарий нового комита повторяет отмененный коммит, но вначале добовляется слово Revert.


git status


git reset

git reset HEAD hello.html - снимает индексацию изменений, если вы решили, что не хотите коммитить изменения (очищает буферную зону от изменений, которые мы только что проиндексировали).
git reset --hard v1 - удаляет коммиты, сделанные после коммита с тэгом v1 (либо можно указать хэш). Если быть точны то коммиты не удаляются, а отсутствуют в ветке. Коммиты, на которые нет ссылок (обратиться можно только по хэшу), остаются в репозитории до тех пор, пока не будет запущен сборщик мусора.


git log - показывет историю всех коммитов. Очень гибкая команда, подробнее можно узнать, введя команду man git log

  • --pretty="..." — определяет формат вывода.
  • %h — укороченный хэш коммита
  • %d — дополнения коммита («головы» веток или теги)
  • %ad — дата коммита
  • %s — комментарий
  • %an — имя автора
  • --graph — отображает дерево коммитов в виде ASCII-графика
  • --author - Показать только те коммиты, автор которых соответствует указанной строке.
  • -(n) - Показать последние n коммитов
  • --date=short — сохраняет формат даты коротким и симпатичным
  • --all - гарантированно означает, что мы видим все ветки и коммиты. По умолчанию показывается только текущая ветка.

Примеры:

  1. git log --all --pretty=format:"%h %ad $s (%an)" --since='7 days ago' --author=Falbin - показать изменения, сделанные за неделю, разработчиком Falbin
  2. git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short - оптимальная команда

В .gitconfig мы настроили alias для команды git log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short, теперь ее можно вызывать командой git hist


tag

git tag v1 - создание тэга v1 для текущей версии проекта. В дальнейшем можно будет переключаться по названию тэга.
git tag - вызов без параметров приводит к показу имен всех тэгов в проекте.
git tag -d oops - удалит тег, вызвав сборшик мусора. Также будут удалены коммиты, на которые ничего не ссылается.


checkout - взять из репозитория какое-либо его состояние.

  1. Можно переключаться по хешу коммита git checkout 6944a07
  2. Можно переключаться по названию веток git checkout master
  3. Можно переключаться по названию тэга. git checkout v1
    • Можно переключится к предыдущей (на 1 шаг назад) версии проекта от тэга v1 так: git checkout v1^ или git checkout v1~1
    • Можно переключится к предыдущей (на 2 шага назад) версии проекта от тэга v1 так: git checkout v1^^ или git checkout v1~2 и т.д.
  4. Избавляемся от нежелательных правок до коммита.
    • Если файл еще не проиндексирован, можно получить последнее состояние файла по его имени checkout hello.html, чтобы отменить нежелательные изменения.
    • Если нежелательные изменения были проиндексированы необходимо сначала сбросить прииндексированные изменения git reset HEAD hello.html, затем получаем последнее состояние файла с помощью команды git checkout hello.html
  5. git checkout <имяветки> - переключение между ветками.
  6. git checkout -b <имяветки> - создает новую ветку и переключается на эту ветку. Является шорткатом для git branch <имяветки> за которым идет git checkout <имяветки>.

branch

git branch - выводит список локальных веток по умолчанию.
git branch -a - выводит список всех веток, в том числе и в удаленном репозитории.


Работа непосредственно с объектами git

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

git cat-file -t <hash> - (алиас заданный нами: type)
git cat-file -p <hash> - (алиас заданный нами: dump)

Есть три типа объектов, которые показывает git type: tree, commit, blob.


git merge master

git rebase master

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

Когда использовать перебазирование, а когда слияние?
Не используйте перебазирование …

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


.gitignore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Игнорирование файла во ВСЕХ директориях
# Например /params/db/config.php или /config.php
config.php

# Игнор-лист файлов проекта
# Игнорировать ВСЕ файлы и директории, включая поддиректории и файлы в них
*

# Игнорирование по типу файла, будут игнорироваться в АБСОЛЮТНО всех директориях
*.zip
*.log
*.pdf

# Игнорирование конкретного файла ТОЛЬКО в корне проекта
# (корнём считается расположение файла .gitignore)
/config.php

# Игнорирование всех файлов и папок ТОЛЬКО в конкретной директории (включая поддиректории)
/images/*

# Игнорирование всех файлов и папок в ЛЮБЫХ директориях с указанным именем
# Например /images/user.jpg, /core/images/user.jpg
images/*

# Игнорирование ВСЕХ html-файлов в ОДНОЙ КОНКРЕТНОЙ директории(НЕ ВКЛЮЧАЯ поддиректории)
# Например /private/index.html
# НЕ БУДУТ проигнорированы файлы в /private/ivan/index.html
/private/*.html

# Игнорирование ВСЕХ html-файлов в КОНКРЕТНОЙ директории ВКЛЮЧАЯ поддиректории
# Например /private/info.html, /private/users/ivan/info.html
/private/**/*.html

# Исключение из игнорирования
# Игнорирование ВСЕХ файлов и папок внутри директории /secret,
# за исключением файла /secret/free.txt, он не будет проигнорирован
/secret/*
!/secret/free.txt

# Игнорирование файла с именем, содержащим спецсимволы
# Например !readme!.txt
\!readme!.txt

# Игнорирование всех JPG и JPEG файлов внутри директорий,
# которые начинаются на "h" и МОГУТ содержать ещё один символ после
# Например /images/h4/user.jpg, /images/h/company.jpeg
/images/h?/*.jp?g

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

git remote - позволяет просмотреть какие удалённые серверы у вас уже настроены.

git clone <имя_клонируемого_проекта> <новое_имя_склонированного_проекта> (к примеру на локальной машине)
Git выводит все коммиты в оригинальный репозиторий, но ветки в удаленном репозитории не рассматриваются как локальные. Если мы хотим собственную ветку style, мы должны сами ее создать.
Пример:

1
2
3
4
5
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/style
remotes/origin/master

git fetch [имя удал. сервера] - (имя удалаленного сервера обычно origin) Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. После того как вы выполнили команду, у вас должны появиться ссылки на все ветки из этого удалённого проекта. Теперь эти ветки в любой момент могут быть просмотрены или слиты.

git merge origin/master - сливает изменения, которые есть в удаленной ветки, с origin/master с локально веткой master

git pull - (эквивалентен комбинации git fetch и git merge origin/master)

При клонировании репозитория, как правило, автоматически создаётся ветка master, которая отслеживает origin/master, поэтому git push и git pull работают для этой ветки “из коробки” и не требуют дополнительных аргументов.

git branch --track style origin/style - добовляет локальную ветку style, которая отслеживает изменения удаленной ветки origin/style.


Полезные ссылки:

  1. Подробно о .gitignore
  2. Подробно о git log
  3. Конфигурирование Git
  4. Уроки по Git
Поделиться