GIT F.A.Q
- Визуальный справочник: http://marklodato.github.io/visual-git-guide/index-ru.html
- Интерактивный курс по использованию GIT - http://githowto.com/
Статья-сборник примеров решения частых задач при использовании GIT - работа с историей изменений, создание, удаление, публикация веток, удаленные (remote) репозитории git, сокрытие и отмена локальных изменений, просмотр информации о коммитах и истории...
F.A.Q по GIT дополняется..
Полезные ссылки:
Внимание!
С 15 марта 2022 github прекращает авторизацию по ключам DSA и запрещает доступ по незашифрованному git:// протоколу!
Замените ссылки на репозитории:
git remote set-url origin https://github.com/vendor/package.git
Ранее загруженные RSA ключи будут продолжать работать с SHA-1.
Основные команды
Слить внешние изменения с заменой локальных:
git pull -X theirs
Разрешить конфликт принимая внешние изменения:
git checkout --theirs file
Стратегии pull/push
При запуске pull/push без указания веток вы можете выбрать желаемую стратегию (поведение Git). Стратегия определяет что будет делать Git при запросе на получение или отправку изменений без явного указания веток.
Установить стратегию для pull/push:
git config pull.default simple # локальный конфиг
git config --global pull.default simple # глобальный конфиг
git config --global push.default simple
Доступные стратегии:
simple Текущая ветка (при условии что имя удаленной ветки такое же)
matching Все ветки, имена которых совпадают
<alias> Явно указать имя ссылки на удаленный репозиторий
current Deprecated! Переименован в simple со 2й версии Git. При current обновляются ВСЕ ветки!
Поведение git pull
После какого-то обновления Git, вы можете наблюдать сообщение запуске pull без явного указания веток: If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/stage-api-fast-filters. Это означает, что вам необходимо связать текущую ветку с удаленной.
Мы знаем, что в локальном git хранилище могут быть ссылки на несколько удаленных репозиториев, которые имеют ветки с одинаковым названием. При этом, сходство имен локальной ветки и ветки в каком-нибудь удаленном репозитории - никак не могут однозначно указывать на родство этих веток. Поэтому, вам нужно явно указать связь локальной ветки с удаленной:
git branch --set-upstream-to=origin/their_branch my_branch
В дальнейшем, при создании веток, сразу связывайте новую ветку с удаленной:
git branch my_branch origin/their_branch
## или
git checkout -b my_branch origin/their_branc
Поведение git push
При попытке отправить изменения на сервер без явного указания веток, вы можете видеть сообщение: warning: push.default is unset (не указана стратегия или ссылка на репозиторий по умолчанию). Вам необходимо задать желаемое поведение при запуске git push без параметров в конфиге с помощью опции push.default
:
git config --global push.default simple
Индекс
Отменить индексацию файла (сам файл не будет удален из каталога):
git rm --cached <file>
git rm -r --cached <some/directory/> # или каталога
Игнорировать (не отслеживать) последующие изменения файла:
git update-index --assume-unchanged app/database/production.sqlite
Для отмены игнора:
git update-index --no-assume-unchanged app/database/production.sqlite
Смотрим список файлов изменения в которых игнорируются git'ом:
git ls-files -v | grep '^h'
Удалить из индекса все удаленные файлы:
git status --porcelain | grep ' D' | awk '$1 == "D" {print $2}' | xargs git rm --cached
История коммитов
- Показать историю коммитов со статистикой по файлу (список файлов и количество измененных строк):
git log --stat <some/file_or_dir>
- Краткая история коммитов определенного пользователя в формате
hash comment
: git log --author=author@onedev.net --pretty=oneline
- Последние 10 коммитов автора с комментариями:
git log --author=author@onedev.net --pretty=oneline -10
- Список коммитов, которые не отправлены в удаленный репозиторий:
git log origin/имя_ветки.. git log --branches --decorate --not --remotes=origin # во всех ветках
- Компактная история коммитов (хеш дата <автор> | коммент):
http://git-scm.com/book/ru/Основы-Git-Просмотр-истории-коммитовgit log --pretty=format:"%h %ad <%an> %s" --date=short
- Одно строчный формат истории коммитов с информацией об авторах:
git log --pretty=format:"%h %ad %an <%ae>" --date=short
История изменений
Показать изменения не внесенные в индекс:
git diff file_name
Показать изменения внесенные в индекс:
git diff --cached file_name
Показать внесенные вами изменения с последнего коммита:
git diff HEAD
Список измененных файлов от указанного коммита до текущего состояния:
git diff --name-only <HASH>
Список изменений из одного определенного коммита:
git diff <HASH>^ <HASH>
Список изменений от определенного коммита до последнего (текущего состояния):
git diff <HASH>^ HEAD
Расширенный поиск
Как найти ветку по коммиту:
git branch --contains <commit>
Как найти самый первый коммит по определенному тексту (может занять много времени):
git grep 'some text' $(git rev-list --all) | tail -n 1 | cut -c -10
Как найти самый первый коммит, в котором добавили файл:
git log --diff-filter=A -- path/file.php
Репозитории
Информация об удаленных репозиториях:
git remote -v # показать алиасы и URL удаленных репозиториев
git remote show origin # детальная инфа об удаленном репозитории
Добавление и удаление удаленных репозиториев:
git remote add <алиас> <URL>
git remote rm origin
Пример
git remote add origin git@github.com:vendor/repo-name.git
Изменить url удаленного репозитория при ошибке:
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
git remote set-url origin git@github.com:vendor/repo.git
git remote set-url origin git://github.com/vendor/repo.git
Ветки / branch
Посмотреть все ветки репозитория:
git branch -a
git branch -r # ветки на сервере
Создать удаленную ветку на сервере:
git push origin origin:refs/heads/new_branch
Создать/получить локальную ветку my_branch на основе удаленной their_branch:
git checkout -b my_branch origin/their_branch # создать новую ветку
git checkout --track origin/their_branch # cвязать текущую ветку с репом
Опубликовать локальную ветку в удаленном репозитории:
git push origin some_branch:some_branch
git push -u origin my_branch ## опубликовать текущую ветку и связать эти ветки
Примечание
При первой публикации ветки необходимо указывать имя удаленной ветки для того, чтобы связать локальную и удаленные ветки. При последующих pull'ах имя удаленной ветки можно опускать.
Переименовать текущую ветку:
git branch -m new-branch-name
Удалить ветку в удаленном репозитории:
git push origin :some_branch
Удалить локальную ветку:
git branch -d some_branch
Сокрытие изменений
Скрыть рабочие изменения (изменения вносятся в стек):
git stash
Будут скрыты только изменения файлов, которые находятся в индексе. Новые файлы не будут скрыты (перемещены в стек/тайник) - заначка.
Посмотреть список тайников (стек спрятанных изменений):
git stash list
Применить (вернуть из тайника) последнюю заначку:
git stash apply
Применить одну из старых заначек:
git stash apply stash@{2}
Показать все содержимое тайника:
git stash show
Удалить все тайники:
git stash clear
Отмена изменений
- Отменить последний коммит:
git reset --soft HEAD^
Примечание
Внесенные изменения будут сохранены. Это сработает только в том случае, если вы еще не опубликовали свои изменения!
- Отменить все изменения в файле до последнего коммита:
Внимание!
Вы НЕ сможете восстановить изменения после этой команды! Убедитесь, что вы отменяете изменения в нужном файле.git checkout -- Controller/ContentController.php
Отменить конфликтный merge:
git reset --hard HEAD
Получить версию файла из определенной ветки:
git checkout some-branch -- file.txt
- Восстановить файл из указанного коммита:
git log --pretty=oneline # смотрим список коммитов, выбираем нужный и ... git checkout 129c39e9b93a19c app/controllers/Controller.php # Возвращаем нужный нам файл
- Извлечь определенную версию файла из истории GIT в указанный путь
git show 129c39e9b93a19c:app/controllers/Controller.php > ~/Controller.php
Отменить последний коммит, который ушел на сервер:
git revert HASH
git revert REVERT-HASH # вернуть коммит ("отменить отмену" коммита)
* Команда revert собирает patch отражающий нужный коммит, разворачивает его и добавляет новый коммит для отката (коммит, конечно же, будет видет виден в истории). Таким образом, при merge и push нет необходимости использовать --force.
Отменить 3 последних коммита, которые уже ушли на сервер:
git reset --hard HEAD^^
git push --force origin origin some-branch
Внимание!
Не используйте без критической на то необходимости --force:
git push --force origin origin some-branch
Это единственная команда Git, которая делает необратимые изменения!
Вообще, делать reset --hard или rebase в опубликованной истории крайне не желательно. Лучше создать новую ветку, собрать в ней нужное состояние и слить ее с вашей веткой.
Откатить коммиты и оставить изменения в виде не проиндексированных:
git reset --mixed HEAD^^
Конфликты
Слить ветки предпочитая чужие изменения (-X
, --strategy-option
):
git merge -X theirs some_branch
Оставить локальную версию конфликтного файла (из текущей локальной ветки) или принять изменения из другой ветки (или ветки удаленного репозитория):
git checkout --ours file.php # оставить файл текущей (локальной) ветки
git checkout --theirs file.php # принять изменения из вливаемой ветки
Конфликтные участки кода:
<<<<ours
Наши изменения
========
Чужие изменения
theirs>>
Изменение истории коммитов
cherry-pick
Влить определенный коммит в текущую ветку (наложить патч, из любой ветки):
git cherry-pick <hash>
rebase
Источник (спасибо автору за разъяснение): http://tonyganch.com/git/rebase/
Внимание!
git rebase меняет hash коммитов! Поэтому, git rebase можно делать только в локальном репозитории, и только до публикации коммитов (push)!
Слияние коммитов
Начать процесс интерактивного слияния 2-х последних коммитов:
git rebase -i HEAD~2
Примечание
После запуска rebase - откроется текстовый редактор. Сверху идут старые коммиты, внизу более свежие.
Доступные действия с коммитами в текстовом редакторе:
pick, p
- Указать как основной коммит-приемник при слиянии.
fixup, f
- Слить коммиты, используя комментарий основного pick-коммита.
squash, s
- Слить коммиты вместе с их комментариями.
reword, r
- Изменить комментарий коммита. Укажите только опцию
r
, а имя коммита вы укажете при выходе из интерактивного режима.
Для удаления коммита - просто удалите строку в интерактивном редакторе коммитов.
Управление процессом rebase
Отменить незавершенный rebase:
git rebase --abort
Откатить успешный rebase можно только с помощью reset --hard:
git reflog # ищем состояние с нужным head коммитом
git reset --hard HEAD@{5} # сбрасываем текущую ветку к этому коммиту
* git log HEAD@{5} # можно проверить историю для старого head коммита
Продолжить выполнение команды rebase:
git rebase --continue
Пропустить наложение коммита и перейти к следующему:
git rebase --skip
Пример слияния коммитов
Начать процесс интерактивного слияния коммитов в пределах 6-ти последних:
git rebase -i HEAD~6
Примечание
При слиянии коммита, Git вливает его в предыдущий в списке. Вы можете изменить порядок коммитов перед слиянием. Например:
pick <hash> Finally Fix #4
f <hash> Two fix #4
f <hash> One fix #4
pick <hash> Fix #12
s <hash> New comment #12
git log --pretty=%s --graph
* Fix #12
* Finally Fix #4
Автоматизация слияния коммитов
Подготовить коммиты к слиянию:
git commit --fixup=g73di4w2mf # Git создаст коммит с сообщением `fixup fixup! Fixed #4`
git commit --squash=5e67t89q0 # Git создаст коммит с сообщением `squash squash! Fixed #9`
Состояние коммитов:
pick Fixed #4
fixup fixup! Fixed #4
pick Fixed #9
squash squash! Fixed #9
Выполнить сливание в автоматическом режиме:
git rebase -i --autosquash HEAD~4
Изменение комментариев
Изменить комментарий к последнему коммиту:
git commit --amend -m 'Обновить комментарий к последнему коммиту'
Изменить комментарии в диапазоне последних 3-х коммитов:
git rebase -i HEAD~3
r New commit comment ~1
pick Original commit ~2
r New commit comment ~3
Сдвинуть коммиты
Принять изменения и сдвинуть свои незапушенные коммиты вверх (как будто вы сделали pull, до того как закоммитили изменения):
git pull --rebase
Наложить коммиты из ветки my-fix на последний коммит ветки stage:
git rebase stage my-fix
Внимание!
Обратите внимание, что при разрешении конфликтов, theirs - это изменения из ветки, в которую мы влили коммиты и сдвинули наш коммит на верх, а ours - это изменения, которые мы получили из чужих новых коммитов. После разрешения конфликтов - вызовите:
git rebase --continue
Удаление коммитов
Удалить последний коммит:
git reset --hard HEAD~
git reset --hard HEAD~2 # последние 3 коммита
#git #github #faq #git faq #repository #git p