HEAD -  указатель на вершину(последний коммит) текущей ветки, снимок последнего созданного коммита/изменений. При переключении веток, указывает на последний коммит в ветке.
рабочая область - каталог в котором находится копия репозитория, это все хранится в файловой системе.
область индекса/индекс - изменения в файлах, которые будут зафиксированны при создании коммита, это все хранится в гите.
fast-forward  -  при мердже означает просто перенос HEAD

После добавления файла в индекс и изменения его, только добавленные изменения будут зафиксированы в коммите, то что было изменено позже - зафиксировано не будет.

Команды

Работа с ветками

git branch --no-merged - посмотреть локальные ветки, которые не были объединены с текущей выбранной веткой
git branch --merged - локальные ветки, которые уже были "слиты" в текущую активную ветку(их можно смело убивать, только надо убедиться относительно какой именно ветки вызывается эта команда!)
git branch -d branchname - удаляем локально ветку branchname
git branch -D branchname - если ветка branchname еще не была никуда слита, и мы понимаем что она нам не нужна - ее удалить можно только принудительно (-D)
git checkout -b branchname - создать новую ветку с именем branchname от текущей
git checkout -b localbranch origin/remotebranch - позволяет создать локальную ветку localbranch (с которой можно работать) из указателя на удаленную ветку origin/remotebranch. Новая локальная ветка будет отслеживать изменения удаленной ветки.
git branch --track remotename/branchname - выполнит ту же операцию. Будет создана локальная ветка с именем branchname, которая будет отслеживать remotename/branchname
git branch -vv - выведет список локальных веток с указанием настроенных для них удаленных веток, а так же дополнительной информацией насколько локальная ветка опережает/отстает от удаленной. Информация выводится исходя из того, какие данных об удаленных ветках есть на компьютере! Команда не выполняет подключение к серверу. Чтобы посмотреть актуальную информацию, сперва нужно извлечь данные с удаленных серверов командами git fetch origin или git fetch --all и потом уже смотреть вывод этой команды

Сохранение изменений

git commit -v - показывает дифф того что будет зафиксированно в коммите

Удаленный репозиторий

git fetch remotename - скачать изменения с удаленного репозитория remotename и положить их в стороне(вроде кэша), локальные ветки, которые уже отслеживают подтянутые изменения не будут затронуты(изменения в них не применятся)
git fetch --all - скачать изменения со всех удаленных репозиториев
git push remotename --delete branchname - удаляем ветку branchname с удаленного репозитория remotename
git push - без аргументов отправит текущую активную ветку на удаленный репозиторий
git remote add remotename url - добавить для текущего репозитория еще один удаленный репозиторий с именем remotename, который расположен на сервере по url
git pull remotename branchname - скачать с удаленного сервера remotename ветку branchname и слить ее с текущей веткой
git push remotename localbranchname:remotebranchname - если локально создали ветку с каким-то одним названием(localbranchname), а потом поняли что название ветки не очень, а как создавать новую ветку - не знаешь - можно отправить эту ветку на удаленный сервер remotename с другим именем(remotebranchname)
git fetch origin - загрузит с сервера origin ветки, но не создаст для них локальные копии для работы, зато теперь известен весь список веток хранящихся на сервере(в виде указателей на удаленные ветки origin/branchname)
git merge origin/branchname - позволяет слить загруженную удаленную ветку origin/branchname в текущую ветку
git push origin -u localbranch:remotebranch - если необходимо изменения из локальной ветки localbranch опубликовать в уже существующей ветке на сервере remotebranch. Такое может быть необходимо, когда один два разработчика начали реализацию одного функционала, но по какой-то причине в ветках с разными именами. Перед выполнением команды необходимо подтянуть изменения с удаленного сервера git fetch origin, чтобы получить изменения в remotebranch, и слить их в свою ветку git merge origin/remotebranch

Интерактивный режим работы

