Раздел «Язык Си».GitTutorial21:

Назад: Шаг 11-20 .. Вперед: Шаг 31-40

21. Подробнее о структуре

Цели: Добавить еще один файл в наш репозиторий

21.01 Добавление index.html

Давайте добавим файл index.html в наш репозиторий. Следующий файл отлично подойдет для этой цели.

ФАЙЛ: HTML

<html>
  <body>
    <iframe src="lib/hello.html" width="200" height="200" />
  </body>
</html>
Добавьте файл и сделайте коммит.

ВЫПОЛНИТЕ:

git add index.html
git commit -m "Added index.html."
Теперь при открытии index.html, вы должны увидеть кусок страницы hello в маленьком окошке.

22. Git внутри: Каталог .git

Цели: Узнать о структуре каталога .git

22.01 Каталог .git

Настало время провести небольшое исследование. Для начала, из корневого каталога вашего проекта…

ВЫПОЛНИТЕ:

ls -C .git

РЕЗУЛЬТАТ:

$ ls -C .git
COMMIT_EDITMSG  MERGE_RR    config      hooks       info        objects     rr-cache
HEAD        ORIG_HEAD   description index       logs        refs
Это магический каталог, в котором хранятся все «материалы» git. Давайте заглянем в каталог объектов.

22.02 База данных объектов

ВЫПОЛНИТЕ:

ls -C .git/objects

РЕЗУЛЬТАТ:

$ ls -C .git/objects
09  24  28  45  59  6a  77  80  8c  97  af  c4  e7  info
11  27  43  56  69  6b  78  84  91  9c  b5  e4  fa  pack

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

22.03 Углубляемся в базу данных объектов

ВЫПОЛНИТЕ:

ls -C .git/objects/<dir>
РЕЗУЛЬТАТ:
$ ls -C .git/objects/09
6b74c56bfc6b40e754fc0725b8c70b2038b91e  9fb6f9d3a104feb32fcac22354c4d0e8a182c1
Смотрим в один из каталогов с именем из 2 букв. Вы увидите файлы с именами из 38 символов. Это файлы, содержащие объекты, хранящиеся в git. Они сжаты и закодированы, поэтому просмотр их содержимого нам мало чем поможет. Рассмотрим далее каталог .git внимательно

22.04 Config File

ВЫПОЛНИТЕ:

cat .git/config

РЕЗУЛЬТАТ:

$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[user]
name = Alexander Shvets
email = alex@githowto.com

Это файл конфигурации, создающийся для каждого конкретного проекта. Записи в этом файле будут перезаписывать записи в файле .gitconfig вашего главного каталога, по крайней мере в рамках этого проекта.

22.05 Ветки и теги

ВЫПОЛНИТЕ:

ls .git/refs
ls .git/refs/heads
ls .git/refs/tags
cat .git/refs/tags/v1

РЕЗУЛЬТАТ:

$ ls .git/refs
heads
tags
$ ls .git/refs/heads
master
$ ls .git/refs/tags
v1
v1-beta
$ cat .git/refs/tags/v1
fa3c1411aa09441695a9e645d4371e8d749da1dc

Вы должны узнавать файлы в подкаталоге тегов. Каждый файл соответствует тегу, ранее созданному с помощью команды git tag. Его содержание – это всего лишь хэш коммита, привязанный к тегу.

Каталог heads практически аналогичен, но используется для веток, а не тегов. На данный момент у нас есть только одна ветка, так что все, что вы увидите в этом каталоге – это ветка master.

22.06 Файл HEAD

ВЫПОЛНИТЕ:

cat .git/HEAD

РЕЗУЛЬТАТ:

$ cat .git/HEAD
ref: refs/heads/master

Файл HEAD содержит ссылку на текущую ветку, в данный момент это должна быть ветка master.

23. Git внутри: Работа непосредственно с объектами git

Цели:

Давайте исследуем объекты git с помощью некоторых инструментов.

23.01 Поиск последнего коммита

Выполните:

git hist --max-count=1

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

РЕЗУЛЬТАТ:

$ git hist --max-count=1
* 8029c07 2011-03-09 | Added index.html. (HEAD, master) [Alexander Shvets]

23.02 Вывод последнего коммита

С помощью SHA1 хэша из коммита, указанного выше…

Выполните:

git cat-file -t <hash>
git cat-file -p <hash>

Вот что выходит у меня…

