Днес
- Ще опознаем Git с помощта на Георги
- Ще погледнем под капака
- Ще го издигнем в култ
- В края на презентацията ще дадем информация за проектите към курса
- Ще ви дадем и трета задача
Бъдещето на образованието
лирическо отклонение
Flipped Classrooms
Образование
- Аз искам да съм част от такъв модел
- За съжаление, все още сме далеч от възможността да го приложим
- Вярвам, обаче, че можем да работим в тази посока
Образование
Образование
и вашата роля
- Днес, например, Георги ще ни поговори малко за VSC и защо Git е скалпелът на програмиста
- Искам да има повече такива включвания от ваша страна - пишете на fmi@ruby.bg
Защо отделяме два часа, за да говорим за Git?
- Защото очевидно е нещо, което е необходимо и се ползва ежедневно
- Дори да си мислим, че го знаем, все ще има нещо ново, което ще научим
- Git e интересен пример за елегантно и семпло техническо решение на сравнително сложен проблем
Version Control System (VCS)
Не просто система, следяща промени в код!
- Съхранение
- Сигурност - всичко е обратимо
- Лесна работа в екип
- Различни версии на кода
- Нещо, без което не можем
Познавате ли този човек?
Linus Torvalds
Бащата на Linux
Създател на Git
Малко история
Linux kernel
- 15,803,499 реда код към юли 2013
- ~22 години история
Какво е нужно
- Епична бързина
- 'Леки' branch-ове - много версии на кода
- Много опции
- Дистрибутираност
Централизирана VCS
- Един централен сървър
- Всички теглят и публикуват кода на него
Децентрализирана VCS
- Всеки, който си 'клонира' хранилището, е пълноправен сървър.
- Цялата история на хранилището се съхранява локално - всеки има свое собствено копие.
- Почти винаги отново има един основен сървър.
- Повечето от операциите се правят локално - не ви е необходим интернет.
- Когато решите - синхронизирате се с който и да е друг сървър.
Защо точно git?
- Страшно гъвкав
- Страшно бърз
- Страшен на пръв поглед, може би и на втори
- Щом го разберете - ще се превърнете в хакери
- Ще ви отнеме много време да откриете всичко, на което е способен
- Но не е нужно да знаете всичко, за да ви е полезен
В началото беше git init
Създава празно хранилище в текущата директория.
Виждате папката .git - съхранява всичко, което му е нужно.
Клониране на хранилище
git clone https://github.com/fmi/ruby-lectures.git
- Компресия - сваля се бързо
- Криптиран трафик - https
- Ако за някоя операция са ви нужни права - ще ви попита
Работната директория
- Директорията на проекта - всичко без
.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 областта.
С --cached
- промени на файлове в staging, спрямо последния commit в хранилището.
git add new_or_modified.rb
Добавя файла към staging
Добавя всички променени файлове в директорията
Изтрива файл от работната директория и го маркира като изтрит в staging.
Типове обекти
- Файл (
blob
) - конкретна негова версия, компресиран
- Дърво (
tree
) - списък от хешове на файлове и дървета
Commit
- за него след малко
Tag
- хеш на конкретен commit
- Съхраняват се в
.git/objects
- Всеки обект се идентифицира с
sha1
хеш
Commits 1
Конкретна версия на дърво (snapshot)
Състои се от:
- Уникален идентификатор
- Автор и committer - може да са различни хора
- Съобщение
- Време на добавяне
- Хеш на предходния commit
- Хеш на дървото, за което се отнася
- Други метаданни...
Commits 2
Всичко е просто файл
5fae695
е част от хеша на commit-a
Commits 3
Списък с 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
Commits 4
Да разгледаме
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
на брой стрелкички
Commits 5
git commit
git commit -m "Fix a typo on slide 3"
Commit-вайте възможно най-малките, логически свързани промени, които не чупят нищо.
Добри практики за съобщението:
- Първи ред - обобщение
- Кратко и описателно (за първия ред)
- Останалите редове - допълнително описание. Например как сте разрешили определен бъг, каква е мотивацията да направите дадена промяна, какво е точното съобщение за грешка, което оправяте с този commit и прочее
- Сегашно време
- До 70 символа на ред
Branches 1
- Файл, съдържащ хеш на commit, който се счита за последен в branch-a
- Този commit се нарича връх на branch-а (branch tip)
- Първи елемент на свързан списък от commit-и
Особености
- Branch по подразбиране -
master
HEAD
- указател към текущия branch (файл, съдържащ името му)
- Локалните и отдалечените са различни -
master
vs origin/master
.git/refs/heads/
Branches 1
Branches 2
Създаване
git branch killer-feature
git checkout -b killer-feature
Превключване между вече създадени
git checkout killer-feature
git checkout master
Branches 2
Демонстрация
git branch
- Нов файл в
.git/refs/heads/
Branches 2
Branches 3
Обновяване
Публикуване
git push
git push origin killer-feature
origin
е име на отдалечено хранилище - това, от което сме клонирали.
- На мястото на
origin
може да стои името на което и да е отдалечено хранилище.
Сливане
git merge killer-feature
git merge --squash killer-feature
- Слива промени от (най-често) 2 клона
- Често създава нов commit
Различни стратегии на сливане. Основните са 2:
Fast-Forward стратегия
Просто премества указателя за клона
Fast-Forward стратегия
Просто премества указателя за клона
Recursive стратегия
Слива 2 разделили се клона с обща история.
Recursive стратегия
Жълтото e merge commit-a. Той съдържа промените и от двата клона.
Branch 4
Изтриване
git branch -d killer-feature
git push origin --delete killer-feature # Ако сте го push-нали
- Премахва само файла на branch-a, commit-ите се пазят
- Дори ако е останал commit, който е извън историята, пак може да се възстанови
- За възстановяване - след малко
Branch 4
Типичен процес на работа
Типичен процес на работа
Заради "евтините" branch-ове на git можем да направим следното:
- Имаме два основни branch-a -
master
и develop
(internal
, unstable
или както го кръстите)
- Когато започваме нова функционалност, правим branch специално за тази промяна.
- Когато приключим, я качваме в
develop
с git merge
- В
develop
нещата се тестват и след определено време се сливат с master
Типичен процес на работа
Резултат
- В
master
имаме само стабилни промени
- В
develop
имаме новите функции, които не са достатъчно тествани
- Ако две нови функции си пречат, това може да се поправи, преди да влязат в стабилната версия
- Ако трябва бързо да поправим нещо в стабилната версия на кода, можем директно да направим commit в
master
Машината на времето
Или как да върнем "безвъзвратно" загубените промени.
git reset
git checkout
git commit --amend
git revert
git reflog
Машината на времето
git reset <commit> <files>
git reset HEAD lectures/git.slim
- Променя файлове в staging областта, като ги взима от хранилището
- В случая
HEAD
указва от кой точно commit да се вземат файловете. Там може да има и хеш на commit
- Не променя файловете в работната директория
- Използва се, когато не искате да commit-вате файл, но да запазите локалните промени
- С
—hard
променя и работната директория
Машината на времето
- Променя файлове в работната директория, като ги взима от staging областта
- Внимание! Може да изгубите код!
Машината на времето
git commit --amend
git push --force # Ако вече сте push-нали
- Променя последния commit. А дали наистина?
- Всъщност създава нов commit със същия предшественик
- Старият commit все още може да бъде възстановен
- Удобно е за поправяне на грешки в съобщението или добавяне на изпуснати файлове
- Не е хубаво да се прави, ако вече сте push-нали, защото някой друг може да е направил pull и ще има конфликт
Машината на времето
- Премахва промените, направени от
commit
- Всъщност създава нов commit, който прави същото като
commit
, но наобратно.
- Разбирайте където има
+
в diff-a става на -
и обратно.
- Ако все пак решите, че искате тези промени можете да revert-нете revert commit-a. Yo Dawg!
Машината на времето
- Показва ви последните операции, които сте правили, заедно с ID-та на разни обекти
- Можете да намерите ID-тата на изгубени commit-и и да ги възстановите
- Понякога се чисти
Игнориране на файлове
Файлът .gitignore
- Често има файлове, които не искаме git да следи
- Например компилирани двоични файлове, временни файлове, конфигурационен файл с API ключове и т.н.
- Всеки ред в
.gitignore
е шаблон за файлове/директории, които трябва да бъдат игнорирани
- Това означава, че няма да се виждат в
git status
Игнориране на файлове
Формат на .gitignore
\/bin # Файла/директорията bin в главната директория на проекта
bin # Всички файлове и директории с име bin
bin/ # Всички директории с име bin
compiled/*.html # Всички файлове с разширение html в compiled-lectures
lib/**/*.txt # Всички текстови файлове в lib или нейна поддиректория
*.exe # Всички изпълними файлове за Windows
Git rebase
Най-мощният инструмент за пренаписване на историята
git checkout killer-feature
git rebase master
git rebase -i master
git rebase -i HEAD~4
- Пресъздава промените от текущия branch, все едно са направени върху сегашното състояние на
master
- С -i ви позволява да си премахнете, промените или слеете (squash) commit-и от историята
- Трябва да направите
git push —force
, ако вече сте push-нали branch-a, който променяте
- Отново - избягвайте да го правите, ако промените вече са публикувани
Git blame
Или "Кой написа това?"
git blame lectures/index.yml
Изводи
- Няма да минете без него...
- ...затова започвайте да го използвате...
- ...с терминала - научават се много неща.
- Може да ви се струва труден - не е
Искайте помощ:
git command —help
man git
man git-command
Графичен интерфейс
GitX
Графичен интерфейс
TortoiseGit
Графичен интерфейс
GitHub
Материали
- Добър туториал за начинаещи с терминалния интерфейс - Try git
- Безплатна книга с много подробни обяснения - Pro Git
Въпроси по Git?
Сега е добър момент да ги зададете.
Проекти
- Носят до 60 точки, срокът за писането им е до датата на защита (в сесията)
- Вие си избирате тема и ни пишете на fmi@ruby.bg, ние я одобряваме
- Крайният срок да си изберете тема и да ви я одобрим, е 24.12.2013, 23:59:59 (ще има новина с инструкции)
- Запознайте се с ръководството и някои ЧЗВ около проектите
- Размер и сложност - 10 задачи или 60 предизвикателства :)
- Най-важното е да си изберете тема, която ви харесва