Git для пользователей Subversion: Часть 1. Начинаем

Раскрываем секреты Git пользователям Subversion

Используя Subversion в качестве базовой системы, в этих двух статьях мы покажем, как установить Git, настроить удаленный репозиторий и начать пользоваться его основными командами.

Теодор Златанов, программист, Gold Software Systems

Теодор Златанов (Teodor Zlatanov) получил диплом магистра по вычислительной технике в Boston University в 1999. Он работает программистом с 1992, используя Perl, Java, C, и C++. Он интересуется работами с открытым исходным кодом по синтаксическому анализу текста, трехуровневыми архитектурами клиент-серверных баз данных, системным администрированием UNIX, CORBA и управлением проектами.



03.02.2011

Для тех, кто незнаком с бесплатными VCS с открытым кодом, следует сказать, что Subversion фактически стала стандартом некоммерческой VCS, заменившим старую и добрую CVS (Concurrent Versions System). Системы CVS все еще отлично подходят для ограниченного использования, но Subversion привлекает тем, что для ее работы требуется практически только небольшая настройка Web-сервера. Subversion имеет некоторые проблемы, которые мы здесь обсудим, но в большинстве случаев она отлично работает.

Так почему же нам нужно еще что-то? Система Git (с заглавной "G"; т.к. git - это инструмент командной строки) во многом спроектирована так, чтобы быть лучше Subversion. Она является одной из многих распределенных VCS. Лично мне довелось работать с Arch/tla, Mercurial, Bazaar, darcs и некоторыми другими. По многим причинам, о которых я буду рассказывать, когда они будут становиться важными для нашего рассказа, Git стала популярной и часто считается одним из двух лидеров (наряду с Subversion) среди персональных и корпоративных VCS.

Есть две причины, по которым вы, будучи пользователем Subversion, можете заинтересоваться Git.

  • Вы планируете перейти к использованию Git, так как Subversion вас в чем-либо ограничивает.
  • Вам интересно узнать о Git и вы хотите сравнить ее с Subversion.

Хотя, возможно, есть и третья причина: Git – это относительно новая технология, которую вы хотите указать в своем резюме. Я надеюсь, это не является вашей главной целью; изучение Git – это одна из самых полезных вещей, которые может сделать разработчик. Даже если вы не используете Git сейчас, концепции и рабочий процесс, реализованные в этой распределенной VCS, наверняка станут важными знаниями для большинства сегментов ИТ-индустрии в следующие 10 лет, поскольку отрасль переживает крупные перемены в своих границах и географической структуре.

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

Эта статья предназначена для пользователей Subversion начального и среднего уровня. Читатель должен быть знаком с Subversion и с общими принципами работы систем управления версиями. Информация в этой статье главным образом предназначена для пользователей UNIX®-подобных систем (таких как Linux® и Mac OS X) и в меньшей степени для пользователей Windows®.

В части 2 этой серии мы обсудим продинутые приемы использования Git: слияние ветвей, генерация файлов различий и другие типичные задачи.

Основы Subversion и Git

Далее вместо "Subversion" я буду использовать аббревиатуру "SVN", чтобы меньше изнашивать клавиши U, B, E, R, S, I и O на моей клавиатуре.

git-svn

Возможно, вы слышали о git-svn – инструменте, позволяющем использовать Git при работе с репозиторием Subversion. В некоторых ситуациях он может быть полезен, но использовать клиент от распределенной системы при работе с централизованной VCS - это все-таки не переход на распределенную VCS.

Итак, чем же хороша SVN? Возможно, вы уже знаете, что главным в VCS являются не файлы, а изменения. SVN, работающая на центральном сервере, добавляет изменения в свой репозиторий данных и может предоставить вам копию этих данных после каждого изменения. Эта копия имеет номер версии; номер версии очень важен для SVN и для людей, работающих с ней. Если ваше изменение следует после моего, ваш номер версии гарантированно будет больше моего.

Git имеет похожую цель – отслеживание изменений, - но не имеет централизованного сервера. Это очень важное отличие. SVN – система централизованная, а Git – распределенная, поэтому в Git не может быть возрастающего порядка версий, так как в ней нет "последней версии". Однако в ней все же имеются уникальные идентификаторы версий, просто сами по себе они не так полезны, как номера версий (ревизий) в SVN.