$ git cat-file -t 8029c07
commit
$ git cat-file -p 8029c07
tree 096b74c56bfc6b40e754fc0725b8c70b2038b91e
parent 567948ac55daa723807c0c16e34c76797efbcbed
author Alexander Shvets <alex@githowto.com> 1299684476 -0500
committer Alexander Shvets <alex@githowto.com> 1299684476 -0500

Added index.html.

Примечание: Если вы задали алиасы «type» и «dump», как описано в уроке об алиасах, можете вводить команды git type и git dump вместо длинных команд (которые я никогда не запоминаю).

Это вывод объекта коммита, который находится во главе ветки master.

23.03 Поиск дерева

Мы можем вывести дерево каталогов, ссылка на который идет в коммите. Это должно быть описание файлов (верхнего уровня) в нашем проекте (для конкретного коммита). Используйте SHA1 хэш из строки «дерева», из списка выше.

Выполните:

git cat-file -p <treehash>

Вот как выглядит мое дерево…

Результат:

$ git cat-file -p 096b74c
100644 blob 28e0e9d6ea7e25f35ec64a43f569b550e8386f90    index.html
040000 tree e46f374f5b36c6f02fb3e9e922b79044f754d795    lib

Да, я вижу index.html и каталог lib.

23.04 Вывод каталога lib

Выполните:

git cat-file -p <libhash>

Результат:

$ git cat-file -p e46f374
100644 blob c45f26b6fdc7db6ba779fc4c385d9d24fc12cf72    hello.html

Существует файл hello.html .

23.05 Вывод файла hello.html

Выполните:

git cat-file -p <hellohash>

Результат:

$ git cat-file -p c45f26b
<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
  </head>
  <body>
    <h1>Hello, World!</h1>
  </body>
</html>

А вот и он. Мы вывели объекты коммитов, объекты деревьев и объекты блобов непосредственно из репозитория git. Это все, что есть – блобы, деревья и коммиты.

23.06 Исследуйте самостоятельно

Исследуйте git репозиторий вручную самостоятельно. Смотрите, удастся ли вам найти оригинальный файл hello.html с самого первого коммита вручную по ссылкам SHA1 хэша в последнем коммите.

24. Создание ветки

Цели: Научиться создавать локальную ветку в репозитории

Пора сделать наш hello world более выразительным. Так как это может занять некоторое время, лучше переместить эти изменения в отдельную ветку, чтобы изолировать их от изменений в ветке master.

24.01 Создайте ветку

Давайте назовем нашу новую ветку «style».

Выполните:

git checkout -b style
git status

Примечание: git checkout -b имяветки является шорткатом для git branch имяветки за которым идет git checkout имяветки .

Обратите внимание, что команда git status сообщает о том, что вы находитесь в ветке style.

24.02 Добавьте файл стилей style.css

Выполните:

touch lib/style.css

ФАЙЛ: lib/style.css

h1 {
  color: red;
}

24.03 Измените основную страницу

Обновите файл hello.html, чтобы использовать стили style.css.

ФАЙЛ: lib/hello.html

<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
    <link type="text/css" rel="stylesheet" media="all" href="style.css" />
  </head>
  <body>
    <h1>Hello, World!</h1>
  </body>
</html>

Выполните:

git add lib/hello.html
git commit -m "Hello uses style.css"

24.04 Измените index.html

Обновите файл index.html, чтобы он тоже использовал style.css

ФАЙЛ: index.html

<html>
  <head>
    <link type="text/css" rel="stylesheet" media="all" href="lib/style.css" />
  </head>
  <body>
    <iframe src="lib/hello.html" width="200" height="200" />
  </body>
</html>

Выполните:

git add index.html
git commit -m "Updated index.html"

24.05 Далее

Теперь у нас есть новая ветка под названием style с 3 новыми коммитами. Далее мы узнаем, как осуществлять навигацию и переключаться между ветками.

25. Навигация по веткам

Цели: Научиться перемещаться между ветками репозитория

Теперь в вашем проекте есть две ветки:

Выполните:

git hist --all

Результат:

$ git hist --all
* 07a2a46 2011-03-09 | Updated index.html (HEAD, style) [Alexander Shvets]
* 649d26c 2011-03-09 | Hello uses style.css [Alexander Shvets]
* 1f3cbd2 2011-03-09 | Added css stylesheet [Alexander Shvets]
* 8029c07 2011-03-09 | Added index.html. (master) [Alexander Shvets]
* 567948a 2011-03-09 | Moved hello.html to lib [Alexander Shvets]
* 6a78635 2011-03-09 | Add an author/email comment [Alexander Shvets]
* fa3c141 2011-03-09 | Added HTML header (v1) [Alexander Shvets]
* 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Alexander Shvets]
* 43628f7 2011-03-09 | Added h1 tag [Alexander Shvets]
* 911e8c9 2011-03-09 | First Commit [Alexander Shvets]