git add -i - включает интерактивный режим добавления файлов в индекс.
Числами/буквами осуществляется выбор команд, для добавления/удаления из индекса, откатывания изменений. Все изменения выводятся небольшими блоками и для каждого блока принимается решение - добавлять в индекс или нет.
Удобно если было несколько правок в файле и надо разбить их на несколько коммитов.
Операцию частичной обработки блоков изменений можно делать и в упрощенном режиме:
git add -p или git add --patch - добавление изменений в индекс частями
git stash save -patch - прячем изменения частями
git reset --patch - убираем части изменений из индекса
git checkout --patch - отменяем локальные изменения частями

Навигация в дереве коммитов

git reflog - Показывает журнал ссылок, в котором хранятся указатели на HEAD. В этом журнале git сохраняет данные о каждом изменении вершины
ветки. Чтобы посмотреть куда ссылался указатель 5 коммитов назад можно воспользоваться командой - git show @{5}, чтобы посмотреть состояние какой-либо ветки достаточно указать её название - git show master@{5}.

В скобки можно передать дату git show master@{2018–09–01}
или относительную дату git show @{yesterday}/git show @{2.months.ago}

Знак ^ в конце ссылки означает “обозначает предка коммита”. Для истории вида:

e325a7a5fb commit a
2464581e3d commit b
e97d228792 commit c

команда git show 2464581e3d^ покажет изменения внесенные коммитом commit c.

После символа можно указать число - git show 2464581e3d^2, чтобы посмотреть второго предка коммита. Но такой синтаксис применяется только для коммитов слияния. Первый родитель указывает на коммит в ветке которая была активна в момент слияния, второй предок — из ветки которая сливалась в текущую.
Знак ~ в конце ссылки так же указывает на предка - прямого предка в истории коммитов.
Чтобы не запутаться в том какую навигацию когда использовать можно запомнить простое правило:
^ - как объединение двух путей(две ветки объединились в одну), используем в коммитах слияния, ~ - прямая(хоть и чуть извилистая) дорога к следующему предку коммита.
HEAD~3 так же можно записать как HEAD^^^. Если же мы хотим перейти в ветку которая сливалась в текущую и там найти предка то надо указать, что нам нужен второй предок для конкретного коммита - HEAD^^2^. Эти способы навигации можно комбинировать между собой.

Диапазон коммитов обозначается двумя точками - ... Эта запись позволяет посмотреть какие коммиты достижимы из одного и не достижимы из другого (дифф в коммитах между двумя ветками например или какие были изменения за 3 последних коммита HEAD~3..HEAD)
Если ветка branchA выглядит так: A -> B -> C -> D, а ветка branchB так: A -> B -> E -> F (branchB сделан из branchA после коммита B), то чтобы узнать какие изменения одной ветки не слиты в другую воспользуемся командой: git log branchA..branchB, в выводе мы увидим что коммиты E и F не слиты в ветку branchA. Если же поменять местами названия веток, то результат будет C и D, очевидно.

Прятанье изменений

git умеет прятать текущие изменения в буфер, например работали над определенным блоком кода и была найдена ошибка, которая требует немедленного исправления. Тут на помощь приходит команда stash.

git stash - спрятать текущие(отслеживаемые гитом) изменения в рабочей области в буфер. При таком сохранении git автоматически добавляет в качестве комментария к этим изменениям - сообщение последнего коммита в этой ветке. Это не совсем удобно и понятно.
git stash save "comment for stash" - позволяет сохранить изменения и добавить к ним понятный комментарий "comment for stash", чтобы позже было проще понять что за изменения сохранены в буфере.
git stash list - показать список того что было спрятано в буфер.
Этот буфер работает по принципу стэка - FILO.
git stash apply - применяет к рабочей области изменения с вершины буфера(то что было спрятано последним) и не удаляет изменения из буфера. Если нужно применить более старые изменения - можно указать ссылку на них - git stash apply stash@{3}.
git stash pop - применяет к рабочей области изменения из буфера и удаляет их(в буфере), так же можно указать ссылку на конкретную запись в буфере - git stash pop stash@{3}.