В Git важнейшим действием является не фиксация изменений (commit), а их слияние (merge). Кто угодно может клонировать репозиторий и вносить изменения в этот клон. Слияние изменений из клона в основной репозиторий делается по усмотрению владельца реозитория. В качестве альтернативы разработчики могут сами публиковать (push) свои изменения в основном репозитория. Мы рассмотрим только последнюю модель авторизованной публикации изменений.


Работа с директорией в SVN

Начнем с простого типичного примера – отслеживание содержимого директории с помощью SVN. Нам понадобится SVN-сервер и, очевидно, директория с файлами, а также учетная запись на этом сервере с правом фиксации изменений как минимум в этой директории. Начнем с добавления и фиксации директории:

Листинг 1. Настраиваем директорию для работы в SVN
% svn co http://svnserver/...какой-либо путь.../top
% cd top
% cp -r ~/my_directory .
% svn add my_directory
% svn commit -m 'добавляем директорию'

Что это нам дает? Теперь мы можем получать из репозитория последние версии любых файлов в этой директории, удалять файлы, переименовывать их, создавать новые файлы и директории, фиксировать изменения в существующих файлах и т.д:

Листинг 2. Простые файловые операции в SVN
# получаем из репозитория последнюю версию файлов
% svn up
# проверяем статус
% svn st
# удаляем файлы
% svn delete
# переименовываем файлы (фактически здесь выполняется delete + add)
% svn rename
# создаем директорию
% svn mkdir
# добавляем файл
% svn add
# фиксируем изменения (всё, что было сделано выше и изменения содержимого файлов)
% svn commit

Мы не будем здесь подробно изучать эти команды, а просто их запомним. Чтобы ознакомиться с базовой справочной информацией по любой из этих команд, наберите svn help COMMAND, а для получения подробных сведений обращайтесь к руководству пользователей.


Работа с директорией в Git

Я буду действовать таким же образом, как и в примере с SVN. Как и прежде, я предполагаю, что у вас есть директория с данными.

В качестве удаленного сервера я использовал бесплатный сервис github.com, но вы, конечно же, можете использовать любой другой сервер. GitHub –это простой способ попробовать поработать с удаленным Git-репозиторием. На момент написания статьи объем данных для бесплатной учетной записи ограничен 300 МБ, кроме того, репозиторий должен быть публичным. Я завел учетную запись с именем “tzz” и создал публичный репозиторий "datatest"; можете его использовать. Я предоставил свой публичный SSH-ключ. Если у вас еще нет своего ключа, следует его сгенерировать. Также можно попробовать серверы Gitorious или repo.or.cz. В Wiki-разделе сайта git.or.cz имеется большой список сайтов, предоставляющих услуги хостинга репозиториев Git (см. ссылку в разделе Resources).

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

Сначала нужно установить систему Git, свою для каждой платформы, и выполнить для нее начальную настройку. На странице загрузки Git (см. Resources) перечислено несколько вариантов для различных платформ. (На Mac OS X я использовал команду port install git-core, но, чтобы ее использовать, сначала нужно установить MacPorts. На странице загрузки Git также имеется ссылка на отдельный установщик Git для MacOS X Git, который, возможно, лучше подойдет в большинстве случаев.)

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

Листинг 3. Базовая настройка Git
% git config --global user.name "Ted Zlatanov"
% git config --global user.email "tzz@bu.edu"

Уже сейчас можно заметить отличие от SVN: в SVN имя пользователя назначается на стороне сервера. В Git вы можете задать какое угодно имя, даже "Великолепная мартышка Витгенштейна", если оно вам нравится (я удержался от этого соблазна).

Далее я настрою файлы данных и инициализирую ими свой репозиторий. (GitHub также может импортировать их из репозитория SVN, что может оказаться полезным.)

