Моя шпаргалка по работе с Git

Некоторое время назад я открыл для себя Git. И знаете, я проникся. То есть, по-настоящему проникся. Теперь я использую Git не только на работе (где я с ним, собственно, познакомился), но и для своих проектиков, которые я стал хранить на BitBucket. Последний начал поддерживать Git относительно недавно. В отличии от GitHub, BitBucket позволяет совершенно бесплатно создавать как открытые, так и закрытые репозитории.

В чем состоит отличие Git от Subversion?

Главное отличие Git от Subversion заключается в том, что Git — распределенная система контроля версий. Звучит ужасающе, но на практике это означает очень простую вещь. Каждый разработчик держит у себя на диске отдельный репозиторий. Обратите внимание — не копию репозитория, не некоторые бранчи, а тупо отдельный и при этом абсолютно полноценный репозиторий.

Пока мы работаем в рамках своего репозитория, все происходит в точности, как в Subversion. Мы коммитим и откатываем изменения, создаем, мерджим и удаляем бранчи, разрешаем конфликты и тд. Помимо этого, предусмотрены команды для работы с репозиториями на удаленных машинах. Например, «git push» означает мердж локальных изменений в удаленный репозиторий, а «git pull» — наоборот, мердж изменений из удаленного репозитория в локальный. Обмен данными по сети обычно происходит с использованием протокола SSH.

В результате имеем:

  • Git присущи все те же преимущества от использования VCS, что мы получаем в Subversion.
  • Git дает нам нормальное шифрование «из коробки», безо всяких танцев с бубнами, как в случае с Subversion.
  • Если сервер с «главным» репозиторием, куда пушат свои изменения все разработчики (хотя формально в Git нет никакого «главного» репозитория), вдруг прилег — ничего страшного. Делаем коммиты в локальный репозиторий и ждем, когда сервер вернется.
  • Даже если сервер доступен, все равно удобнее сделать пяток локальных коммитов, а затем отправить их на сервер одним пушем.
  • Сервер вообще не нужен. Вы можете использовать Git только локально. И не обязательно для работы с исходниками. Например, можно использовать Git для того, чтобы иметь возможность откатиться к предыдущим версиям файлов (каких-нибудь электронных таблиц) или вернуть случайно удаленные. А в этой заметке рассказывается, как хранить git-репозиторий на флешке.
  • Git не раскидывает по каталогам служебную информацию (помните «.svn»?), вместо этого она хранится только в корне репозитория.
  • Git нынче очень моден (хотя это далеко не единственная распределенная система контроля версий, например, есть Mercurial и Darcs), в связи с чем растет число разработчиков, использующих его. Как следствие, используя Git, легче получить помощь на каком-нибудь форуме или собрать команду разработчиков, знакомых с этой VCS.
  • Существует множество полезных утилит для работы с Git — Qgit, gitk, gitweb и другие. «Из коробки» есть импорт и экспорт в/из Subversion/CVS.
  • Git поддерживают многие хостинги репозиториев (GitHub, BitBucket, SourceForge, Google Code, …) — есть из чего выбрать.
  • Большой популярностью пользуется GitHub. Используя Git, вы увеличиваете вероятность того, что кто-то захочет безвозмездно написать патч для вашего OpenSource проекта.

Пример использования Git

Я использовал Git при написании программы из заметки Генерация почти осмысленных текстов на Haskell, сидя под своей любимой FreeBSD. Вот как примерно выглядела моя работа с Git.

В первую очередь необходимо поставить Git:

pkg_add -r git

Затем создаем пару ssh ключей, если не создавали ее ранее:

ssh-keygen
cat ~/.ssh/id_rsa.pub

Заходим на БитБакет, создаем git-репозиторий под новый проект, а в свойствах аккаунта прописываем свой открытый ssh-ключ. Затем клонируем репозиторий:

cd ~/projects/haskell
git clone git@bitbucket.org:afiskon/hs-textgen.git
cd hs-textgen

Делаем какие-то изменения:

echo test > TODO.TXT

Добавляем новый файл в репозиторий и делаем коммит:

