====== Git ======
# Для начала надо настроить имя и email для авторизации.
git config --global --edit # либо
vi ~/.gitconfig # либо способом <поле> <значение>
git config --global user.name ivanpetrov
git config --global user.email i.petrov@example.com
# Некоторые поля для настройки
# core.editor - редактор сообщений коммитов
# commit.template - шаблон, используемый при каждом коммите
# alias - псевдоним, например, после
git config --global alias.st "status -s" # можно будет писать
git st # вместо
git status -s
# Прокси
git config --global http.proxy http://proxy.example.com:3128
git config --global https.proxy http://proxy.example.com:3128 # именно http://, иначе будет ошибка "An unexpected TLS packet was received"
# Вывести все поля с их значениями
git config --list
git init # создать репозиторий
git clone # копировать репозиторий
В своих обычных операциях Git [[https://git-scm.com/book/ru/v2/%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B-Git-%D0%A0%D0%B0%D1%81%D0%BA%D1%80%D1%8B%D1%82%D0%B8%D0%B5-%D1%82%D0%B0%D0%B9%D0%BD-reset|управляет тремя деревьями]] (разделами):
- HEAD - Последний коммит в репозитории
- Индекс - Снимок следующего намеченного коммита (staging area, подготовленные файлы)
- Рабочий каталог - локальная рабочая папка
''git status'' показывает файлы и их статус (с ключом ''-s'' - сокр. тип вывода):
* Untracked - левый файл, git о нём не знает (с ключом ''-s'' - ??).
* Modified - изменён, но не находится на очереди для коммита (с ключом ''-s'' - красный).
* Staged - готов к коммиту (с ключом ''-s'' - зелёный).
* Unmodified - изменений нет, актуальная версия.
===== Изменения/сравнения =====
git diff # сравнение рабочего каталога с индексом (область подготовленных файлов)
git diff --staged # сравнить индекс с HEAD (непроиндексированные изменения показаны не будут)
git diff folder/ # показать изменения только для указанной папки
===== Обновление/коммит =====
git add # обновить область подготовленных файлов новой версией файла/папки
git commit # обновить HEAD
===== Игнорирование =====
Файлы с паролями и т. п. - файл ''.gitignore''.
# ignores all .txt files JUST in the current folder
*.txt
# ignores all .txt recursive from the current folder
**.txt
# ignores all .txt in subdirectories recursive from the current
# folder (does not include the current folder)
**/*.txt
# ignore files only in the directory with the .gitignore file - leading “/”
/*.txt
# A .gitignore file in the root directory with these contents:
/content/*.txt
# will ignore all .txt files in the content directory. It will not ignore .txt files in the subdirectories of the content directory.
https://www.quora.com/Does-gitignore-file-only-work-on-current-folder\\
https://www.atlassian.com/ru/git/tutorials/saving-changes/gitignore
===== Удалённые репозитории =====
git remote -v # список удалённых репозиториев с заданными именами
git remote add # добавить удалённый репозиторий с заданным именем
git remote remove
git remote rename
git remote set-url # новый адрес
git remote show # инфо о репозитории
git fetch # получить данные ветки, но не сливать изменения
git pull # слить данные ветки
git push # отправить изменения в ветку
# Если локальная ветка уже отслеживает удалённую, то можно просто
git push
git pull
Перенастроить локальный репозиторий с одного удалённого на другой
git remote show # показать название удалённого репозитория
origin
git remote get-url origin # показать ссылку
git remote set-url origin # установить новую
===== Коммиты =====
Коммит - это некий снапшот ФС и отсылки на предыдущие снапшоты. Содержит контрольную сумму, которую git использует для ссылки на него.
git commit # открыть редактор для сообщения в коммите
git commit -m "Bug fixed" # можно и без редактора
git commit -a # Коммитить модифицированные файлы напрямую, минуя стадию stage (git add в этом случае не нужен)
git commit -amend # заменить последний коммит - на случай, если коммит ошибочен
git revert # создать новый коммит, откатывающий изменения последнего (история сохраняется)
git reset # откатить коммит с перемещением указателя HEAD (без сохранения истории).
# Опции: --mixed (по умолчанию) - изменения станут неиндексированными, --soft - индексированными, --hard - полная отмена изменений.
# бесследный откат последнего коммита
git reset --hard HEAD~1
# --force - для того, чтобы игнорировать предупреждение о том,
# что удалённый репозиторий новее
git push --force
https://proglib.io/p/sravnenie-5-komand-git-revert-checkout-reset-merge-i-rebase-2020-05-25
На коммит можно ссылаться как через контрольную сумму, так и на позицию относительно HEAD, например, ''HEAD~3'' - 3 коммита назад.
Перенос коммита, например, если он был отправлен не в ту ветку, можно сделать командой ''[[https://www.atlassian.com/git/tutorials/cherry-pick|git cherry-pick]]''. Список коммитов можно получить с помощью ''git log master..test''.\\
''git log master..foo'' will show the commits that are on foo and not on master. Helpful for seeing what commits you've added since branching!
С откатыванием коммитов слияния сложнее. [[https://www.youtube.com/watch?v=_O6uANApwH0|2 Ways to Undo Merge Commits]]
Куча мелких коммитов делает историю проекта замусоренной, что важно при слиянии веток. Их можно объединить в один.
# интерактивное сжатие
git cherry -v main # показать сделанные коммиты в сравнении с веткой main
git rebase -i HEAD~3 # -i - интерактивно, объединить последние 3 коммита
# pick - первый коммит
# squash - коммиты, которые будут слиты с первым
# сжатие при слиянии веток - коммиты из feature будут объединены и слиты с текущей веткой
git merge --squash feature
===== Ветки =====
Ветки - версии проекта. По умолчанию - master или main. Лучше называть понятно в соответствии с предназначением - release, dev, test и т. д. Переключение между ветками - это перемещение указателя HEAD в HEAD соответствующей ветки.
git branch dev # создать новую ветку dev
git checkout dev # переключиться на ветку dev
git checkout -b dev # создать ветку и переключиться на неё
git branch -d dev # удалить
Когда отслеживается удалённый репозиторий, то отслеживается удалённая ветка. Команда ''git clone'' привязывает локальную ветку master к ветке origin/master удалённого репозитория.
git branch -u origin/serverfix # привязать текущую ветку к удалённой ветке serverfix репозитория origin
git checkout --track origin/serverfix # то же самое
git checkout -b serverfix origin/serverfix # создать локальную ветку и отслеживать удалённую
git branch -vv # показать локальные и отслеживаемые удалённые ветки
git checkout origin/serverfix # создать одноимённую локальную ветку и отслеживать удалённую
''git checkout'' меняет место указания HEAD по аналогии с ''git reset'', который его перемещает.
Слияние веток (merge) - создание коммита, указывающего HEADs как предков из двух предыдущих веток - основной и тематической. Для слияния нужно
# Переключиться на основную ветку main
git checkout main
# и выполнить слияние с веткой feature
git merge feature
{{:service:pasted:20220721-132004.png}}
Если обе ветки меняют одну и ту же часть кода, то возникает конфликт, т. к. git не знает, что нужно оставить, необходимо ручное вмешательство. Конфликтующие файлы выводятся командой ''git status''. В этих файлах будут маркеры с цитатами из обоих веток, нужно оставить там то, что нужно. После разрешения конфликтов можно коммитить -''git commit''.
Rebase - копирует коммиты тематической ветки в основную, как если бы они там и были.\\
{{:service:pasted:20220721-134136.png}}
# копировать изменения ветки feature на ветку main
git rebase main feature
Merge создаёт некий хаос в логах истории. Rebase в этом плане более последователен, но копированные коммиты всё равно будут другими, хотя и идентичными по содержанию.
==== Изменить ссылку на удалённый репозиторий (для переезда на другой сервер) ====
git remote show # показать имя удалённого репозитория
git remote get-url origin # показать ссылку
git remote set-url origin git@example.com:username/repo.git # установить новую ссылку
git push # отправить данные в новый удалённый репозиторий
==== Создать ветку локально и затем создать её на удалённом сервере ====
git checkout -b new-branch
git branch -u origin/new-branch
git push
===== Просмотр изменений =====
git log -p # показать изменения в каждом коммите
git log -stat # вывести краткую статистику для коммитов - изм. файлы, кол-во изм. строк
git log -7 # 7 посл. коммитов
git log -since="2022-01-01" # коммиты в 1 янв 2022. Также есть -until=
git log -pretty=format:"%h %s" # тонкая настройка формата логов
git log -grep string # поиск добавления/удаления строки в сообщениях и строках кода (также параметр -S)
git log --author= --no-merges # коммиты определённого автора без коммитов слияния веток
git log main..test # каких коммитов из test нет в main
git log --left-right main..test # показать уникальные коммиты для обеих веток, где они расположены
git log -L,: # история изменений набора строк в файле
git blame -L 1,5 README.md # Кто вносил изменения в диапазон указанных строк
git grep # поиск по регулярке по всем файлам в истории коммитов -n - показать номер строки, -c - кол-во совпадений
https://git-scm.com/docs/git-log/2.21.0#Documentation/git-log.txt
===== Схема =====
{{:service:pasted:20240529-093727.png?800}}
**Clone and Checkout**
In order to start making changes, you must first clone and checkout the repository, and then create a branch to begin your edits.\\
On your local terminal, the commands or these actions are:
git clone
# or
git checkout -b
**Add and Commit**
To make additions to your branch, you will use the following commands:
# Stage the file
git add
# Run git status
git status
# Commit the file
git commit -m "commit message"
# Run git status
git status
# Push the commit to the remote
git push origin
# and for an initial push to branch
git push -u origin...
# Run git status
git status
# View the git log
git log
===== Советы =====
* Одно изменение - один коммит. Так проще откатиться.
* Сообщение коммита - заголовок меньше 50 символов, в повелительном наклонении "add a new feature". Сообщение должно объяснять, почему коммит был сделан.
* При разработке делать небольшие коммиты, а при добавлении в репозиторий объединять их в один.
===== Ошибки/проблемы =====
==== Ругань на SSL-сертификат ====
[[https://ru.stackoverflow.com/questions/458822/%D0%9F%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D0%B0-%D1%81-ssl-%D0%BF%D1%80%D0%B8-%D0%BA%D0%BB%D0%BE%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8-%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB%D0%B8%D1%89%D0%B0|Варианты решения]]:
- Использовать SSH при работе с git
- Отключить проверку ssl сертификата при клонировании GIT_SSL_NO_VERIFY=true git clone /path/to/repo
- Отключить проверку ssl сертификата глобально git config --global http.sslVerify false
- Если сертификат самоподписанный - найти инструкцию по добавлению самоподписанного сертификата в доверенные
===== Литература =====
[[https://www.youtube.com/watch?v=9oDNBuive-g|Let's git started together!]] (Youtube) - review the Git concepts, explained by one of the GitLab's Developer Evangelist\\
https://dangitgit.com/ru - варианты исправления/отката ошибок\\