Листинг 4. Настройка директории и первая фиксация
# возьмем несколько файлов
% cp -rp ~/.gdbinit gdbinit
% mkdir fortunes
% cp -rp ~/.fortunes.db fortunes/data.txt
# инициализация
% git init
# "Initialized empty Git repository in /Users/tzz/datatest/.git/"
# add the file and the directory
% git add gdbinit fortunes
% git commit -m 'инициализация'
#[master (root-commit) b238ddc] инициализация
# 2 files changed, 2371 insertions(+), 0 deletions(-)
# create mode 100644 fortunes/data.txt
# create mode 100644 gdbinit

Git выводит информацию о режимах доступа к файлам; 100644 является восьмеричным представлением битов прав доступа к этим файлам. На них можно не обращать внимания, а вот сообщение о 2371 вставке может показаться загадочным. Ведь мы изменили всего 2 файла, не так ли? На самом деле это число обозначает количество вставленных строк. И, конечно же, мы не удалили ни одной строки.

А что насчет публикации (переноса) наших изменений на сервере GitHub? В документации об этом рассказывается на примере сервера с именем “origin” (вы можете использовать любое другое имя). Следует сказать, что для того, чтобы узнать больше о какой-либо команде Git, например, git remote, нужно набрать git remote --help или git help remote. Такое поведение типично для инструментов командной строки, SVN также работает очень похожим образом.

Листинг 5. Публикация изменений в удаленном репозитории
# помните, что наш удаленный репозиторий называется "datatest"?
% git remote add origin git@github.com:tzz/datatest.git
# публикуем изменения
% git push origin master
#Warning: Permanently added 'github.com,65.74.177.129' (RSA) to the list of known hosts.
#Counting objects: 5, done.
#Delta compression using 2 threads.
#Compressing objects: 100% (4/4), done.
#Writing objects: 100% (5/5), 29.88 KiB, done.
#Total 5 (delta 0), reused 0 (delta 0)
#To git@github.com:tzz/datatest.git
# * [new branch]      master -> master

Здесь OpenSSH выдает предупреждение, связанное с тем, что ранее машина github.com была ему неизвестна. Не обращайте на него внимания.

Сообщения, выдаваемые Git, чрезвычайно подробны. В отличие от легких для понимания сообщений SVN, в Git сообщения написаны посвященными и предназначены для посвященных. Если вы родом из Дюны Герберта Фрэнка и обучены как биокомпьютер, возможно вы поймете их, хотя тогда, возможно, вы уже написали свою собственную версию Git. Ну а остальным сообщения о дельта-сжатии и количестве используемых им потоков просто не очень важны (и могут вызывать головную боль).

Перенос изменений был сделан через SSH, но также можно использовать другие протоколы, такие как HTTP, HTTPS, rsync и file. Более подробную информацию см. в справке: git push --help.

Мы подошли к самому главному различию между SVN и Git. В SVN операция commit указывает: «надо скопировать это на центральный сервер». В SVN ваши изменения остаются неосязаемыми, пока вы их не зафиксируете (commit). В Git фиксация изменений является локальной, у вас есть локальный репозиторий, которому нет дела до того, что происходит на удаленной стороне. Можно откатить назад изменение, ветвь, зафиксировать изменение в ветви и т.д. без какого-либо взаимодействия с удаленным сервером. Публикация изменений (push) в Git по сути является синхронизацией состояния вашего репозитория с удаленным сервером.

Хорошо, напоследок давайте посмотрим, как то, что мы только что сделали, отображается в журнале Git:

Листинг 6. Журнал Git
% git log
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    инициализация

В журнале есть запись только о фиксации изменений (обратите внимание, что здесь, в отличие от номера ревизии в SVN, фигурирует длинный случайный идентификатор операции фиксации). Нет никакого упоминания о синхронизации, проводимой по команде git push.


Совместная работа с помощью Git

До сих пор мы использовали Git в качестве замены SVN. Конечно, чтобы сделать все интереснее, необходимо иметь нескольких пользователей и несколько наборов изменений. Давайте работать с нашим репозиторием с еще одной машины (я буду использовать машину с Ubuntu GNU/Linux; на ней пакет, который надо установить, называется не git, а git-core):

