Skip to content

Instantly share code, notes, and snippets.

@maxim-oleinik
Last active May 1, 2023 13:14
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save maxim-oleinik/12e743331614592793155b22f07969a6 to your computer and use it in GitHub Desktop.
Save maxim-oleinik/12e743331614592793155b22f07969a6 to your computer and use it in GitHub Desktop.
GIT cheat sheet
Git
================================================================================
Ссылки
------
* Книга "Git Community Book"
http://book.git-scm.com/
* Книга "Git Magic"
http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html
* Сравнение команд Git-SVN
http://git.or.cz/course/svn.html
Установка
---------
Win:
http://code.google.com/p/msysgit/
Надо везде указать UTF-8
Настройка
---------
1. Отредактировать файл ~/.gitconfig
[user]
name = Maxim Oleinik
email = some.email@gmail.com
[color]
diff = auto
status = auto
branch = auto
[alias]
st = status
ci = commit
br = branch
co = checkout
di = diff
plog = log --follow --pretty=format:'%h %Cblue%cn %Creset%cr %Cgreen%s'
# можно указать любые свои алиасы к разным командам
[core]
whitespace = trailing-space, space-before-tab, cr-at-eol
Или использовать команду git config:
git config --global user.name "Maxim Oleinik"
git config --global user.email "maxim.oleinik@gmail.com"
!!! Далее все примеры будут использовать указанные алиасы.
2. Чтобы игнорировать локальные конфигурационные файлы личного IDE,
которые не не должны фигурировать в .gitignore,
надо указать все эти файлы в PROJECT_DIR/.git/info/exclude
Общее
-----
# Утилита для просмотра дерева коммитов
gitk --all &
или
gitg
# Создать репозиторий в текущей директории
git init
# Клонировать существующий репозиторий
git clone /path/to/repo
git clone http://github.com/symfony/symfony.git
# Игнорирование файлов
Перечислить все в PROJECT_DIR/.gitignore
# Полностью обновить свой репозиторий
git fetch
git fetch --tags # Обновить теги, которые были "передвинуты"
git remote prune origin # Убрать ссылки на удаленные ветки
git co master
git merge origin/master
git submodule update --init # Обновить ссылки на субмодули
git submodule foreach 'git submodule update --init' # Обновить субмодули субмодулей
Рабочий процесс
---------------
# показать статус - список измененных незакоммиченных файлов
git st
# Staged - промежуточный коммит
git add <file>
git add myFile*
git add <dir1> <dir2> <file1>
git add . # Добавить ВСЁ в текущей директории
git add -p # Добавлять фрагментами дифа, просматривая каждое изменение
# ОЧЕНЬ рекомендую использовать постоянно
git diff -U0 | grepdiff 'regex search' --output-matching=hunk | git apply --cached --unidiff-zero
# Закоммитить только те фрагменты, которые попадают под регулярку
# I use -U0 on the diff to avoid getting unrelated changes. You might want to adjust this value to suite your situation.
git add -N . # Добавить все "новые" файлы под контроль без содержимого (только путь),
# т.е. git покажет содержимое этих файлов в дифе
git rm # удалить файл или директорию
git ls-files -d | xargs git rm # Если файлы удалили ручками без git rm,
# тогда это поможет удалить их для git скопом
git mv # переименовать файл
# фактически это 2 команды add NEW + rm OLD
# Diff
git di --cached # просмотреть изменения, которые будут закоммичены (добавлены как git add)
git di # просмотреть изменения, которые не "добавлены"
git di HEAD # просмотреть все измения
git di -b -w # посмотреть диф без учета пробелов
# Новые файлы (не добавленные через git add) diff не показывает.
# Или можно добавить их через git add -N
# Коммит
git сi # закоммитить изменения добавленные через git add
git сi -a # закоммитить все изменения
# новые файлы (не добавленные через git add) не коммитятся
git сi <file1> <dir> - закоммитить указанные файлы (независимо от git add)
# Отменить текущие незакоммиченные изменения в файлах
git co <file1> <dir> # откатить не "добавленные" измения
git reset HEAD <file1> <dir> # отменить git add
Управление коммитами, откат изменений
-------------------------------------
см. http://gq.net.ru/2009/12/16/git-history-rewrite/
git revert HEAD # создаст новый зеркальный коммит
git commit --amend # изменить сообщение последнего коммита
# Откатить коммит, отредактировать и закоммитить заново
git reset --soft HEAD^ # откатить последний коммит
... внести измения
git commit # закоммитить
# Объединить коммиты, удалить, изменить порядок
git rebase -i HEAD~3 # последние 3 коммита
# откроется редактор со списком коммитов с командой напротив каждого коммита
# там есть справка, какие команды есть, и что они делают
Ветки и Теги
------------
# Работа с тегами
см. git help tag
git tag -f TAG_NAME <ref> # Передвинуть существующую метку в новую точку
# Ветки
git br # список локальных веток
git br -r # список веток внешнего репозитория
git br -a # список всех веток
git br my-branch # создать ветку my-branch с текущей позиции
git co -b my-branch master # создать ветку my-branch от master и переключиться на нее
git co -b some-branch origin/some-branch # создать ветку some-branch из origin репозитория
git co my-branch
git reset --hard some_branch # перенести указатель текущей ветки на указанную ревизию
git reset --hard REF удалит все текущие изменения и коммиты, так, как будто была создана новая ветка
git reset --hard origin/master git co -b my-branch origin/master
git br -d my-branch # безопасно удалить ветку (смерджена в текущую)
git br -D my-branch # принудительно удалить ветку
git co my-branch # переключиться на указанную ветку
# Merge
A - B - C (master)
\
D - E (my-branch)
git co master
git merge my-branch
A - B - C - F (master)
\ /
D - E (my-branch)
# merge с объединением коммитов
A - B - C (master)
\
D - E - F (my-branch)
git co master
git merge --squash my-branch
A - B - C - DEF (master)
# создаст 1 коммит БЕЗ merge-коммита, в который объединит коммиты, которые мерджились
# Cherry-pick - положить указанный коммит в текущую ветку
A - B - C (master)
\
D (my-branch)
git co master
git cherry-pick D
A - B - C - D' (master)
\
D (my-branch)
# Подтянуть ветку
A - B - C (master)
\
D - E (my-branch)
git co my-branch
git rebase master
A - B - C (master)
\
D - E (my-branch)
# Пененести ветку (поменять родителя)
A - B - C (master)
\
D - E (branch-1)
\
F - G (branch-2)
git co branch-2
git rebase --onto master branch-1 branch-2
A - B - C (master)
\ \
\ F - G (branch-2)
\
D - E (branch-1)
Резолв конфликтов
-----------------
git co current-branch
git merge -Xtheirs some-branch # Все конфликты решать в пользу some-branch
git merge -Xours some-branch # Все конфликты решать в пользу current-branch
-Xignore-all-space # игнорирует изменения в любом количестве существующих пробельных символов
-Xignore-space-change # игнорирует вообще все изменения пробельных символов
см. подробнее про работу с конфликтами
https://git-scm.com/book/ru/v2/Инструменты-Git-Продвинутое-слияние
Работа с удаленным репозиторием
-------------------------------
git remote # см. git help remote
git fetch # загрузить изменения из внешнего репозитория
# в локальный репозиторий изменения не применяются
git pull origin master # загрузить в ТЕКУЩУЮ ветку изменения из origin/master
# аналог git merge origin/master - и ЛУЧШЕ всего использовать этот вариант
# во избежания разных недоразумений, поскольку сразу видно, что будет мердж в текущую ветку
git push origin master # отправить свои коммиты из local/master в origin/master
git push origin my-branch # экспортировать локальную ветку в my-branch в origin/master
git push origin my-branch:remote-branch
# отправить правки из локальной ветки my-branch
# во внешнюю remote-branch
git push origin :remote-branch # удалить ветку `remote-branch` из внешнего репозитория
# Удалить у себя все упоминания origin веток, которые кто-то уже удалил
git remote prune origin
# Теги
git push --tags # Отправить теги в удаленный репозиторий
git fetch --tags # Принудительно загрузить теги (если были передвинуты)
git push origin :TAG_NAME # Удалить метку из удаленного репо
Пример командной работы над задачей в отдельной ветке
-----------------------------------------------------
# Обновить свой репозиторий
git fetch
git co master
git merge origin/master
# Создать ветку "t314-article-form" под текущую задачу и переключиться на нее
git co -b t314-article-form
# ... работа и коммиты в новой ветке
# Пока работал, master уже ушел вперед, надо обновить свою локальную копию master
git fetch
git co master
git merge origin/master
# Обратно в ветку и подтянуть ее к мастеру
git co t314-article-form
git rebase master # Подтянуть ветку к новым правкам,
# теперь ветка со всеми коммитами будет начинаться из новой точки
# Отправить ветку в общий (origin) репозиторий на ревью
git push origin t314-article-form
# После ревью слить и удалить ненужную теперь ветку
git co master
git merge t314-article-form
git br -d t314-article-form # Удалить локальную ветку
git push origin :t314-article-form # Удалить ветку из общего репозитория
# Все участники команды по-прежнему видят удаленную ветку. Удаляют ссылки у себя:
git remote prune origin
Stash
-----
см. git help shash
Пример работы над 2 задачами с изпользованием stash
# Сохранить текущие незакоммиченные правки,
# чтобы переключиться в другую ветку для срочной работы
git stash save "Моя незаконченная работа"
# ... переключаемся в другую ветку, работаем там и возвращаемся обратно
# Восстанавливаем спрятанные правки
git stash apply # поднимет последнее сохранение
git stash apply stash@{0} # или явно указать номер
git stas clear # полностью очистить всю хоронушку
или
git stash pop # восстановить правки и удалить запись о них
# Просмотреть список всех сохраненных состояний
git stash list
История
-------
git show - выводит информацию об объектах (коммитах, метках, деревьях и пр.)
---------
git show # показать последний коммит
git show fb47ddb2 # показать указанный коммит
git show HEAD^ # предыдущий коммит (второй с конца)
git show HEAD^^ # третий коммит с конца
git show HEAD~4 # пятый коммит с конца
-- слияния
git show HEAD^1 # show the first parent of HEAD
git show HEAD^2 # show the second parent of HEAD
----
git show my-branch:fs/locks.c # посмотреть версию конкретного файла
git blame - когда и кем редактировалась каждая строка файла в последний раз
---------
git blame -L 100,120 some_file.txt # Показать аннотацию для указанного файла для строк с 100 до 200
git log - вывести список коммитов по условию
---------
git log v2.5.. # коммиты начинающиеся с v2.5 до текущей позиции
git log master..test # коммиты, которые есть в test, но нет в master
git log master...test # коммиты, которые есть или в master, или в test, НО не в обоих ветках
git log origin/master..master # разница с внешним хранилищем - что надо закоммитить
git log origin/master..HEAD # с текущей ревизией
git log master..origin/master # как отстал локальный master
git log Makefile # которые изменили файл Makefile
git log fs/ # только затронувших файлы, путь которых начинается с 'fs/'
git log --since="2 weeks ago" # за последние 2 недели
git log -5 # последние 5 коммитов
git log --author=oleinik # автор коммита содержит указанный текст
git log --grep'some text' # поиск коммитов содержащих указанный текст в commit message
git log -G'foo()' # коммиты, в которых в дифе присутствует строка foo()
git log -S'foo()' # коммиты, в которых в дифе появилась или исчезла строка foo()
git log --follow # Показывать историю переименований файлов
git log --no-merges # Не показывать мерджи
git log -5 -p --reverse FILE # Посмотреть последние 5 дифов указанного файла
-p - показать diff
-reverse - начиная от самого старого к последнему
Субмодули
---------
Добавить в проект другой git-репозиторий ввиде субмодуля как внешнюю зависимость.
Нельзя добавить только часть репозитория как svn:externals, только весь целиком.
см. git help submodule
# Добавить субмодуль
git submodule add http://github.com/maxim-oleinik/symfony-dev-rules ./doc/rules
# Чтобы коммитить в субмодуль, надо изменить конфиг ./doc/rules/.git/config
url = git@github.com:/maxim-oleinik/symfony-dev-rules.git
# Обновить ссылки на субмодули
git submodule update
git submodule update --init
# Выполнить указанную команду для каждого субмодуля
git submodule foreach <command>
git submodule foreach 'git st'
# Удалить субмодуль
1. Удалить из .gitmodules
2. Удалить из .git/config
3. Удалить файлы git rm --cached path/to/submodule
4. Закоммитить результат
# Обновить конфиг проекта, при переключении модуля на другой репозиторий
git submodule sync
Субмодули в свою очередь могут иметь другие субмодули и так до бесконечности.
Это жутко неудобно. И поэтому, лучше явно прописывать все зависимости в одном месте.
Прочее
------
# Очистить все файлы и директории, которые не стоят под контролем
git clean -fd
git clean -fdx # !!! Удалит все файлы перечисленные в .gitignore
# Лог всех манипуляций с репозиторием. Здесь можно искать потерянные коммиты
git reflog
# Оптимизировать и перепаковать репозиторий
git gc
# Работа с патчами
git format-patch HEAD~2 # Создать набор патчей от указанной точки
git format-patch master..test
git apply /path/to/patch/file # Применить патч
git send-email patch_files # Отправить набор патчей по email
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment