пятница, 15 июля 2011 г.

Git - распределенная система контроля версий (часть 2)

Использование команд на практике

Подготовка Git:
  • git congif -- global user.name “Your name” - указываем имя
  • git config --global user.email “your_email@gmail.com” - и адрес электронной почты
Создание проекта:
  • создаем каталог, переходи в него и создаем файл test.html
  • git init - создаем git репозиторий из каталога
  • git add test.html - добавляем страницу в репозиторий
  • git commit -m “First commit” - коммитимся
  • git status - проверяем текущее состояние репозитория
Внесение изменений:
  • изменяем страничку test.html
  • git status - и проверяем состояние рабочего каталога, git знает что произошло изменения в файле test.html и эти изменения еще не зафиксированные в репозитории
Индексация изменений:
  • gid add test.html - проиндексируем изменения
  • git status - проверяем состояние, git знает об изменении, но оно еще не записано в репозиторий
Git позволяет записывать изменения в малых коммитах, сначала нужно проиндексировать одну часть файлов и закоммитить, а потом следующую часть. Метка -m делает комментарий в командной строке
  • git add first.html
  • git add second.html
  • git commit -m “First part”
  • git add third.html
  • git commit -m “Second part”
Git фокусируется на изменениях в файле, а не на самом файле. Когда происходит индексация файла, мы говорим, что git надо отметить текущее состояние файла, коммит которого будет выполнен позже.
  • изменяем test.html страничку и проиндексируем
  • обратно изменяем test.html страничку
  • git status  - проверяем состояние
Мы увидим, что у нас есть два состояния файла test.html - первое проиндексировано и готово к коммиту, а второе непроиндексированно. Если сделать коммит сейчас, то заголовки не сохранятся в репозиторие.
  • git commit -m “added changes” - выполняем коммит проиндексированного изменения
  • git status - проверяем состояние и видим, что test.html имеет незафиксированные изменения
  • git add . - добавляем все изменения в файлы текущего каталога и все подкаталоги
  • git status - проверяем состояние и видим, что все проиндексировано и готово к коммиту
  • git commit - m “final changes”
Просмотр истории. Примеры команд для просмотра истории проекта:
  • git log --pretty=oneline - однострочный формат
  • git log --pretty=oneline --author=;
  • git log --pretty=oneline --max-count=2
  • git log --pretty=oneline --since=”5 minutes ago”
  • git log --pretty=oneline --all
также можно определить свой формат вывода:
  • git log --pretty=format" %h %ad | %s%d [%an]" --graph --date=short - указываем короткий хеш коммита, дату коммита, комментарий и тег, имя автора, отображение коммита в виде ASCII-графика, короткий формат даты
Использование алиасов - короткая форма команд, для применения нужно добавить след. сокращения в файл .config:
[alias]
            lg = git log --pretty=format" %h %ad | %s%d [%an]" --graph --date=short
            co = checkout
            ci = commit
            br = branch
Переключение между ветками:
  • git lg - получаем хешы всех предыдущих коммитов
  • git checkout b816555 - используем полученный хеш чтобы вернуться к определенному состоянию
  • git checkout master - возвращаемся к последней версии в ветке master
Создание тегов:
  • git tag version1- создаем тег version1, текущая версия
  • git tag version1^1 - переключаемся на пред. версию
  • git tag version1-beta - создаем тег для новой версии
  • git checkout version1-beta - переключаемся для другую ветку
  • git tag - просмотр доступных тегов
  • git lg master --all - просмотр тегов в логе
Отмена локальных изменений, до индексации:
  • git checkout master - убеждаемся, что мы находимся на последнем коммите ветки
вносим изменения в файле test.html, но не индексируем
  • git checkout test.html - отмена изменений
Отмена проиндексированных изменений, до коммитов:
     вносим изменения в файл test.html и проиндексируем изменение
  • git add test.html
  • git reset HEAD test.html - очищаем буферную зону от изменений, но reset не изменяет рабочий каталог, т.е. рабочий каталог содержит изменения
  • git checkout test.html - удаляем изменения
если все прошло успешно, то после выполнения команды git status выведет “nothing to commit (working directory clean)”
Отменна коммитов:
     вносим изменения в файл test.html и коммитим
  • git revert HEAD --no-edit - выполняем отмену последнего произведенного коммита
  • git lg - проверяем историю коммитов
     также возможно отменять коммит по это хеш-значению 