Листинг 7. Настраиваем еще один экземпляр Git и загружаем в нем содержимое репозитория
% git config --global user.name "The Other Ted"
% git config --global user.email "tzz@bu.edu"
% git clone git@github.com:tzz/datatest.git
#Initialized empty Git repository in /home/tzz/datatest/.git/
#Warning: Permanently added 'github.com,65.74.177.129' (RSA) to the list of known hosts.
#remote: Counting objects: 5, done.
#remote: Compressing objects: 100% (4/4), done.
#Indexing 5 objects...
#remote: Total 5 (delta 0), reused 0 (delta 0)
# 100% (5/5) done
% ls datatest
#fortunes  gdbinit
% ls -a datatest/.git
# .  ..  branches  config  description  HEAD  hooks  index  info  logs  objects  refs
% ls -a datatest/.git/hooks
# .  ..  applypatch-msg  commit-msg  post-commit  post-receive post-update
#  pre-applypatch  pre-commit  pre-rebase  update

OpenSSH опять выдает предупреждение о том, что раньше эта машина не работала через SSH с GitHub. Команда git clone похожа на команду SVN checkout, но здесь вместо получения определенной версии содержимого мы получаем весь репозиторий целиком.

Я вывел здесь содержимое директории datatest/.git и ее поддиректории hooks, чтобы показать, что мы получили действительно все. По умолчанию Git не таит никаких секретов, в отличие от SVN, которая по умолчанию хранит репозиторий в тайне и разрешает доступ только к копиям содержимого.

Кстати, если вы хотите настроить для своего Git-репозитория какие-либо правила, которые бы выполнялись, например, при каждой фиксации изменений, это можно сделать с помощью сценариев в директории hooks. Это обычные сценарии оболочки, во многом похожие на “ловушки” в SVN, которые согласно стандартам UNIX возвращают ноль в случае успеха и что-либо другое в случае ошибки. Я не буду здесь вдаваться в детали сценариев-«ловушек», но если вы собираетесь использовать Git в командной работе, вам определенно следует их подробно изучить.

Итак, пользователь "The Other Ted" хочет добавить новый файл в главную ветвь (которую можно грубо соотнести с ветвью TRUNK в SVN), а также создать новую ветвь с некоторыми изменениями в файле gdbinit.

Листинг 8. Добавляем файл и создаем новую ветвь
# копируем файл, который будет добавлен...
% cp ~/bin/encode.pl .
% git add encode.pl
% git commit -m 'добавляем encode.pl'
#Created commit 6750342: добавляем encode.pl
# 1 files changed, 1 insertions(+), 0 deletions(-)
# create mode 100644 encode.pl
% git log
#commit 675034202629e5497ed10b319a9ba42fc72b33e9
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    добавляем encode.pl
#
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    инициализация
% git branch empty-gdbinit
% git branch
#  empty-gdbinit
#* master
% git checkout empty-gdbinit
#Switched to branch "empty-gdbinit"
% git branch
#* empty-gdbinit
#  master
% git add gdbinit
% git commit -m 'empty gdbinit'
#Created commit 5512d0a: empty gdbinit
# 1 files changed, 0 insertions(+), 1005 deletions(-)
% git push
#updating 'refs/heads/master'
#  from b238ddca99ee582e1a184658405e2a825f0815da
#  to   675034202629e5497ed10b319a9ba42fc72b33e9
#Generating pack...
#Done counting 4 objects.
#Result has 3 objects.
#Deltifying 3 objects...
# 100% (3/3) done
#Writing 3 objects...
# 100% (3/3) done
#Total 3 (delta 0), reused 0 (delta 0)

Это был длинный пример, и я надеюсь, что вы не заснули, читая его. Если же вы заснули, я надеюсь, вам снились репозитории Git, синхронизирующиеся в бесконечном вальсе наборов изменений (о, не беспокойтесь, вам будет это сниться).

Сначала я добавил и зафиксировал файл (encode.pl, всего из одной строки). После фиксации удаленный репозиторий ничего не знал о том, что я сделал изменения. Затем я создал новую ветвь empty-gdbinit и переключился в нее (также это можно было сделать командой git checkout -b empty-gdbinit). В этой ветви я добавил пустой файл gdbinit и зафиксировал это изменение. И, наконец, я перенес изменения на удаленный сервер.

Если переключиться в главную ветвь, мы не увидим в журнале записи об «empty gdbinit». Т.е. каждая ветвь имеет собственный журнал, что представляется логичным.

