Syntax highlighting of 9bd7069 ~( git)

# GIT

[TOC]

## Полезные команды

### Конфигурация

```bash
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
# --- Установка редактора для коммитов
git config --global core.editor "vim"
# --- Храним доступы в файле ~/.git-credentials
#     Доступы сохраняются там автоматически
git config --global credential.helper store
```

### Клонирование и слияние
```bash
# Клонирование крайнего коммита
git clone --depth=1 URL
# "Переход" к конкретному коммиту
git checkout [revision] .
# "Переход" на крайний коммит
git checkout -
# --- слияние со "схлопываением" коммитов
git checkout master
git merge --squash feature123
git commit -m 'merged feature #123'
# --- "перетаскивание файлов между ветками
git checkout gh-pages # переходим в целевую ветку gh-pages
git checkout master -- myplugin.js # "забираем" файл из ветки master
git commit -m "Update myplugin.js from master" # фиксируем изменения
```

### Меняем историю

[git rebase about](https://www.atlassian.com/ru/git/tutorials/rewriting-history/git-rebase)
```bash
# схлопываем 3 коммита через rebase (в редакторе выбираем squash)
git rebase -i HEAD~3
# перетаскиваем коммит в ТЕКУЩУЮ ветку
git cherry-pick <commithash>
```

### Журнал и история
```bash
# Список коммитов по автору
git log --author="John Smith"
# история изменений файла
git log -- app/some/file.rb
# отображение изменений конкретного файла
git log --all --full-history -- <path/to/file>
# отображение файла из заданного коммита
git show $REV:$FILE
# поиск по commit сообщению
git log --all --grep='Build 0051'
# вывод журнала в виде графа с изменением формата
git log --pretty="format:%H %s" --graph
```

### Отображение изменений

```bash
# отображение отслеживаемой ветки
git branch -vv
# Отображение хэша крайнего коммита
git rev-parse HEAD
# Отображение всех измененных файлов в текущей и develop ветвях .
# Можно использовать опцию --name-only
git diff --name-status develop
# Отображение измененных файлов только ветви notMainDev
# Если ветвь notMainDev влита, то ничего не выводится
git diff --name-only <notMainDev> $(git merge-base <notMainDev> <mainDev>)
# то же, но короче
git diff --name-only mainDev...
# статусы
#   `A`  Added
#   `C`  Copied
#   `D`  Deleted
#   `M`  Modified
#   `R`  Renamed. Статус может дополняться числом, например R100
#   `T`  have their type (mode) changed
#   `U`  Unmerged
#   `X`  Unknown
#   `B`  have had their pairing Broken
#   `*`  All-or-none

# Отображение изменений коммита
git show <revhash>
```

### Индекс и откат

```bash
# Удаление файла из кэша
git rm --cached some-file
# Удаление директории из кэша
git rm --cached -r some-directory
# remove all files from git cache
git rm -r --cached .
git add .
git commit -m ".gitignore is now working"
# --- откат изменений
git clean -f
git checkout -- *
# Изменение сообщения крайнего коммита
git commit --amend
# Мягкий откат коммита - файлы остаются скорректированными, отменена процедура коммита
git reset --soft HEAD^
# жесткий откат
git reset --hard HEAD^
# отмена индексации, был зеленый - стал красный
git reset HEAD filename
```



### Прячем изменения

```bash
# --- прячем изменения
git stash
# --- список спрятанных изменений
git stash list
# --- "вытащить" спрятанные изменения в текущей ветке
git stash apply
# --- "вытащить" изменения через указания индекса в списке
git stash apply stash@{2}
```

### Метки
```bash
# Создание метки (тэга)
git tag -a 1.0.1 -m "Version 1.0.1"
# Создание метки для коммита
git tag -a 0.2.0 9fceb02 -m "Version 0.2.0"
# Загрузка метки в репозиторий
git push origin 1.0.1
# Удаление метки из локального репозитория
git tag -d 1.0.2
# Удаление метки из удаленного репозитория
git push origin :refs/tags/1.0.2
# Список меток с сообщениями
git tag -l --format='%(tag) %(subject)'
# --- создаем ветку из тега
git fetch --all --tags
git checkout tags/v1.0 -b v1.0-branch
```

### Submodules
```bash
# https://git-scm.com/book/ru/v2/Инструменты-Git-Подмодули
# Добавление подмодуля в проект
git submodule add REPO_URL PATH
# отображение изменений
git diff --cached SUBMODULE
# клонирование репозитория с подмодулями
git clone REPO-URL
cd repo/submodule/dir
git submodule init
git submodule update
# тоже одной командой
git clone --recursive REPO-URL
# обновление модуля
cd submodule/dir
git fetch
git merge origin/master
# --- обновление всех модулей в repo
# @note Если необходимо обновится не из master, то в файле .gitmodules
# в соответствующей секции модуля необходимо добавить branch = ..., напр:
# branch = stable
git submodule update --remote
# отображение изменений в модуле
cd ../repo/root/dir
git diff --submodule
# конфигурация для отображения изменений в модулях командой git diff (без --submodule)
git config --global diff.submodule log

# --- если в проект добавлен git-модуль, то при выполнии git pull
#     будет создана директория для модуля, но она будет пустая.
#     Чтобы ее "заполнить", необхомо выполнить команды
git submodule init
# Подмодуль «.path/or/name/of/submodule» (remote url) зарегистрирован по пути «./»
git submodule update

# cd dir/with/new/git-module
# git submodule init
# Подмодуль «.path/or/name/of/submodule» (remote url) зарегистрирован по пути «./»
# git submodule update
# Клонирование в ...
```

[Удаление submodule](https://gist.github.com/myusuf3/7f645819ded92bda6677)

-   Delete the relevant section from the .gitmodules file.
-   Stage the .gitmodules changes `git add .gitmodules`
-   Delete the relevant section from .git/config.
-   Run `git rm --cached path_to_submodule` (no trailing slash).
-   Run `rm -rf .git/modules/path_to_submodule` (no trailing slash).
-   Commit `git commit -m "Removed submodule"`
-   Delete the now untracked submodule files `rm -rf path_to_submodule`

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

[Conventional Commits](https://www.conventionalcommits.org/ru/v1.0.0-beta.2/)

https://git-scm.com/book/ru/v2

https://stackoverflow.com/questions/67699/how-to-clone-all-remote-branches-in-git

## Полезные утилиты

### gitk 
Графический интерфейс для git
https://stackoverflow.com/questions/1786027/how-to-view-file-history-in-git
```bash
sudo apt install gitk
# show file change histroy
gitk path/to/file
```

## Credentials

При работе с git по http/https можно зафиксировать имя пользователя и включить временное запоминание пароля.

[StackOverflow](https://stackoverflow.com/questions/10054318/how-to-provide-username-and-password-when-run-git-clone-gitremote-git)

```bash
git config --global credential.helper cache
git config --global credential.https://github.com.username foo
git clone ...
```

Глобальная конфигурация

```ini
~/.gitconfig
[color]
	ui = true
[user]
	name = Nik Mikhaylichenko
	email = nn.mikh@yandex.ru
[credential "https://github.com"]
	username = nmix
```

Локальная конфигурация

```ini
# .git/config
[user]
	name = Николай Михайличенко
	email = n.mihailichenko@krasnodar.pro
[credential]
	username = zoid
```

## Изменение commit message

```
git commit --amend
git push --force
```

# Troubleshooting

## fatal: Needed a single revision

При обновлении git-модулей для одного из модулей получаем ошибку
```bash
git submodule update --remote
# ...
fatal: Needed a single revision
```
Проблема оказалось в том, что автор модуля toml переименовал ветку master в ветку main
Необходимо прописать наименовании новой ветки в конфигурации модуля
```git
# .gitmodules
[submodule ".vim/bundle/vim-toml"]
	path = .vim/bundle/vim-toml
	url = https://github.com/cespare/vim-toml.git
	branch = main  # <------------------
```


## если что-то не работает

`GIT_TRACE=1 GIT_SSH_COMMAND="ssh -vvv" git clone https://git.example.com/my/app.git app`

## sign_and_send_pubkey

При попытке залить изменения на сервер, получаем ошибку
```bash
git push -u origin master 
sign_and_send_pubkey: signing failed: agent refused operation
git@bitbucket.org: Permission denied (publickey).
fatal: Не удалось прочитать из внешнего репозитория.

Удостоверьтесь, что у вас есть необходимые права доступа
и репозиторий существует.
```

Ошибка связана с некорректным файлом *~/.ssh/id_rsa*, либо правами доступа к нему.

```bash
ssh-add
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/zoid/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
```

Необходимо скорректировать права доступа к файлу и повторить операцию
```bash
chmod 700 .ssh/id_rsa
ssh-add
Enter passphrase for /home/zoid/.ssh/id_rsa:
...
Identity added: ...
```