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~3r 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