Листинг 9. Просматриваем журналы различных ветвей
# мы все ещё находимся в ветви empty-gdbinit
% git log
#commit 5512d0a4327416c499dcb5f72c3f4f6a257d209f
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    empty gdbinit
#
#commit 675034202629e5497ed10b319a9ba42fc72b33e9
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    добавляем encode.pl
#
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    инициализация
% git checkout master
#Switched to branch "master"
% git log
#commit 675034202629e5497ed10b319a9ba42fc72b33e9
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    добавляем encode.pl
#
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    инициализация

Когда мы выполнили команду push, Git сообщил серверам GitHub: «Эй, посмотрите, добавился новый файл с именем encode.pl»

Web-интерфейс GitHub теперь будет отображать файл encode.pl. Однако в GitHub все еще имеется только одна ветвь. Почему ветвь empty-gdbinit не была синхронизована? По умолчанию Git не предполагает, что вы хотите публиковать ветви и их изменения. Чтобы сделать это, нужно опубликовать все:

Листинг 10. Публикуем все изменения
% git push -a
#updating 'refs/heads/empty-gdbinit'
#  from 0000000000000000000000000000000000000000
#  to   5512d0a4327416c499dcb5f72c3f4f6a257d209f
#updating 'refs/remotes/origin/HEAD'
#  from 0000000000000000000000000000000000000000
#  to   b238ddca99ee582e1a184658405e2a825f0815da
#updating 'refs/remotes/origin/master'
#  from 0000000000000000000000000000000000000000
#  to   b238ddca99ee582e1a184658405e2a825f0815da
#Generating pack...
#Done counting 5 objects.
#Result has 3 objects.
#Deltifying 3 objects...
# 100% (3/3) done
#Writing 3 objects...
# 100% (3/3) done
#Total 3 (delta 1), reused 0 (delta 0)

Интерфейс для мыслителей снова предстает во всей красе. Но мы сможем разобраться в том, что происходит, не так ли? Возможно, мы не великие мыслители, но наш здравый смысл подскажет нам, что 0000000000000000000000000000000000000000 – это некая специальная начальная метка. Также из журнала, показанного в листинге 9, мы можем заметить, что метка 5512d0a4327416c499dcb5f72c3f4f6a257d209f является последней (и единственной) фиксацией в ветви empty-gdbinit. Все остальное для большинства пользователей могло быть написано и на арамейском, так как им до этого нет никакого дела. Теперь в GitHub отображается новая ветвь и ее изменения.

Также имеются команды git mv и git rm, с помощью которых можно соответственно перемещать и переименовывать файлы.


Заключение

В этой статье я рассказал о базовых концепциях Git и организовал с ее помощью управление версиями в простой директории, сравнивая ее по ходу рассказа с Subversion. На простом примере я продемонстрировал работу с ветвями.

В части 2 я расскажу о выполнении слияний, генерации файлов различий и некоторых других командах Git. Я настоятельно рекомендую вам прочитать легко доступное для понимания справочное руководство по Git или хотя бы просмотреть учебное пособие. И то, и другое находится на домашней странице Git, поэтому советую потратить некоторое время на их изучение (см. ссылку в разделе Ресурсы). Имея опыт работы с SVN, сделать это будет не очень сложно.

С другой стороны, Git является очень богатой DVCS; узнав больше об ее возможностях, вы почти наверняка станете их использовать для упрощения и улучшения своего стиля работы с VCS. Также, возможно, вы увидите пару снов о Git-репозиториях.

Ресурсы

Научиться

Получить продукты и технологии

  • Загрузите Git, а также ознакомьтесь с множеством инструментов и документов, представленных на странице загрузки Git (EN).
  • Разработайте ваш следующий Linux-проект с помощью пробного ПО от IBM, которое можно загрузить непосредственно с сайта developerWorks.

Обсудить

  • Участвуйте в жизни сообщества developerWorks (EN) - создав свой личный профиль и домашнюю страницу, вы можете приспособить developerWorks к своим интересам и взаимодействовать с другими пользователями developerWorks.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=620813
ArticleTitle=Git для пользователей Subversion: Часть 1. Начинаем
publish-date=02032011