Уже были статьи про основы гита, были и статьи про внутреннее устройство репозитория. Сегодня поговорим, как простому смертному работать с гитом на автопилоте и не морочить себе голову.
Во-первых, шорткаты (в порядке убывания популярности):
alias gst='git-status'
alias ga='git-add'
alias gc='git-commit -m'
alias gp='git pull && git push'
alias gull='git pull'
alias gush='git push'
alias gb='git-branch'
alias gco='git-checkout'
alias gd='git-diff'
Во-вторых, отображение текущей ветки в командной строке:
export PS1='`__git_ps1 "%s"` \w \$ '
Выглядит так:
lazy-args-in-futures ~/Work/io/oleganza-io.git $
(Как установить: http://ericgoodwin.com/2008/4/10/auto-co… )
Типичный поток работы в одной ветке
1) Что-то пописали, прогнали тесты
2) $ gst - увидели, какие файлы новые, какие обновленные.
3) $ ga a b c - добавили новые и обновленные файлы в индекс.
4) $ gc 'something is done' - записали коммит в репозиторий
5) Снова что-то написали, снова закоммитили.
6) $ gp - слили чужие изменения, залили свои изменения. Если вдруг возник конфликт, вам об этом напишут, будете мерджить.
Чтобы просто подтянуть обновления, набираем $ gull (git pull).
Локальные ветки
Принцип: одна фича — одна ветка. Один багфикс (если предполагается длиннее двух коммитов) — одна ветка. Один эксперимент — одна ветка. Одна фича внутри эксперимента — ветка от ветки. Ну, вы уловили идею.
Зачем оно нужно? Представьте, что вы начали день с фичи А, а к вам подошли и сказали, что нужно зафиксить Б. А через пять минут выяснилось, что для того, чтобы по-человечески зафиксить Б, нужно прикрутить и проверить Ц. Если каждую из этих задач держать в отдельных ветках, то голова не пойдет кругом, и работа не встанет поперек горла.
Набираем:
master ~/project $ gco -b my-feature
Получаем:
my-feature ~/project $
Список всех веток:
$ gb
Переключиться на другую ветку:
$ gco some-branch
Не забывайте, что вы всегда можете подлить какую-нибудь ветку в текущую с помощью git merge other-branch.
Жизненные ситуации с ветками
1) Исправление бага/добавление фичи. Делаем ветку, все тестируем, подливаем в нее master: gull && git merge master, снова тестируем, выходим в мастер (gco master), подливаем ветку (git merge my-branch), тестируем, заливаем мастер (gush) и удаляем ветку (gb -D my-branch).
2) Публикация ветки для совместной работы: gush origin my-branch:refs/heads/my-branch
Удаление ветки: gush origin :refs/heads/my-branch (внимание на пробел перед двоеточием)
3) Вы сидите в одной ветке и сделали что-то, что хотели бы закоммитить в другую ветку. Если вы еще не закоммитили, то делаем git reset HEAD для уже добавленных файлов (через ga/git-add), потом git-stash, выходим в нужную ветку, делаем git-stash apply и далее действуем так, как будто мы прямо тут все и меняли.
4) Вы сделали коммит в некоторую экспериментальную ветку, который имеет смысл залить в мастер, но git merge my-branch не подходит, потому что после этого коммита были еще несколько экспериментальных коммитов.
На этот случай есть git-cherry-pick. Вначале, посмотрите git-log и скопируйте номер нужного коммита. Далее, вы должны закоммитить все изменения в той ветке, в которую будете кидать выдернутый коммит. Затем, делаете git-cherry-pick и разруливаете конфликты, если возникли.
У меня такая ситуация была именно с добавлением коммита в мастер, поэтому после этих хирургических манипуляций мне нужно было подлить мастер в локальную ветку. Поскольку cherry-pick всего лишь применяет дифф (номер коммита становится другим), то ветка не знает, что внесенное изменение у нее уже есть, и не может нормально его смерджить. Поэтому, при мердже мастера в ветку вы гарантированно получите глупые конфликты а-ля "строчка АБВ конфликтует с АБВ".
Если кто-нибудь знает, как избежать конфликтов в такой ситуации (и сэкономить 5 минут времени), поделитесь опытом.
Скучные нравоучения напоследок
1) Коммиты должны быть мелкими. Дифф на пять экранов должен быть исключением, а не правилом.
2) На первых порах не морочьте себе голову с rebase и "чистотой" линии коммитов. Это беспокоит только последних эстетов или Линуса (который мерджит десяток веток в день). Читать git-log и игнорировать банальные merge commits нет никакой проблемы.
3) Читайте git-log после pull, ругайте своих коллег за невразумительные описания коммитов.
4) Изучите .git/config
В следующий раз нужно написать пару слов о комфортной работе с git-submodule и git-svn.