Git меняет правила игры в распределенной Web-разработке

Современные системы управления версиями предоставляют мощную поддержку совместной работы над проектами

Системы управления версиями являются ключевым компонентом большинства проектов разработки ПО, неважно, разрабатываете ли вы приложение, Web-сайт или операционную систему.

Вильям фон Хаген, системный администратор, писатель, WordSmiths

Вильям (Билл) фон Хаген является писателем и администратором UNIX-систем на протяжении 20 лет, а с 1993 года стал активным сторонником Linux. Билл является автором и соавтором книг по таким темам, как Ubuntu Linux, виртуализация с помощью Xen, коллекция компиляторов GNU (gcc), SUSE Linux, Mac OS X, файловые системы Linux и SGML. Он также написал множество статей об издательских технологиях и создании Web-сайтов в Linux и Mac OS X. С Биллом можно связаться по адресу wvh@vonhagen.org.



03.03.2011

Системы управления версиями (version control systems, VCS) предоставляют механизм внесения изменений в файлы проекта и управления ими и широко используются в командной разработке ПО, документации и других онлайновых проектах. Системы VCS важны для проектов разработки не меньше, чем системы резервного копирования, так как они позволяют множеству пользователей фиксировать изменения в одних и тех же файлах проекта, не рискуя при этом случайно перезаписать изменения своих коллег.

Часто используемые сокращения

  • CSS: каскадные таблицы стилей (Cascading Style Sheet)
  • GUI: графический интерфейс пользователя (Graphical user interface)
  • HTML: язык разметки гипертекста (Hypertext Markup Language)
  • HTTP: протокол передачи гипертекста (Hypertext Transfer Protocol)

Даже если бы Линус Торвальдс не разработал ядро операционной системы Linux®, возможно он все равно был бы так же известен благодаря созданию системы управления версиями Git. Разработка таких сложных проектов, как Linux, обеспечивает тестирование системы VCS в экстремальных условиях, поэтому неудивительно, что Git быстро стала стабильной, мощной и гибкой системой.

В Linux и UNIX® применяется чрезвычайно много систем VCS, начиная от таких динозавров, как RCS и CVS и заканчивая современными системами, такими как Subversion, Mercurial, Bazaar, Arch и Darcs. По иронии судьбы (особенно по отношению к Linux), Git была разработана для замены коммерческой VCS BitKeeper, которая обладала впечатляющими уникальными возможностями и имела бесплатную версию. BitKeeper все так же является впечатляющей системой, но изменения в схеме ее лицензирования, в конце концов, вынудили Торвальдса искать альтернативу, и, в лучших традициях свободного ПО, он решил написать свою собственную VCS. Как и ядро Linux, Git теперь является продуктом расширений, исправлений и иного участия в нем несчетного числа разработчиков ПО с открытым кодом.

Благодаря своей мощи и бесплатности Git быстро распространяется в открытых проектах и научных организациях. В корпоративных и научных средах Git может приносить пользу как VCS и как платформа для совместной работы. Это привело к тому, что Git применяется во множестве нетрадиционных для VCS проектов, не связанных с управлением исходным кодом. Как рассказывается в этой статье, Git особенно полезна в сложных, распределенных проектах Web-разработки, со сформулированными требованиями к содержимому и к коду, а потому требующих постоянного взаимодействия различных людей.

Git: больше, чем просто VCS

Git была создана для того, чтобы тысячи разработчиков, находящихся в различных точках земного шара и обладающих разного качества подключением к Интернет, могли совместно работать над одним проектом, не сталкиваясь с серьезными проблемами производительности или доступа. Эти фундаментальные требования поддерживаются в Git благодаря следующим важным аспектам:

  • Использование центрального репозитория с одновременным предоставлением каждому разработчику полной копии исходного кода проекта. Это гарантирует, что все разработчики могут выполнить свою работу независимо от текущего состояния своего соединения.
  • Обеспечение быстрой и надежной поддержки создания внутри проекта отдельных рабочих пространств, называемых ветвями, и слияний, т.е. распространения изменений из одной ветви проекта в другие. Ветви облегчают поддержку различных версий пакета, независимо от того, являются ли эти версии постоянными или же они созданы для экспериментов. Слияния являются ключевым аспектом всех систем управления версиями, а особое распространение они имеют в VCS, ориентированных на ветви.
  • Реалзация легкого обмена изменениями в ветвях и коде между группами разработчиков без необходимости занесения этих изменений в центральный репозиторий.

