Основам git мне пришлось научиться на своем первом месте работы (около трех лет назад).
С тех пор я считал, что для полноценной работы нужно запомнить всего-лишь несколько команд: И дополнительно: В принципе, я и сейчас во многом так считаю, но со временем волей-неволей начинаешь узнавать интересные трюки. Вообще, имеет смысл подробнее разузнать о понятиях гита. Лучше подробнее ознакомиться с концепцией коммитов, что такое ветка, что такое тег и пр. Удивительно, но не у всех оно есть. Отправляемся в гугл по запросу "git_completion", скачиваем скрипт и действуем по инструкции к нему. Данный код нужно добавить в .bashrc. Он со мной с некоторыми изменениями путешествует еще с того самого первого места работы. Для справки: за внешний вид командной строки баша отвечает переменная PS1. Have fun. Вообще-то, у гита есть свои алиасы, но я понятия не имею, как их добавлять, т.к. мне лень изучать вопрос и не нравится использование команды git. Я пользуюсь башем: Обратите внимание на __git_complete <something> <another>. Эта команда включает гитовое автодополнение для алиаса. Для начала небольшая страшилка, основанная на реальных событиях: Да, история произошла со мной. Через несколько часов я смог его закрыть и начал коммитить только с однострочными комментариями через git commit -m. Git, как и некоторые другие утилиты (crontab, например) проверяют наличие переменной EDITOR. В конфиге баша (~/.bashrc) можно добавить вот такую строчку: У меня это emacsclient, раньше был subl (Sublime Text). Я не проверял, но я полагаю, что очень важно, чтобы команда не возвращала управление терминалу, пока текстовый файл не будет закрыт. Иногда можно просто сменить ветку, но иногда возникают конфликты. Я знаю два варианта: 1) Сделать временный коммит
2) git stash, сменить ветку, ..., вернуть ветку, git stash pop Первый вариант надежнее, второй удобнее (имхо).  Показывает ваши изменения относительно текущего коммита + stage (важное уточнение). Замечание: в дифф не попадают новые файлы Замечание: сюда новые файлы попадают. Т.е. файлы, которые не относятся к репозиторию У меня на это дело есть alias в баше: git reset --soft <commit/branch/tag> переносит ветку на коммит, но код не меняет. Разница заносится в stage. $(<whatever>) — баш выполняет содержимое скобочек и подставляет результат выполнения вместо всего выражения. Например, cat $(ls | tail -1) выдаст содержимое последнего файла из ls. git log --format=%H -2 выдаст хеши двух последних коммитов. В общем, вся команда сводится к тому, что текущая ветка переносится на один коммит назад, а изменения, внесенные коммитом, попадают в stage upd. Как многие справедливо заметили, того же результата можно добиться намного проще: git reset --soft HEAD~ — данная команда берет предыдущий коммит от "головы" и "ресетит" гит на него. В свое оправдание могу сказать, что этому алиасу пара лет и в то время я не знал о том, что такое HEAD и тем более HEAD~ Когда я работаю на своей ветке, периодически я делаю несколько коммитов, которые совсем не имеют смысла по отдельности (а делаю я это просто для того, чтобы коммитить почаще и не терять мысль), поэтому перед вливанием их в мастер имеет смысл их объединить Решение: Интерактивный rebase! Это откроет текстовый редактор, в котором списком будут указаны коммиты.
Вы можете: В данной ситуации нужно взять нужные коммиты, расставить их друг за другом и всем, кроме первого, поставить пометку squash. Вообще я после каждой фичи делаю интерактивный ребейз и смотрю, какие коммиты я хочу объединить, какие переставить для красоты, какие поправить. Это позволяет сохранять красоту в версионировании. Еще стоит упомянуть: Ситуация: 3 коммита назад допустил опечатку, не хочу, чтобы это позорище кто-то увидел отдельным коммитом. Решение: Интерактивный rebase! Лично я в указанной ситуации (а у меня она часто возникает) делаю так: создаю коммит, где в сообщении добавляю префикс, заканчиваю работу над веткой, делаю полный ребейз ветки на мастер (git rebase -i master) и переношу этот коммит под тот, к которому данная правка относится, с пометкой s (squash). Коммиты желательно делать максимально простыми (антоним слову "сложными"). Хочу вот я на гитхабе посмотреть, какая история у файла hello_world.rb, смотрю историю, а там среди прочих коммит "create super-booper feature", в котором в файле hello_world.rb у одной переменной изменено имя, хотя она к фиче совсем отношения не имеет. Лучше было бы наличие коммита "rename variable x to y in hello_world.rb". Собственно, например, у меня есть код: Мне нужно добавить фичу: выводить удвоенное n. Изи! Но пока я пишу фичу, на автомате меняю некрасивое имя функции. Пишем: Как теперь коммитить? Можно быстро вернуть старое название, закоммитить новый функционал, а потом уже переименовать, но это не всегда уместно, т.к. изменения могут быть достаточно крупными. Можно честно признать, что коммит сложный и написать сообщение в духе "добавил фичу + переименовал метод", но мы ведь стараемся делать коммиты простыми, верно? Но у гита есть отличная команда: Она интерактивная. Поочередно берет изменения кусками (hunk) и спрашивает, что с данным куском делать: игнорировать, добавить, изменить и добавить. Третий вариант достаточно мощный, можно по отдельности добавлять изменения даже в рамках одной строчки (kvadrat(x) + kub(x) => square(x) + cube(x) в 2 коммита). Я не буду приводить пример, просто зайдите в любой ваш проект с гитом, отредактируйте пару файлов в разных местах и введите эту команду. Иногда лучше один раз попробовать, чем сто раз услышать (при работе команды можно ввести ? для краткой справки) Я указал здесь всего-лишь парочку "трюков" работы с git, но их я использую на ежедневной основе. Смысл данного поста (помимо того, чтобы ублажить свое ЧСВ и оставить заметку для себя самого) в том, чтобы еще раз подчеркнуть известную (относительно) фразу: Know your tools!. В гите (да и в принципе во всех ваших инструментах для работы) есть множество деталей, которые могут сделать вашу жизнь проще. Например, я видел репозитории, в которых стояли валидации для коммитов: нельзя было ничего закоммитить, если не проходили тесты или тесты не покрывают изменения. Software Engineer