25.01 Переключение на ветку Master

Просто используйте команду git checkout для переключения между ветками.

Выполните:

git checkout master
cat lib/hello.html

Результат:

$ git checkout master
Switched to branch 'master'
$ cat lib/hello.html
<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
<head>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>

Сейчас мы находимся на ветке Master. Это заметно по тому, что файл hello.html не использует стили style.css.

25.02 Вернемся к ветке «style».

Выполните:

git checkout style
cat lib/hello.html

Результат:

$ git checkout style
Switched to branch 'style'
$ cat lib/hello.html
<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
<head>
<link type="text/css" rel="stylesheet" media="all" href="style.css" />
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>

Содержимое lib/hello.html подтверждает, что мы вернулись в ветку style

26. Изменения в ветке master

Цели: Научиться работать с несколькими ветками с различными (и, возможно, конфликтующими) изменениями.

Пока вы меняли ветку «style», кто-то решил обновить ветку master. Они добавили README.

26.01 Создайте файл README в ветке master

Выполните:

git checkout master

Файл README:

This is the Hello World example from the git tutorial.

26.02 Сделайте коммит изменений README в ветку master

Выполните:

git add README
git commit -m "Added README"

27. Просмотр отличающихся веток

Цели: научиться просматривать отличающиеся ветки в репозитории.

27.01 Просмотрите текущие ветки

Теперь у нас в репозитории есть две отличающиеся ветки. Используйте следующую лог-команду для просмотра веток и их отличий.

Выполните:

git hist --all

Результат:

$ git hist --all
* 6c0f848 2011-03-09 | Added README (HEAD, master) [Alexander Shvets]
| * 07a2a46 2011-03-09 | Updated index.html (style) [Alexander Shvets]
| * 649d26c 2011-03-09 | Hello uses style.css [Alexander Shvets]
| * 1f3cbd2 2011-03-09 | Added css stylesheet [Alexander Shvets]
|/
* 8029c07 2011-03-09 | Added index.html. [Alexander Shvets]
* 567948a 2011-03-09 | Moved hello.html to lib [Alexander Shvets]
* 6a78635 2011-03-09 | Add an author/email comment [Alexander Shvets]
* fa3c141 2011-03-09 | Added HTML header (v1) [Alexander Shvets]
* 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Alexander Shvets]
* 43628f7 2011-03-09 | Added h1 tag [Alexander Shvets]
* 911e8c9 2011-03-09 | First Commit [Alexander Shvets]

Это наша первая возможность увидеть в действии --graph в git hist. Добавление опции --graph в git log вызывает построение дерева коммитов с помощью простых ASCII символов. Мы видим обе ветки (style и master), и то, что ветка master является текущей HEAD. Общим предшественником обеих веток является коммит «Added index.html».

Метка --all гарантированно означает, что мы видим все ветки. По умолчанию показывается только текущая ветка.

28. Слияние (merge)

Цели: Научиться сливать две отличающиеся ветки для переноса изменений обратно в одну ветку.

28.01 Слияние веток

Слияние переносит изменения из двух веток в одну. Давайте вернемся к ветке style и сольем master с style.

Выполните:

git checkout style
git merge master
git hist --all

Результат:

$ git checkout style
Switched to branch 'style'
$ git merge master
Merge made by recursive.
README |    1 +
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 README
$ git hist --all
*   5813a3f 2011-03-09 | Merge branch 'master' into style (HEAD, style) [Alexander Shvets]
|\  
| * 6c0f848 2011-03-09 | Added README (master) [Alexander Shvets]
* | 07a2a46 2011-03-09 | Updated index.html [Alexander Shvets]
* | 649d26c 2011-03-09 | Hello uses style.css [Alexander Shvets]
* | 1f3cbd2 2011-03-09 | Added css stylesheet [Alexander Shvets]
|/  
* 8029c07 2011-03-09 | Added index.html. [Alexander Shvets]
* 567948a 2011-03-09 | Moved hello.html to lib [Alexander Shvets]
* 6a78635 2011-03-09 | Add an author/email comment [Alexander Shvets]
* fa3c141 2011-03-09 | Added HTML header (v1) [Alexander Shvets]
* 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Alexander Shvets]
* 43628f7 2011-03-09 | Added h1 tag [Alexander Shvets]
* 911e8c9 2011-03-09 | First Commit [Alexander Shvets]