Удаление ошибочного коммита из ветки:
  •  git lg - при выполнении команды можно увидеть два последних коммита
      давайте уберем неправильный коммит и сделаем вид, что его никогда не было, для этого:
  • git tag wrong - отмечаем последний коммит тегом
  • git reset --hard v1 - сброс коммита к предшествующему коммиту и указываем, что рабочий каталог должен быть обновлен в соответствии с новым head ветки
  • git lg --all - видим, что ошибочные коммиты присутствуют в репозитории, но отсутствуют в ветке master
  • git tag -d wrong - удаляем тег wrong и коммиты на которые он ссылался, сборщиком мусора
     после проверки(git lg --all) видим, что тег wrong не отображается в репозитории
Внесение изменений в коммиты:
  • вносим изменения в файл test.html и коммитим
  • git add test.html
  • git commit -m “author comment was added”
после выполнения коммита вы понимаете, что забыли добавить доп. комментарии. Для того чтобы не создавать отдельный коммит, ради доп. комментария, просто изменим предыдущий коммит.
  • вносим изменения в файл test.html
  • git add test.html
  • git commit --amend -m “author and e-mail comment was added”
После просмотра истории(git lg) видим, что оригинальный коммит был изменен.
Работа с обьектами Git:
  • git lg --max-count=1 - выводим последний коммит
  • git cat-file -p e1d1489 - выводим обьект коммита из главной ветки master
tree 771a1209c66c0e9210914aa5edc58e011d3158a2
parent 6d10a74c12ac34f5762cffc6a05acf424faefb8c
author Dmitry Nikolaenko 1312139846 +0300
committer Dmitry Nikolaenko 1312139846 +0300
index.html was added
  • git cat-file -p 771a1209c - выводим дерево каталогов
  • git cat-file -p 100644 - вывод файла по хешу из дерева
Создание ветки:
создадим новую ветку и перейдем в нее
  • git branch resources
  • git checkout resources
добавим файл style.css в каталог lib и добавим стили в файл test.html, проиндексируем и закоммитим
  • git checkout master - перейдем в master
  • cat lib/test.html - видим, что test.html не использует стили style.css, т.к. изменения были выполнены в ветке resources
Слияние веток:
перейдем в ветку resources и выполним слияние master с resources
  • git checkout resources
  • git merge master
  • git lg --all
Разрешение конфликтов:
Выполним в ветке master изменения, перейдем в ветку resources и попытаемся ее обьединить с новой веткой master.
  • git checkout resources
  • git merger master
получим приблиз. след. строки
Auto-merging lib/test.html
CONFLICT (content): Merge conflict in lib/test.html
Automatic merge failed; fix conflicts and then commit the result.
Конфликт нужно решить вручную, проиндексировать и закоммитить.
Сброс ветки и преобразование:
  • git checkout resources
  • git reset --hard 9bf1954 - сброс ветки resources до момента слияния
  • git checkout master
  • git reset --hard 73cb08c - сброс ветки master до конфликтующего коммита
  • git checkout resources
  • git rebase master
ветка resources содержит все свои изменения + все изменения ветки master
  • git checkout master
  • git merge resources - слияние resources в master, теперь ветки идентичны
Клонирование репозиториев:
  • git clone test cloned_test - создаем клон репозитория
  • git remote show origin - смотрим информац. об имени по умолчанию и видим, что оригинальным репозиторием является test
  • git branch -a - выводим список всех веток, но оказывается, что ветки в удаленном репозитории не рассматриваются как локальные и по этому нам придется создать ее вручную. Для этого:
  • cd ../test - перейдем в репоз. test
Изменим любой файл, проиндексируем и закоммитим изменения. Теперь в оригинальном репозитории есть более поздние изменение, которых нет в клонированной версии.
  • cd ../cloned_test - переходим в клонированную версию главного репозитория
  • git fetch - извлекаем изменения из удаленного репозитория(выполняется без слияния в локальных ветках)
  • git merge origin/master  - перемещаем извлеченные изменения в текущую ветку и рабочий каталог
Того же результата можно добиться выполнением команды git pull.

понедельник, 11 июля 2011 г.