Эти архитектурные решения и их реализация являются ключевыми аспектами успеха Git и удобства его использования. Конечно же, Git также удовлетворяет стандартным требованиям к VCS по неизменяемости и подотчетности. Неизменяемость означает, что изменения, будучи добавлены в репозиторий, становятся неотъемлемой частью истории проекта. Хотя изменения впоследствии могут быть удалены (так называемый reverting – отмена изменений), тем не менее, и изменения, и удаление этих изменений являются неотъемлемой частью истории проекта. Подотчетность означает, что можно легко отследить, кто и когда внес определенные изменения. Для чего было сделано изменение, может оставаться загадкой (хотя при внесении изменений необходимо заполнять комментарий), но, по крайней мере, всегда можно узнать, кого об этом следует спросить.

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


Устанавливаем Git

Пакеты Git доступы в репозиториях большинства дистрибутивов Linux. В Ubuntu, Debian и других системах, использующих формат пакетов .deb, нужно установить пакет git-core В системах, работающих с RPM-пакетами, таких как Fedora, Red Hat, Centos, SUSE и Mandriva, основной пакет Git называется просто git. Базовый пакет Git также требует, чтобы в системе были установлены Perl, библиотеки Perl для шифрования и обработки исключений, а также утилита patch.

При желании получить самую последнюю версию Git для Linux, можно заглянуть на Web-сайт Git, на котором доступны пакеты .deb и RPM, а также последний исходный код Git (если вы хотите собрать свою собственную версию). На сайте Git также доступны скомпилированные версии Git для Mac® OS X, Windows®, Cygwin под Windows и Solaris® от Sun/Oracle. В настоящее время администраторам операционных систем IBM® AIX® и Hewlett-Packard® HP-UX приходится самостоятельно собирать Git для своей платформы из исходного кода. За информацией о получении и сборке Git обращайтесь к разделу Ресурсы.

Основной пакет Git содержит исполняемый файл git и несколько дополнительных приложений. Как можно ожидать, также доступно огромное количество других связанных с Git пакетов. Некоторые из наиболее популярных пакетов перечислены ниже:

  • git-cola. Графический интерфейс (GUI) для работы с файлами и директориями в репозитории Git.
  • git-doc. Устанавливает локальную копию справочника пользователя, руководства и документации.
  • git-gui. Графический интерфейс для работы с репозиториями Git и навигации по ним; использует пакет gitk.
  • git-web. Основанный на Web графический интерфейс работы с репозиториями Git.
  • gitk. Простой графический интерфейс для работы с репозиториями Git и навигации по ним.
  • qgit. Основанное на Qt графическое приложение для просмотра и исследования репозиториев Git.

Пакеты git-gui, git-web, gitk и qgit предоставляют схожую функциональность, хотя git-web основан на Web, в то время как остальные запускаются локально. Любой из этих пакетов может быть полезен при начале работы с Git, хотя возможно пакет git-web является наилучшим выбором в распределенной среде разработки.

Если вам интересно поэкспериментировать с Git, но вы уже работаете с другой системой VCS, вам могут оказаться полезными следующие пакеты:

  • git-cvs. Этот пакет обеспечивает взаимодействие репозиториев Git и CVS, позволяя импортировать CVS-репозитории и историю изменений в Git, вести работу в Git, вносить изменения обратно в CVS-репозиторий, а также импортировать обновления из CVS-репозитория.
  • git-svn. Этот пакет обеспечивает взаимодействие репозиториев Git и Subversion, позволяя импортировать Subversion-репозитории и историю изменений в Git, вести работу в Git, вносить изменения обратно в Subversion-репозиторий, а также импортировать обновления из Subversion-репозитория.

Основные команды Git

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

Аналоги команд Git

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