git stash apply --index - сразу вернет состояние спрятанным файлам: индесирован/неиндексирован
git stash drop stash@{0} - удалить из буфера последние спрятанные изменения, без применения их к рабочей области.
git stash --keep-index - прячет только файлы, которые не проиндексированы командой git add
git stash --include-untracked - спрячет измененные файлы, проиндексированные и неотслеживаемые, тоже самое можно сделать с git stash -u
Интересное: если из буфера вытащили изменения, потом сверху еще добавили руками изменений, и захотели отменить то что вернули из буфера то это можно сделать!!! Команды git stash unapply нет, но можно применить изменения РЕВЕРСИВНО о_О:
git stash show -p | git apply -R
Можно указать индекс изменений git stash show stash@{1} -p | git apply

git stash show - список файлов и немного статистики по изменениям.
git stash show -p - вывод изменений в файлах которые лежат в буфере.
в эти команды так же можно передать ссылку на элемент буфера: git stash show stash@{1} -p

Если изменения лежали в буфере очень долго, и их применение приводит к конфликтам — можно вытащить их в отдельную ветку, там актуализировать и слить в нужную ветку. Вытащить скрытые данные из буфера в ветку можно командой: git stash branch branchname stash@{2}, при этом stash@{2} будет удален

Чистка рабочей области

Почистить рабочую область можно командой git clean. Пользоваться этим нужно осторожно - она удаляет все неотслеживаемые файлы без возможности восстановления.
Если есть подозрение, что файлы могут понадобится - можно воспользоваться командой git stash --all, которая удалит мусорные файлы, но при этом спрячет их в буфер.

Если решение об удалении хлама принято окончательно - лучше использовать git clean -f -d. Флаги включают удаление неотслеживаемых файлов и директорий (-f - force). К этой команде можно добавить параметр -n, чтобы посмотреть имитацию очистки рабочей директории.

Важно помнить, что git clean не удаляет игнорируемые файлы, которые скрываются через .gitignore. Чтобы удалить и их нужно добавить параметр -x. У команды clean так же есть интерактивный режим удаления, включается он флагом -i

Поиск

Команда git grep funcname позволяет искать строку funcname в текущем рабочем каталоге. Так же можно указать регулярное выражение.

С флага -n можно указать как много строк показывать для найденных вхождений, например git grep -n3 funcname вернет по 3 строки вверх и вниз от включения строки funcname.

Параметр --count покажет количество включений строки поиска в каждый файл, а флаг -p добавит в вывод имя метода в котором найдена эта строка(для js возвращает имя класса):

app/components/foo.js=export default class A {
app/components/foo.js: item.disabled=false
app/components/foo.js: item.disabled=true

Флаг --and - позволяет искать сложные комбинации в одной строке, флаг --break - добавляет пустые строки между разными файлами в выводе поиска,
флаг --heading - выводит сперва название файла, а затем все включения в нем.

Для поиска в истории можно использовать git log с параметром -S:
git log -Sprocess --oneline - эта команда выведет все коммиты в которых была добавлена/удалена строка process , флаг --oneline чтобы вывести сокращенную информацию о коммитах:

67c9287e95 add check check for key existance
028468202a fix condition

Найдя хэш коммита, можно воспользоваться командой git diff 85c32a7e95 чтобы посмотреть изменения.

Для более сложного поиска можно использовать параметр -G, в который передаются регулярные выражения для поиска в истории. Параметр -L в команде git log позволяет вывести историю конкретной строки или функции в определенном файле:
git log -L :showModal:my-app/components/table/info.js
правда у меня этот метод ничего не нашел, ни для js, ни для php кода, возможно потому что git не смог понять как в js искать функции
Cигнатура такого поиска выглядит так:
git log -L :funcName:pathToFile
или так:
git log start,end:pathToFile - в этом варианте start это номер строки начиная с которой смотреть историю, end - номер строки до которой смотреть историю.