Git - распределенная система контроля версий (часть 1)

     Git - распределенная система управления версиями файлов. Поддерживает быстрое разделение и слияние версий, включает инструменты для визуализации и навигации по нелинейной истории разработки. Git предоставляет каждому разработчику локальную копию всей истории разработки, изменения копируются из одного репозитория в другой.
     В Git теряется понятие ревизии, характерное для линейных моделей разработки. Вместо этого каждый из коммитов определяется хэшем. Это немножко неудобно для восприятия, поэтому разумно использовать механизм тэгов для того, чтобы выделять ключевые коммиты.     
     Преимуществом является то, что можно работать с кодом как хотите, а не как диктует система контроля версий. В git для идентификации любых объектов используется уникальный хэш из 40 символов, который определяется хэшируюшей функцией на основе содержимого объекта. Объекты — это коммиты, файлы, тэги, деревья. Поскольку хэш уникален для содержимого, например, файла, то и сравнивать такие файлы очень легко — достаточно просто сравнить ихние хешы. Хэши являются идентификаторами коммитов. Также хеш является продвинутым аналогом ревизий Subversion.
1) Централизованная и распределенная система контроля версий     
        В централизованной подходе разработки существует единственный удаленный центральный репозиторий в который разработчики вносят свои изменения. Разработка при таком подходе происходит так: выкачивается последняя версия проекта из репозитория, разрабатывается или исправляется новый функционал, происходит обращение к репозиторию для разрешения конфликтов, загружается новая ревизия на сервер. Иногда требуется работать удаленно без доступа к центральному репозиторию, это ограничивает действия разработчика и лишает гибкости при разработке.     
     В распределенном подходе не существует главного репозитория (как в SVN), всем разработчикам предоставляется собственный репозиторий с которым они работают. Связь с другим репозиториями нужна только для изменения/чтения версий файлов других ветвей.
2) Особенности Git
  • гибкая система управления которая может использоваться не только в сфере разработки 
  • удобное ветвление и слияние, которое происходит быстро и легко 
  • предоставляет гибкие и простые в использовании инструменты для ведения истории проекта 
  • легкость взаимодействия между репозиториями 
  • всем разработчикам предоставляется полная копия исходного кода проекта, это означает что каждый разработчик работает независимо от текущего состояния проекта 
3) Архитектура Git
     Git-репозиторий состоит из четырех типов обьектов: Blob, Tree, Commit и References.

  • Blob (Binary Large Object) – все файлы проекта являются blob-ами. Это тип данных , который вмещает содержимое файла и собственный SHA-1 хеш. 
  • Tree - это каждая директория проекта. Tree ссылается на другие tree и blob'ы, и указывает их имена и атрибуты. 
  • Commit хранит историю проекта. Содержит собственный SHA-1 хеш, ссылку на одно дерево, ссылку на предыдущий коммит. 
  • Reference содержит ссылку на любой из четырех обьектов - Blob, Tree, Commit и References. Он указывает на обьект на который он ссылается. Работать с набором символов не очень удобно, в отличие от SHA1-хеша, можно именовать как захочется. 
     Ссылки делятся на ветки(Head, Branch) и теги(Tag).
  • Ветвь (Head, Branch) - ссылка, которая указывает на последний коммит определенной ветви, используется как синоним файла на который она ссылаетс 
  • Тег (tag) - ссылается на один и тот же обьект(blob, tree, commit, tag), хранит ссылку на сам коммит, имя автора, собственное имя и комментарий. Tag можно разделить на легковесный(состоит из имени и ссылки на коммит) и тяжеловесный или аннотированный(состоит из собственного хеша, типа указываемого обьекта, символьного имени, даты и времени создания тега, имени и e-mail). 
4) Основные команды Git
  • add - индексация изменений 
  • branch - выводит список ветвей, создает новые ветки или удаляет копию ветвей 
  • checkout - переключение между ветками, извлечение отдельных файлов и истории коммитов 
  • commit - записывает изменения файлов и директорий в индекс git 
  • diff - показывает различия между деревьями проекта, коммитами и состоянием индекса 
  • fetch - извлекает изменения удаленной ветки из репозитория 
  • grep - поиск в файлах текущей ветки соответствия указанному шаблону и отображает их 
  • log - информация о коммитах или по отдельным файлам 
  • merge - слияние изменений, сделанных в одной ветви, в другую ветвь 
  • mv - переименовывает файл, директорию или символическую ссылку 
  • pull - забирает изменения из центрального репозитория 
  • push - вносит изменения в центральный репозиторий 
  • rebase - берет коммиты из ветки, где было совершенно несколько коммитов и накладывает их на последний коммит ветки master 
  • rm - удаляет файл, директорию или символическую ссылку 
  • status - показывает состояние проекта, измененные и не добавленные файлы, индексированные файлы 
  • show - показывает изменения, сделанные отдельным коммитом