git add TODO.TXT
git commit -a

Поскольку я не указал описание коммита, запускается редактор VIM, с помощью которого я и ввожу описание. Затем я отправляю все сделанные мною изменения на БитБакет:

git push origin

Допустим, теперь я хочу сделать некоторые изменения в проекте, но не уверен, выйдет ли из этого что-то хорошее. В таких случаях создается новая ветка:

git branch new_feature
git checkout new_feature

Работаем с этой веткой. Если ничего хорошего не вышло, возвращаемся к основной ветке (она же «trunk» или «ствол»):

git checkout master

Если вышло что-то хорошее, мерджим ветку в master (о разрешении конфликтов рассказано в следующем параграфе):

git commit -a # делаем коммит всех изменений в new_feature
git checkout master # переключаемся на master
git merge new_feature # мерджим ветку new_feature

Не забываем время от времени отправлять наш код на BitBucket:

git push origin

Если мы правим код с нескольких компьютеров, то перед началом работы не забываем «накатить» в локальный репозиторий последнюю версию кода:

git pull origin

Работа в команде мало чем отличается от описанного выше. Только каждый программист должен работать со своей веткой, чтобы не мешать другим программистам. Одна из классических ошибок при начале работы с Git заключается в push’е всех веток, а не только той, с которой вы работали. Вообще я бы советовал первое время перед выполнением каждого push делать паузу с тем, чтобы подумать, что и куда сейчас уйдет. Для большей безопасности советую при генерации ssh-ключей указать пароль. Тогда каждый запрос пароля со стороны Git будет для вас сигналом «Эй, ты делаешь что-то, что затронет других».

Для работы с Git под Windows можно воспользоваться клиентом TortoiseGit. Если память не изменяет, для нормальной работы ему нужен MSysGit. Для генерации ключей можно воспользоваться утилитой PuTTyGen, только не забудьте экспортировать открытый ключ в правильном формате, «Conversions → Export OpenSSH key».

Следует отметить, что мне лично TortoiseGit показался каким-то глючноватым и вообще не слишком удобным. Возможно, это всего лишь дело привычки, но мне кажется намного удобнее работать с Git из консоли, чем с помощью контекстного меню в Проводнике. Так что по возможности я бы советовал работать с Git в Юниксах. В крайнем случае можно поставить виртуальную машину, установить под ней FreeBSD (безо всяких GUI) и работать в этой виртуальной машине.

Шпаргалка по командам

В этом параграфе приведена сухая шпаргалка по командам Git. Я далеко не спец в этой системе контроля версий, так что ошибки в терминологии или еще в чем-то вполне возможны. Если вы видите в этом разделе ошибку, отпишитесь, пожалуйста, в комментариях.

Создать новый репозиторий:

git init project-name

Клонировать репозиторий с удаленной машины:

git clone git@bitbucket.org:afiskon/hs-textgen.git

Добавить файл в репозиторий:

git add text.txt

Текущее состояние репозитория (изменения, неразрешенные конфликты и тп):

git status

Сделать коммит:

git commit -a -m "Commit description"

Сделать коммит, введя его описание с помощью $EDITOR:

git commit -a

Замерджить все ветки локального репозитория на удаленный репозиторий:

git push origin

Аналогично предыдущему, но делается пуш только ветки master:

git push origin master

Замерджить все ветки с удаленного репозитория:

git pull origin

Аналогично предыдущему, но «накатывается» только ветка master:

git pull origin master

Скачать все ветки с origin, но не мерджить их в локальный репозиторий:

git fetch origin

Аналогично предыдущему, но только для одной заданной ветки:

git fetch origin master

Начать работать с веткой some_branch (уже существующей):

git checkout -b some_branch origin/some_branch

Создать новый бранч (ответвится от текущего):

git branch some_branch

Переключиться на другую ветку (из тех, с которыми уже работаем):

git checkout some_branch

Получаем список веток, с которыми работаем:

git branch # звездочкой отмечена текущая ветвь

Просмотреть все существующие ветви:

git branch -a # | grep something

Замерджить some_branch в текущую ветку:

