GIT

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

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

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

Ветвление

# --- удаление веток по шаблону
git branch | egrep "KDK-[0-9]+" | xargs git branch -D
# --- фиксируем изменения из detached-ветки
#      шаблон: git push <remote name> HEAD:<remote branch name>
git push origin HEAD:master

Клонирование и слияние

# Клонирование крайнего коммита
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

# --- схлопываем 3 коммита через rebase (в редакторе выбираем squash)
git rebase -i HEAD~3
# --- перетаскиваем коммит в ТЕКУЩУЮ ветку
git cherry-pick <commithash>

# --- удаляем историю
#     источник: https://xebia.com/blog/deleting-your-commit-history/
git checkout --orphan temp_branch
git add -A
git commit -m "Initial commit"
git branch -D main
git branch -m main
git push --force origin main

Журнал и история

# Список коммитов по автору
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

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

# отображение отслеживаемой ветки
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>

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

# Удаление файла из кэша
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

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

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

Метки

# Создание метки (тэга)
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

# 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

  • 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://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

sudo apt install gitk
# show file change histroy
gitk path/to/file

Credentials

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

StackOverflow

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

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

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

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

# .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-модулей для одного из модулей получаем ошибку

git submodule update --remote
# ...
fatal: Needed a single revision

Проблема оказалось в том, что автор модуля toml переименовал ветку master в ветку main Необходимо прописать наименовании новой ветки в конфигурации модуля

# .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

При попытке залить изменения на сервер, получаем ошибку

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

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

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

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.

Необходимо скорректировать права доступа к файлу и повторить операцию

chmod 700 .ssh/id_rsa
ssh-add
Enter passphrase for /home/zoid/.ssh/id_rsa:
...
Identity added: ...