Содержание

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 <repo address> # копировать репозиторий

В своих обычных операциях Git управляет тремя деревьями (разделами):

  1. HEAD - Последний коммит в репозитории
  2. Индекс - Снимок следующего намеченного коммита (staging area, подготовленные файлы)
  3. Рабочий каталог - локальная рабочая папка

git status показывает файлы и их статус (с ключом -s - сокр. тип вывода):

Изменения/сравнения

git diff # сравнение рабочего каталога с индексом (область подготовленных файлов)
git diff --staged # сравнить индекс с HEAD (непроиндексированные изменения показаны не будут)
git diff folder/ # показать изменения только для указанной папки

Обновление/коммит

git add <file/folder> # обновить область подготовленных файлов новой версией файла/папки
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 <name> <url> # добавить удалённый репозиторий с заданным именем
git remote remove <name>
git remote rename <old name> <new name>
git remote set-url <name> <url> # новый адрес
git remote show <name> # инфо о репозитории
 
git fetch <name> <branch> # получить данные ветки, но не сливать изменения
git pull <name> <branch> # слить данные ветки
git push <name> <branch> # отправить изменения в ветку
# Если локальная ветка уже отслеживает удалённую, то можно просто
git push
git pull

Перенастроить локальный репозиторий с одного удалённого на другой

git remote show # показать название удалённого репозитория
origin
git remote get-url origin # показать ссылку
git remote set-url origin <url> # установить новую

Коммиты

Коммит - это некий снапшот ФС и отсылки на предыдущие снапшоты. Содержит контрольную сумму, которую 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 коммита назад.

Перенос коммита, например, если он был отправлен не в ту ветку, можно сделать командой 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!

С откатыванием коммитов слияния сложнее. 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

Если обе ветки меняют одну и ту же часть кода, то возникает конфликт, т. к. git не знает, что нужно оставить, необходимо ручное вмешательство. Конфликтующие файлы выводятся командой git status. В этих файлах будут маркеры с цитатами из обоих веток, нужно оставить там то, что нужно. После разрешения конфликтов можно коммитить -git commit.

Rebase - копирует коммиты тематической ветки в основную, как если бы они там и были.

# копировать изменения ветки 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=<name> --no-merges # коммиты определённого автора без коммитов слияния веток
git log main..test # каких коммитов из test нет в main
git log --left-right main..test # показать уникальные коммиты для обеих веток, где они расположены
git log -L<start>,<end>:<file> # история изменений набора строк в файле
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

Схема

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 <clone with ssh>
# or 
<clone with https>
git checkout -b <branchname>

Add and Commit

To make additions to your branch, you will use the following commands:

# Stage the file
git add <file>
# 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 <your_new_branch>
# and for an initial push to branch
git push -u origin...
# Run git status
git status
# View the git log
git log

Советы

Ошибки/проблемы

Ругань на SSL-сертификат

Варианты решения:

  1. Использовать SSH при работе с git
  2. Отключить проверку ssl сертификата при клонировании
    GIT_SSL_NO_VERIFY=true git clone /path/to/repo
  3. Отключить проверку ssl сертификата глобально
    git config --global http.sslVerify false
  4. Если сертификат самоподписанный - найти инструкцию по добавлению самоподписанного сертификата в доверенные

Литература

Let's git started together! (Youtube) - review the Git concepts, explained by one of the GitLab's Developer Evangelist
https://dangitgit.com/ru - варианты исправления/отката ошибок