Мысли
May 22, 2021

Конспект взаимодействия с git

Гит (git) оперирует коммитами (commit) - изменениями содержимого файлов. Ветка (branch) - это указатель на коммит, смещается с каждым новым коммитом в искомую ветку. Каждый коммит указывает на предыдущий, вплоть до первого. На один родительский коммит может указывать несколько коммитов, реализуется через ветки. Ветки можно сливать с помощью merge-коммита. Если одна из сливаемых веток была пустой (от общего коммита, от которого произошло разветвление), то по умолчанию происходит fast-forward - перенос указателя на общий коммит (пустая ветка) к коммиту непустой ветки. Историю коммитов можно изменять с помощью rebase. https://githowto.com/ru/

Сокращения команд (alias).
Файл для настройки находится в $HOME. Для windows vista и выше за это отвечает переменная %userprofile% (win-r для вызова окна "Выполнить", затем ввести туда %userprofile% и нажать ОК, после чего откроется папка, соответствующая этой переменной), которая имеет путь <root>\Users\<username>, где <root> - это диск на котором установлена ОС, а <username> - имя профиля. https://ru.wikipedia.org/wiki/Домашний_каталог
Файл .gitconfig - для настройки алиасов и прочего внутри команды git. https://githowto.com/ru/aliases
Содержание:

[user]
	name = EvgenZhaba
	email = <мояпочта>
[alias]
	hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=iso