Путем периодического слияния ветки master с веткой style вы можете переносить из master любые изменения и поддерживать совместимость изменений style с изменениями в основной ветке.

Однако, это делает графики коммитов действительно уродливыми. Позже мы рассмотрим возможность перебазирования, как альтернативы слиянию.

28.02 Далее

Но что если изменения в ветке master конфликтуют с изменениями в style?

29. Создание конфликта

Цели: Создание конфликтующих изменений в ветке master.

29.01 Вернитесь в master и создайте конфликт

Вернитесь в ветку master и внесите следующие изменения:

git checkout master

ФАЙЛ: lib/hello.html

<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
    <!-- no style -->
  </head>
  <body>
    <h1>Hello, World! Life is great!</h1>
  </body>
</html>

Выполните:

git add lib/hello.html
git commit -m 'Life is great!'

IDEA! Внимание: используйте для этого коммита одинарные кавычки, дабы избежать проблем с символом !. В bash он считается служебным.

29.02 Просмотр веток

Выполните:

git hist --all

Результат:

$ git hist --all
* 454ec68 2011-03-09 | Life is great! (HEAD, master) [Alexander Shvets]
| * 5813a3f 2011-03-09 | Merge branch 'master' into style (style) [Alexander Shvets]
| |\  
| |/  
|/| 
* | 6c0f848 2011-03-09 | Added README [Alexander Shvets]
| * 07a2a46 2011-03-09 | Updated index.html [Alexander Shvets]
| * 649d26c 2011-03-09 | Hello uses style.css [Alexander Shvets]
| * 1f3cbd2 2011-03-09 | Added css stylesheet [Alexander Shvets]
|/  
* 8029c07 2011-03-09 | Added index.html. [Alexander Shvets]
* 567948a 2011-03-09 | Moved hello.html to lib [Alexander Shvets]
* 6a78635 2011-03-09 | Add an author/email comment [Alexander Shvets]
* fa3c141 2011-03-09 | Added HTML header (v1) [Alexander Shvets]
* 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Alexander Shvets]
* 43628f7 2011-03-09 | Added h1 tag [Alexander Shvets]
* 911e8c9 2011-03-09 | First Commit [Alexander Shvets]

После коммита «Added README» ветка master была объединена с веткой style, но в настоящее время в master есть дополнительный коммит, который не был слит с style.

29.03 Далее

Последнее изменение в master конфликтует с некоторыми изменениями в style. В следующем шаге мы решим этот конфликт.

30. Разрешение конфликтов

Цели: Научиться разрешать конфликты во время слияния

30.01 Слияние master с веткой style

Теперь вернемся к ветке style и попытаемся объединить ее с новой веткой master.

Выполните:

git checkout style
git merge master

Результат:

$ git checkout style
Switched to branch 'style'
$ git merge master
Auto-merging lib/hello.html
CONFLICT (content): Merge conflict in lib/hello.html
Automatic merge failed; fix conflicts and then commit the result.

Если вы откроете lib/hello.html, вы увидите:

ФАЙЛ: lib/hello.html

<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
<<<<<<< HEAD
    <link type="text/css" rel="stylesheet" media="all" href="style.css" />
=======
    <!-- no style -->
>>>>>>> master
  </head>
  <body>
    <h1>Hello,World! Life is great!</h1>
  </body>
</html>

Первый раздел - версия во главе текущей ветки (style). Второй раздел - версия ветки master.

30.02 Решение конфликта

Вам необходимо вручную разрешить конфликт. Внесите изменения в lib/hello.html для достижения следующего результата.

ФАЙЛ: lib/hello.html

<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
    <link type="text/css" rel="stylesheet" media="all" href="style.css" />
  </head>
  <body>
    <h1>Hello, World! Life is great!</h1>
  </body>
</html>

30.03 Сделайте коммит решения конфликта

Выполните:

git add lib/hello.html
git commit -m "Merged master fixed conflict."

Результат:

$ git add lib/hello.html
$ git commit -m "Merged master fixed conflict."
Recorded resolution for 'lib/hello.html'.
[style 645c4e6] Merged master fixed conflict.

30.04 Расширенные возможности слияния

Git не предоставляет никаких графических инструментов слияния, но будет с удовольствием работать с любыми сторонними инструментами слияния, которые вы хотите использовать ([[http://stackoverflow.com/questions/137102/whats-the-best-visual-merge-tool-for-git][обсуждение таких инструментов на StackOverflow?]).