ХХ полезных советов для пользователей Git среднего уровня. Часть 1

:

Вообще-то изначально я планировал перевести статью Энди Джеффриса (Andy Jeffries) 25 Tips for Intermediate Git Users, но в процессе я отбросил бестолковые, общеизвестные или самые простые советы вроде «настройте первым делом user.name и user.email», которые явно не подходят людям, уже более-менее плотно знакомым с Git.
Взамен я дополню статью моментами из личной практики («Своя практика»! Звучит здорово, будто я частный врач или адвокат! :-] )
1. Самое начало.

Поскольку user.{name,email,signingkey} настроены, можно посмотреть в сторону мелких удобств, вроде $ git config --global help.autocorrect 1 — в случае опечаток, гит попробует угадать что же вы имели в виду
[solar@hasher couchdb]$ git statu
WARNING: You called a Git command named 'statu', which does not exist.
Continuing under the assumption that you meant 'status'
in 0.1 seconds automatically…
# On branch 0.10.x-alt
nothing to commit (working directory clean)

Значение 1 здесь показывает десятые доли секунды.
Отрицательное значение приведёт к выполнению предполагаемой команды немедленно, а нулевое — просто к показу подсказки (по умолчанию).

Из альясов я добавляю только
git config --global alias.logp 'log --pretty=format:"%h — %an: %s"' — 10 последних коммитов в формате «SHA — Author: Commit message»
git config --global alias.unstage 'reset HEAD'
git config --global alias.remotes 'remote -v' — Это сделает вывод git remote чуть более подробным, но не столь много словным, как git remote show $branch, в котором, к тому же, нужно указать конкретный сервер.

2. Конфликты при мердже

При имеющем место конфликте можно посмотреть предмет раздора в нормальном стандартного diff -u:
$ git diff --merge
diff --cc dummy.rb
index 5175dde,0c65895..4a00477
--- a/dummy.rb
+++ b/dummy.rb
@@@ -1,5 -1,5 +1,5 @@@
class MyFoo
def say
- puts "Bonjour"
- puts "Hello world"
++ puts "Annyong Haseyo"
end
end

Если нужно получить файл из одного из мерджащихся бранчей, можно сделать git checkout —ours flash/foo.fla либо git checkout —theirs flash/foo.fla — это избавит от необходимости помнить какие бранчи сливаются.

Так же всегда можно посмотреть различия перед объединением — $ git diff branch1 branch2

3. Тэги.

Чтобы удобно определять эволюционные стадии кода, надо использовать тэги.
$ git tag -m '$tag_description' $tag_name
Если из вашего гита содержимое отправляется на сборку, все можно будет собрать конкретную указанную версию. Кстати, скорее всего, нужно будет создавать тэги, подписанные Вашим gpg-ключём (git config --global user.singingkey $key_ID)

4. Новые бранчи

Как всем должно быть известно, в новый бранч можно попасть либо создаев его и переключившись ($git branch new_branch; git checkout new_branch), либо сразу — $ git checkout -b new_branch.
Кстати, переименовать текущий бранч можно с помощью git branch -m new_name, а сторонний — git branch -m current_name new_name.
Не самая часто используемая возможность, но иногда приходится и так получается всяко быстрее чем checkout -b и последующее ручное удаление старого бранча.

5. Объединение бранчей. Merge и rebase.

Чтобы поместить в один бранч изменения из другого бранча, можно использовать либо merge — m создаёт новый коммит, в котором находятся необходимые правки, либо rebase — r же переписывает историю. С одной стороны, после rebase история получается более аккуратной, с другой — это уже другая история, поэтому в случае опубликованных общеступных бранчей лучше пользоваться merge. Тем более, что за количество коммитов никто денег не берёт.

Можно посмотреть бранчи, изменения в которых еще не перенесены в текущий бранч — это можно сделать через git branch --no-merged. Такие бранчи лучше не дропать, хехе.

6. Удалённые бранчи

Удалённые — в смысле, remote :-]

Можно пушить в удалённый бранч напрямую — git push origin branch_name, если имена локального и удалённого бранчей совпадают, а можно и с помощью полной формы — git push origin localBranch:refs/heads/Remote_Branch_Name

Кстати, чтобы не указывать каждый раз имя сервера и бранч, можно создавать отслеживаемые бранчи с помощью git checkout -b myfeature origin/myfeature. Теперь, находясь в этом бранче, можно пушить/фетчить/пуллить без конкретных имен.

7. Stash

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

i. hack-hack-hack
ii. git stash
iii. fix-fix-fix
iv. git commit -a -m 'bugfix #31337'
v. git stash pop

Те же, кто знает про git stash, посмотрите на последнюю строку — её отличие от apply в том, что откладываемые результаты не остаются во временном хранилище (посмотрите git stash list после нескольких примений stash!)

Если изменение было фактически законченным, можно оформить коммит не отходят от кассы — git stash save 'commit msg'

8. Поиск в истории

Если про коммит известно хоть что-то, можно попробовать его найти!
$ git log --grep=«Something in the message» — поиск по описанию коммита
$ git log -S"{% include \«header.tmpl\» %}" — поиск коммита по строке в файлах бранча. Обратите внимание на отсутствие пробела после -S
$ git log templates/header.tmpl — поиск коммитов, в которых затрагивался указанный файл.

Также можно уточнить поиск при помощи опций вроде --since=X.months.ago --until=Y.day.ago --author=andy -S«something»
Опция --all-match комбинирует параметры с помощью AND, а не дефолтного OR.

Дальше я опишу отмену и манипуляции с изменениями, интерактивный rebase, изменение файлов по всей истории (лично мне пригодилось, когда я заметил, что держу боевые пароли в основном бранче, хехе) и всякие другие мелочи ^_^

P.S.: Спасибо за такой нужный +1, %username% )