Посмотреть список основных команд Git можно выполнив команду git без аргументов. Вот часть команд, которые будут показаны в этом списке:

  • add. Добавляет к индексу Git новый файл. Для фактического добавления этого файла в репозиторий Git в дальнейшем нужно выполнить его фиксацию (commit).
  • branch. Позволяет вывести список ветвей, копии которых у вас есть, определить, в какой ветви вы сейчас работаете, создать новые ветви или удалить локальную копию ветвей, которые вы создали или извлекли из репозитория. Эта команда не может переключить вас в другую ветвь. Для переключения надо использовать команду checkout.
  • checkout. Эту команду можно выполнить для ветви или файла/директории. Если ее выполнить для какой-либо ветви, эта ветвь становится вашей рабочей ветвью. Если ее выполнить для какого-либо файла или директории, то этот файл или директория будут обновлены до текущей версии, находящейся в репозитории в вашей рабочей ветви. Также с помощью этой команды можно создать новую ветвь, которая будет основана на указанной существующей ветви, и, возможно, будет отслеживать изменения относительно нее.
  • commit. Записывает (фиксирует) изменения файлов и директорий в индекс Git. Можно указать файлы и директории, изменения в которых мы хотим зафиксировать, с помощью параметра -a добавить все имеющиеся изменения в файлы, отслеживаемые Git, или с помощью параметра --interactive выбрать изменения в файлах и директориях, которые мы хотим зафиксировать за один раз. (Последний вариант может быть особенно полезен, если вы работаете над несколькими задачами, включающими большое количество файлов, но хотите зафиксировать некоторые изменения совместно. Фиксации производятся в локальный репозиторий, если же вы используете удаленный центральный репозиторий, то для того, чтобы опубликовать на нем свои локальные изменения, нужно использовать команду push.)
  • diff. Отображает различия между локальным файлом и его версией, зафиксированной в репозитории или между двумя различными версиями файла, зафиксированными в репозитории. Эта команда чаще всего используется просто с указанием имени файла, чтобы отобразить различия между указанным файлом и его версией, находящейся в репозитории в текущей ветви.
  • fetch. Извлекает обновления индекса из другого репозитория, после чего идентифицирует вновь созданные метки и оповещает о том, какие изменения в файлах и директориях, имеющиеся в репозитории, отсутствуют в локальной копии. Далее можно просмотреть доступные изменения с помощью команды git log. Для фактического извлечения файлов из репозитория следует использовать команду git pull или git rebase.
  • grep. Ищет в файлах текущей ветви соответствия указанному шаблону и отображает их. Эта команда поддерживает большинство параметров обычной команды grep от GNU.
  • log. Показывает журнал фиксаций для текущей ветви или для определенных файлов текущей ветви.
  • merge. Выполняет перенос (слияние) изменений, сделанных в одной ветви, в другую ветвь. Эта команда предоставляет параметр, позволяющий либо автоматически занести изменения, либо перед принятием изменений просмотреть, как будет выглядеть обновленная версия.
  • mv. Переименовывает файл, директорию или символическую ссылку, отслеживаемую Git.
  • pull. Извлекает обновления индекса из другого репозитория и вносит соответствующие изменения в файлы и директории текущей ветви.
  • push. Обновляет индекс удаленного репозитория в соответствии с локальным индексом и информацией об изменении объектов.
  • rebase. Обновляет рабочую ветвь в соответствии с удаленной ветвью и изменяет все не опубликованные в удаленной ветви локальные фиксации таким образом, чтобы они могли быть применены к текущему состоянию удаленной ветви. Это мощная, но потенциально опасная команда, потому что она при необходимости буквально перезаписывает фиксации, так чтобы можно было выполнить слияние. В зависимости от частоты и размера изменений, производимых на удаленном репозитории, зачастую использование обычной команды git pull является предпочтительным.
  • rm. Удаляет файл, директорию или символическую ссылку, отслеживаемую Git.
  • stash. Временно переносит все текущие изменения в стек и возвращает текущую рабочую ветвь в изначальное состояние. Команда git stash save сохраняет текущие изменения в локальный стек, а git stash apply извлекает их и повторно выполняет. Это может быть полезным, когда вы хотите извлечь изменения из удаленного хранилища или выполнить rebase, не фиксируя при этом находящиеся в работе изменения.
  • status. Показывает статус текущей ветви, идентифицируя не занесенные в репозиторий изменения, не отслеживаемые файлы и т.д.

Любую команду Git можно вызвать с параметром --help, чтобы получить по ней детальную информацию, список аргументов, которые можно ей передать и т.д. Также получить справку по любой команде Git можно с помощью команды формата git help command.

Чтобы ознакомиться с полным списком команд Git, выполните команду man git, которая отображает справочную информацию по Git.


Создаем новый проект Git

