Днес
- Ще се занимаваме с Git
- Ще погледнем под капака
- Ще го разберем
Защо отделяме два часа, за да говорим за Git?
- Защото очевидно е нещо, което е необходимо и се ползва ежедневно
- Дори да си мислим, че го знаем, все ще има нещо ново, което ще научим
- Git e интересен пример за елегантно и семпло техническо решение на сравнително сложен проблем
Version Control System (VCS)
Не просто система, следяща промени в код!
- Съхранение
- Сигурност - всичко е обратимо
- Лесна работа в екип
- Различни версии на кода
- Нещо, без което не можем
Познавате ли този човек?
Linus Torvalds
Бащата на Linux
Създател на Git
Малко история
Linux kernel
- 15,803,499 реда код към юли 2013
- ~23 години история
Какво е нужно?
- Епична бързина
- Много версии на кода - 'леки' branch-ове
- Много опции
- Дистрибутираност
Централизирана VCS
- Един централен сървър
- Всички теглят и публикуват кода на него
- Локално се пазят само най-необходимите неща
Децентрализирана VCS
- Всеки, който си 'клонира' хранилището, е пълноправен сървър
- Цялата история на хранилището се съхранява локално - всеки има свое собствено копие
- Почти винаги отново има един основен сървър
- Може изобщо да няма отдалечен сървър
- Почти всички операции се правят локално - не е необходима интернет връзка
- Когато решите - синхронизирате се с който и да е друг сървър
Защо точно git?
- Страшно гъвкав
- Страшно бърз
- Страшен на пръв поглед, може би и на втори
- Когато разберете как работи, ще ви озари ярка светлина и животът ви вече ще има смисъл
- Ще ви отнеме много време да откриете всичко, на което е способен
- Но не е нужно да знаете всичко, за да ви е полезен
В началото беше git init
Създава празно хранилище в текущата директория.
Виждате папката .git
- съхранява всичко, което е нужно за историята.
Клониране на хранилище
git clone https://github.com/fmi/ruby-lectures.git
- Компресия - сваля се бързо
- Криптиран трафик - https
- Поддържа и други протоколи като
file
, ssh
и git
Работната директория (working directory)
- Директорията на проекта - всичко без
.git
- Една версия на файловете
Хранилището
- Там се намират файловете, които са commit-нати
- Съхраняват се в
.git
Staging област
- Нарича се и индекс
- Междинна област между работната директория и хранилището
- Съхранява файловете, които ще отидат в следващия commit
- Просто един файл -
.git/index
Отдалечено хранилище
- Друго хранилище
- Най-често се намира на друг компютър
- Може да е просто друга
git
директория
- Локалното и отдалеченото хранилище се синхронизират чрез
git pull
и git push
- Може да има повече от едно такова
- А може и да няма нито едно
Четирите области
Четирите области
- Един файл може да е в повече от една област едновременно
- Възможно е този файл да е с различно съдържание във всяка една област
- Хранилищата съдържат много версии на един и същ файл
4 състояния на файл
Untracked
- няма версии на този файл в staging областта и локалното хранилище (нов файл)
Unmodified
- файлът е с еднакво съдържание в работната директория, staging и хранилището
Modified
- файлът е с различно съдържание в работната директория и staging
Staged
- файлът е с еднакво съдържание в работната директория и staging, но се различава в хранилището
- Ако не сме променили състоянието на файл в staging, то то е същото като в текущия commit в хранилището
4 състояния на файл
Staging областта
С примери
Списък с всички променени, изтрити и нови файлове.
Промени на файловете в работната директория, спрямо тези в staging областта.
Със --staged
(--cached
в по-стари версии) - промени на файлове в staging, спрямо последния commit в хранилището.
git add new_or_modified.rb
Добавя файла към staging.
Добавя всички променени файлове в директорията.
Изтрива файл от работната директория и го маркира като изтрит в staging.
Типове обекти
- Файл (
blob
) - конкретна негова версия (snapshot), компресиран
- Дърво (
tree
) - списък от хешове на файлове и дървета
Commit
- за него след малко
Tag
- етикет, съдържащ идентификатора на конкретен commit
- Съхраняват се в
.git/objects
- Всеки обект се идентифицира с
sha1
хеш от съдържанието си
Commit
Конкретна версия на дърво (snapshot)
Състои се от:
- Уникален идентификатор
- Автор и committer - може да са различни хора
- Съобщение
- Време на добавяне
- Хеш на предходния commit - може да е повече от един
- Хеш на дървото (конкретната версия на файловата структура), за което се отнася
- Други метаданни
Commit
Всичко е просто файл
5fae695
е част от хеша на commit-a
Commit
Списък с commit-и в историята
git log
git log --stat
git log --since=2.weeks
git log --since=5.days.15.minutes
git log --until=2013-11-30
git log --grep 'Proc.new'
git log --author 'Dimitar Dimitrov'
git log lectures/01-introduction-to-ruby.slim
Commit
Да разгледаме
git show 5fae69568cd5420e13a34c06f6f495ea9bcb9a4e
git show 5fae695
git show HEAD
git show HEAD^
git show HEAD^^^
git show HEAD~3
git diff HEAD~3..HEAD
HEAD
е указател към последния commit
HEAD^^^
- Броят стрелкички е поредният номер на commit-a (0 е най-скорошният)
HEAD~n
- същото като HEAD^
с n
на брой стрелкички
Commit
git commit
git commit -m "Fix a typo on slide 3"
Commit-вайте възможно най-малките, логически свързани промени, които не чупят нищо.
Commit съобщения
- Начин на комуникация с колегите
- Казват ви какво се е случило, докато ви е нямало
- Разкриват причини за бъгове
- Показват мотивацията за промяната
Commit съобщения
Най-важното нещо във всяка VCS
- Първи ред - tl;dr версия. Възможно най-кратко и описателно - до 70 символа
- Останалите редове - допълнително описание
- Как сте разрешили определен бъг
- Каква е мотивацията да направите дадена промяна
- Какво е точното съобщение за грешка, което оправяте с този commit и прочее
- Сегашно време - все едно commit-ите говорят за себе си
Commit съобщения
Лош пример
Update Gemfile.lock
Commit съобщения
Добър пример
Update skeptic and libv8
The skeptic update showed errors in edge cases with the "spaces around
operators" restriction.
The libv8 update was because of compile problems I had with the older
version on OS X Yosemite.
Branch-ове (разклонения)
- Файл, съдържащ хеш на commit, който се счита за последен в branch-a
- Този commit се нарича връх на branch-а (branch tip)
- Първи елемент на свързан списък от commit-и
Branch-ове
Особености
- Branch по подразбиране -
master
HEAD
всъщност е референция към текущия branch (файл, съдържащ името му)
- Локалните и отдалечените са различни -
master
vs origin/master
- Всъщност
origin/master
е локален branch, съответстващ на отдалечения. Ако го променим - отново трябва да push-нем
.git/refs/heads/
Branch-ове
Създаване на branch
git branch killer-feature
git checkout -b killer-feature
Превключване между вече създадени
git checkout killer-feature
git checkout master
Създаване на branch
Демонстрация
- Нов файл в
.git/refs/heads/
Обновяване
git pull
git pull origin
git pull origin master
- Изтегля промените и ги слива с текущия branch
Публикуване
git push
git push origin killer-feature
git push origin local-branch-name:killer-feature # Ако са с различни имена
origin
е име на отдалечено хранилище - това, от което сме клонирали
- На мястото на
origin
може да стои името на което и да е отдалечено хранилище