В нём можно записать имя автора коммитов и его почту (как скрыть реальную: на https://github.com/settings/emails можно нажать "Keep my email addresses private", после чего будет выдана фейкопочта на гитхабе, предназначенная только для операций с git)
Алиас git hist будет выводить историю коммитов графом в формате типа:

* a44512d 2020-04-20 20:07:23 +0300 | текст коммита [EvgenZhaba]

Также там (но уже по пути Git\etc\.gitconfig) хранится вариант хранения учетных данных:

[credential]
	helper = manager
	
в данном случае логин и пароль запоминаются (в учётных данных windows, посмотреть (или удалить) можно в "Панель управления\Все элементы панели управления\Диспетчер учетных данных", выбрать "Учетные данные windows") и их не надо вводить каждый раз при отправке коммитов на удалённый репозиторий. https://git-scm.com/book/ru/v2/Инструменты-Git-Хранилище-учётных-данных
В этом же файле есть настройка (autocrlf = true), которая будет преобразовывать для использования файлов концы строк в виндовый формат(CR LF), а в гит отправлять правильный(LF). https://htmlacademy.ru/blog/boost/tools/konec-stroki

Файл .profile - файл настройки алиасов для оболочки. При установке git на windows 10 этот файл оказался также в %userprofile%.
Содержание:

alias ga='git add'
alias gs='git status'
alias gss='git status --short'
alias gc='git commit'
alias gcm='git commit --message'
alias gh='git hist'
alias gco='git checkout'
alias gr='git rebase'
alias gpush='git push'
alias gpull='git pull --rebase'

Используемые команды.
git init - создать репозиторий. https://githowto.com/ru/create_a_project
git mv <файл> <путь> - перемещение файла в указанный путь.

git add <файл> - добавить файл для индексации (. - добавить все файлы). https://githowto.com/ru/staging_changes
git status - проверить состояние, нет ли проиндексированных файлов, изменения которых ожидают записи. https://githowto.com/ru/checking_status
git commit - сделать коммит на основе изменений проиндексированных файлов, также открывается окно текстового редактора для ввода комментария к коммиту, я использую и рекомендую notepad++. https://githowto.com/ru/commiting_changes
git commit --message "комментарий" - сделать коммит с комментарием, указанным в команде.
git commit --amend -m "другой комментарий" - изменение комментария и запись текущих проиндексированных файлов в предыдущий коммит. https://githowto.com/ru/amending_commits
git revert <коммит> - отмена какого-то коммита путём антикоммита: те же самые изменения этого коммита, но в обратную сторону. https://githowto.com/ru/undoing_committed_changes

git log - список произведённых изменений, предполагается использование алиаса:
git hist - то же самое, но в удобном виде (алиас).
gitk - визуальный просмотр списка коммитов.

git checkout <коммит> - перемещение в состояние: данного коммита, указателя на него (ветки), или тега на него (также всегда есть указатель на текущий коммит: HEAD)https://githowto.com/ru/getting_old_versions и ещё позволяет отменить непроиндексированные нежелательные изменения https://githowto.com/ru/undoing_local_changes
git reset HEAD <файл> - отмена проиндексированных изменений до коммита, но файлы не вернутся в исходное состояние, поэтому после надо выполнить git checkout <file> (эта команда при указании имени файла возвращает его в состояние, каким оно было в текущем коммите).
git reset --hard <коммит> - удаление коммитов до указанного (тем не менее остаются в репозитории до сборщика мусора). https://githowto.com/ru/removing_commits_from_a_branch

git tag <тег> - создание тега для текущего коммита, смысловое отличие от ветки, что статично привязан к коммиту. https://githowto.com/ru/tagging_versions
git tag - просмотр всех тегов.
git tag -d <тег> - удаление тега. https://githowto.com/ru/remove_the_oops_tag

git branch <ветка> - создание ветки (новые коммиты сдвигают текущую ветку).
git checkout -b <ветка> - создание ветки и переключение в неё (новые коммиты теперь сдвигают новую ветку).
git branch -d <ветка> - удаление ветки https://git-scm.com/book/ru/v2/Ветвление-в-Git-Управление-ветками

git merge <ветка> - сливает указанную ветку в текущую, в процессе могут быть конфликты слияния, которые надо решить. https://githowto.com/ru/resolving_conflicts
git rebase <ветка> - применить все коммиты в текущей ветке к указанной ветке (перенос коммитов). (НЕ ВЫПОЛНЯТЬ В ОБЩУЮ ВЕТКУ НА УДАЛЁННОМ РЕПОЗИТОРИИ!)

git remote add origin https://github.com/<имяпользователя>/<репозиторий>.git - добавляет удалённый репозиторий origin (ссылка взята со страницы только что созданного репозитория на github, то есть сперва создаётся репозиторий на github, а потом уже подключается на компьютере).
git push -u origin master - отправить коммиты из ветки master на удалённый репозиторий, флаг -u связывает локальную и удалённую ветку, и потом можно просто делать git push (и аналогичные команды работы с удалённым репозиторием).
git push origin master - выгрузить изменения из ветки master в удалённый репозиторий origin, возможно только если там не появилось новых изменений, которые сперва надо загрузить себе, объединить со своей веткой, и потом уже выгрузить (потому что сливать можно только merge fast-forward коммитом, которого по факту нет, так как сервер свои коммиты создавать не может, а при изменениях с обеих сторон потребуется merge-коммит всё равно, и поэтому сервер так сам (истинным merge-коммитом) слить не сможет https://habr.com/ru/post/136847/ ).
git fetch origin - получить изменения из origin. https://git-scm.com/book/ru/v2/Ветвление-в-Git-Удалённые-ветки
git pull origin master - равнозначно git fetch origin и потом git merge origin

Объединять ветки обычно предполагается с помощью merge, но иногда коммиты слияния веток из 1-2 коммитов, а также регулярные (пусть даже и нужные) подливания из ветки master в другие, ведут к хаосу и замусориванию истории merge-коммитами. https://habr.com/ru/post/161009/ http://svyatov.ru/2013/02/git-merge-vs-rebase/
Поэтому для объединения иногда используется rebase, одно из лучших условий: у сливаемой ветки 1-3 коммита. Суть в следующем: сперва используется команда
git pull --rebase origin master - равнозначно git fetch origin, затем master перемещается к origin/master через fast-forward, и те локальные коммиты, что были в master, начинают последовательно применяться.
Процесс rebase содержит количество шагов равное количеству коммитов в вашей локальной ветке.
git rebase --abort - отменить процесс rebase
Если возникли конфликты, то решить их, затем проиндексировать нужные файлы для коммита и
git rebase --continue - продолжить процесс rebase после конфликта
git rebase --skip - пропустить ненужный коммит (если вдруг оказалось, что он полностью исключает какой-нибудь из предыдущих коммитов, и этот коммит делать не надо, то есть нужен при выборе между тем что было уже раньше, и тем что сейчас применяем, и пониманием что текущий коммит вообще не нужен)

Для отмены неудачного rebase, да и вообще любого действия существует команда:
git reflog - показ всех изменений, можно переключиться на любую точку в истории, то есть откатиться на неё. https://git-scm.com/book/ru/v2/Git-изнутри-Уход-за-репозиторием-и-восстановление-данных


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

Модель Trunk-Based Development.
1. Ветки живут очень малое время и содержат минимальное количество коммитов, нужных для реализации части улучшения.
2. Файл конфигураций с флагами улучшений. Для каждого улучшения есть флаг, который его включает/выключает. До полного завершения реализации флаг по умолчанию выключен.
3. В ветке реализуется не улучшение, а его часть, абстракция. Например нужно сменить способ выполнения какой-то логики. Путь абстракций будет таким: выделить логику в абстракцию -> добавить в этой абстракции другую логику -> сделать по умолчанию в абстракции выбор новой логики. Получившуюся в ходе улучшения абстракцию можно оставить для будущих изменений. Каждый этап - это отдельная ветка, и поэтому код, написанный в ней, сразу становится общим по ходу завершения реализации абстракции.

Исходя из этого, программа всегда имеет актуальную версию и реализованные части улучшений. Но для этого нужно иметь ответственность за каждое слияние ветки с основной (master), используя тестирование и код-ревью, чтобы система оставалась стабильной. И внимательно следить за файлом конфигураций.

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