Чтобы начать использовать Git для существующего проекта, который не использует никакой системы управления версиями, выполните следующие шаги:

  1. Перейдите в директорию, содержащую исходный код проекта:
    $ cd www.move2linux.com
    $ ls
    greenbar_wide.gif  images  index.html  legacy.html  services.html
  2. С помощью команды git init создайте в текущей директории пустой репозиторий:
    $ git init
    Initialized empty Git repository in .git/
  3. Теперь с помощью команды git status можно проверить статус нашего нового проекта.

    Эта команда помечает всё, находящееся в текущей директории как untracked, что означает, что Git не получал инструкций отслеживать эти файлы и директории, хотя он знает об их существовании:

    $ git status
    # On branch master
    #
    # Initial commit
    #
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
    #
    #       greenbar_wide.gif
    #       images/
    #       index.html
    #       legacy.html
    #       services.html
    nothing added to commit but untracked files present...
  4. Добавляем файлы и директории проекта в новый репозиторий Git.

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

    $ git add .
  5. Выполним команду git status еще раз, чтобы убедиться, что все файлы и поддиректории текущей директории были добавлены в новый проект:
      $ git status
      # On branch master
      #
      # Initial commit
      #
      # Changes to be committed:
      #   (use "git rm --cached <file>..." to unstage)
      #
      #       new file: greenbar_wide.gif
      #       new file: images/digits/b/0.gif
      #       new file: images/digits/b/1.gif
      #       new file: images/digits/b/4.gif
      #       new file: images/digits/b/5.gif
      #       new file: images/digits/b/6.gif
      #       new file: images/digits/b/7.gif
      #       new file: images/digits/b/8.gif
      #       new file: images/digits/b/9.gif
      #       new file: index.html
      #       new file: legacy.html
      #       new file: services.html
      #
  6. Выполним команду git commit, чтобы зафиксировать в репозитории начальные версии файлов.

    Если не указать комментарий к изменению в командной строке с помощью параметра –m -m "commit message", то в процессе выполнения команды commit будет запущен текстовый редактор по умолчанию, в котором вам нужно будет ввести комментарий к вносимому изменению. Сохранив комментарий и закрыв текстовый редактор, Git заносит изменение в репозиторий и выводит информацию о выполненном изменении и измененных файлах.

    $ git commit 
    Created initial commit dfbd6cc: Initial checkin
    12 files changed, 285 insertions(+), 0 deletions(-)
    ...

Теперь все готово к тому, чтобы начать работать с файлами проекта в Git с помощью описанных выше команд.

Настраиваем центральный репозиторий

Если создавать репозиторий так, как описано в этом разделе, то затем необходимо иногда загружать (pull) в свой репозиторий изменения, сделанные другими пользователями или обновлять (check out) файлы ветви после того, как другие пользователи сами опубликуют (push) в ней свои изменения. В разделе Распределенная Web-разработка с использованием Git рассказывается о настройке центрального репозитория, не содержащего рабочей копии файлов проекта (т.е. хранящего только индекс), и благодаря этому не имеющего такой проблемы.

Делаем изменения в существующем проекте Git

Если вы хотите начать вносить свои изменения в уже созданный кем-либо проект Git, то в этом случае все еще проще. Нужно лишь с помощью команды git clone создать свою собственную рабочую копию проекта:

$ git clone /home/jake/src/maps

В этом примере мы создаем копию проекта maps в своей текущей директории. Далее можно перейти в свою копию проекта и с помощью описанных выше команд начать работать с его файлами.

Клонируем проект Git

Клонирование проекта Git, находящегося на удаленной машине также выполняется просто. Git по умолчанию поддерживает протоколы Secure shell (SSH) и HTTP, а также может использовать свой собственный необычайно эффективный протокол git, если на удаленной машине запущен демон Git, и этот демон экспортирует нужный проект. По умолчанию Git использует SSH, поэтому синтаксис клонирования удаленного репозитория выглядит так, как и можно было ожидать:

$ git clone remote-machine:/home/jake/src/maps
$ git clone ssh://remote-machine/home/jake/src/maps

Замечание: Для клонирования проекта Git с помощью SSH необходимо иметь аутентифицированный доступ к удаленной системе, что является хорошим аргументом для использования протокола git, даже несмотря на то, что для его работы необходимо запускать демон Git.


Распределенная Web-разработка с использованием Git