git merge some_branch

Удалить бранч (после мерджа):

git branch -d some_branch

Просто удалить бранч (тупиковая ветвь):

git branch -D some_branch

Последние изменения:

git log

История конкретного файла:

git log file.txt

Аналогично предыдущему, но с просмотром сделанных изменений:

git log -p file.txt

Посмотреть, кем в последний раз правилась каждая строка файла:

git blame file.txt

Откатиться к конкретному коммиту (хэш смотрим в «git log»):

git reset --hard d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4

Аналогично предыдущему, но файлы на диске остаются без изменений:

git reset --soft d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4

Попытаться обратить заданный commit (но чаще используется branch/reset + merge):

git revert d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4

Просмотр изменений (суммарных, а не всех по очереди, как в «git log»):

git diff # подробности см в "git diff --help"

Используем vimdiff в качестве программы для разрешения конфликтов (mergetool) по умолчанию:

git config --global merge.tool vimdiff

Отключаем диалог «какой mergetool вы хотели бы использовать»:

git config --global mergetool.prompt false

Разрешение конфликтов (когда оные возникают в результате мерджа):

git mergetool

Создание тэга:

git tag some_tag # за тэгом можно указать хэш коммита

Следует отметить, что Git позволяет использовать короткую запись хэшей. Вместо «d8578edf8458ce06fbc5bb76a58c5ca4a58c5ca4» можно писать «d8578edf» или даже «d857».

Дополнительные материалы

В качестве источников дополнительной информации я бы рекомендовал следующие:

Как обычно, любые замечания, дополнения и вопросы категорически приветствуются. И кстати, с наступающим вас!

Дополнение: См также заметку Как я выбирал между GitHub и BitBucket.

  • Аноним

    http://gitref.org/ — тоже хороший небольший туториал для начинающих с более подробными примерами

  • Алексей

    Отличная статья. Но раз на этом сайте к критике относятся спокойно (да я и критиковать ничего не собираюсь — написано здорово), хочется сказать, что есть такая штука как bazaar. 5 лет ею уже очарован. Правда оговорюсь — только в локальных целях (то есть для себя одного). И вот здесь: http://bazaar.canonical.com/en/ можно найти кучу проектов, которые пользуются bazaar, видимо не без оснований. С другой стороны, материалов по bazaar на русском что-то не видно…
    Вот некоторые материалы:
    Распределенная система контроля версий Bazaar
    http://hlabs.spb.ru/development/versions/bazaar.html
    Распределенная система контроля версий Bazaar (cvs bazaar)
    http://www.opennet.ru/base/dev/bazaar_vcs.txt.html
    Учебник Bazaar
    http://doc.bazaar.canonical.com/beta/ru/tutorials/tutorial.html
    Руководство пользователя Bazaar
    http://doc.bazaar.canonical.com/beta/ru/user-guide/index.html

  • Алексей

    Извиняюсь :) Сперва написал что по Bazaar материалов нет, а потом уже дал себе труд их отыскать, а вот фразу не удалил…

  • Александр Перечнев

    Да, на прошлой работе я так же подружился с Git. А так же влюбился в Vim =).

    • http://eax.me/ afiskon

      Кстати, как выяснилось, git очень-очень похож на Mercurial. Видимо, создавался по образу и подобию.

      На счет Vim — в него бы средства рефакторинга в стиле «переименовал переменную в одном месте — переименовалась везде» и цены бы ему не было.

      • Алексей

        vim бесценен «как есть»! А для подобного рода вещей есть очень интересный универсальный препроцессор filepp. Написан на PERL, с исходниками. Я лично там 3 ошибки исправил (много времени не потребовалось) и очень им доволен. Чудеса можно с программами делать с его помощью. Он и для PERL подходит, и для HTML, SQL — в общем универсален.

        • http://eax.me/ afiskon

          «vim бесценен как есть!»

          Согласен.

          «для подобного рода вещей есть очень интересный универсальный препроцессор filepp»

          Спасибо, ознакомлюсь. Хотя я не уверен, что filepp также удобен, как средства рефакторинга в современных IDE.