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 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" # фиксируем изменения
Меняем историю
# схлопываем 3 коммита через rebase (в редакторе выбираем squash)
git rebase -i HEAD~3
# перетаскиваем коммит в ТЕКУЩУЮ ветку
git cherry-pick <commithash>
Журнал и история
# Список коммитов по автору
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
# Клонирование в ...
- 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
Полезные ссылки
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 можно зафиксировать имя пользователя и включить временное запоминание пароля.
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: ...