Репозитории, например такой, какой мы создали выше, содержат рабочую копию всех файлов проекта Git, а также файлы, необходимые Git для отслеживания изменений, ветвей, меток и т.д. По умолчанию, при публикации изменений в репозитории Git, содержащем рабочие копии файлов проекта, происходит только обновление индекса, но не самих файлов проекта. Так сделано потому, что при обновлении файлов могут возникать конфликты слияния изменений, если вы в данный момент работаете с теми же самыми файлами.

Чтобы при публикации изменений выполнялось обновление файлов, нужно создать так называемый пустой репозиторий—– т.е. репозиторий, не имеющий рабочей копии ваших файлов, но содержащий индекс Git, объекты, отражающие изменения этого индекса и другие файлы, необходимые Git. Так как пустой репозиторий не содержит рабочей копии ваших файлов, то в нем никто не может работать, и он служит просто точкой сбора изменений, поступающих от всех разработчиков, работающих над проектом.

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

  1. Зайдем на наш Web-сервер с помощью SSH и перейдем в директорию с содержимым нашего Web-сайта.

    Если содержимое сайта еще не отслеживается Git, настроим здесь репозиторий Git, используя процедуру, описанную в предыдущем разделе. Например:

    $ ssh somehost
    $ cd /var/www/html
    $ git init
    $ git add .
    $ git commit -m "Initial commit"
  2. Переместимся в категорию уровнем выше и создадим пустой репозиторий Git, клонировав только что созданный проект:
    $ cd ..
    $ git clone --bare html html.git

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

  3. Переименуем существующую Web-директорию и создадим новый проект Git с таким же именем, клонировав наш пустой репозиторий:
    $ mv html html.OLD && git clone html.git html

    Директория нового проекта содержит полученную из репозитория версию всех файлов проекта Git, хранящего содержимое нашего Web-сервера.

  4. Отредактируйте (или создайте) в поддиректории hooks пустого репозитория сценарий, который после каждого обновления будет вносить соответствующие изменения в только что созданную директорию.

    Этот сценарий будет выполняться при каждом обновлении какого-либо файла, отслеживаемого нашим пустым репозиторием. Убедитесь, что сценарий является исполняемым файлом:

    $ pushd html.git/hooks
    $ emacs post-update
    $ chmod 755 post-update

    Этот сценарий должен выглядеть примерно так, как показано в листинге 1.

    Листинг 1. Сценарий действий после обновления репозитория
    #!/bin/bash
    #
    WEB_DIR="/var/www/html"
    export GIT_DIR="$WEB_DIR/.git"
    pushd $WEB_DIR > /dev/null
    git pull
    popd > /dev/null

    Обратите внимание, что этот сценарий должен использовать интерпретатор /bin/bash, так как он работает с его встроенными командами pushd и popd. Если сценарий действий после обновления уже существует, можно, убедившись, что он использует правильный интерпретатор, просто добавить в его конец текст нашего сценария. Также необходимо убедиться, что в существующем сценарии нигде не используется команда exec, которая остановит дальнейшее выполнение скрипта.

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

  • Можно работать над файлами в локальной версии Web-сайта, а затем публиковать свои изменения непосредственно в центральном репозитории совместного доступа.
  • Ваш коллега командой pull может получать от вас изменения, которые вы зафиксировали в своем локальном репозитории. Такой прием позволяет совместно работать над файлами перед их публикацией в центральном репозитории, а значит и на вашем Web-сайте.

Хотя Git намного быстрее большинства систем VCS, ее навряд ли стоит использовать непосредственно на работающей версии Web-сайта, если вы работаете над большим, сложным и интенсивно используемым сайтом. Посетители сайта могут столкнуться со случаями, когда часть файлов сайта уже обновилась, а другая часть - еще нет. Особенно проблематичная ситуация может возникнуть при загрузке страницы, уже использующей обновленную таблицу стилей CSS, когда это обновление еще не получено. Такие проблемы можно легко предотвратить, если хранить старое и новое содержимое сайта в разных каталогах, а каталог, с которым Web-серверу следует работать, указывать символической ссылкой или в конфигурационном файле, которые можно легко поменять, когда вы захотите, чтобы ваш сайт начал работать с новым содержимым.


Заключение

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

Ресурсы

Научиться

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

Комментарии

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, Web-архитектура
ArticleID=630442
ArticleTitle=Git меняет правила игры в распределенной Web-разработке
publish-date=03032011