-
1. Начало
- 1.1 За Version Control системите
- 1.2 Кратка история на Git
- 1.3 Какво е Git
- 1.4 Конзолата на Git
- 1.5 Инсталиране на Git
- 1.6 Първоначална настройка на Git
- 1.7 Помощна информация в Git
- 1.8 Обобщение
-
2. Основи на Git
-
3. Клонове в Git
-
4. GitHub
-
5. Git инструменти
- 5.1 Избор на къмити
- 5.2 Интерактивно индексиране
- 5.3 Stashing и Cleaning
- 5.4 Подписване на вашата работа
- 5.5 Търсене
- 5.6 Манипулация на историята
- 5.7 Мистерията на командата Reset
- 5.8 Сливане за напреднали
- 5.9 Rerere
- 5.10 Дебъгване с Git
- 5.11 Подмодули
- 5.12 Пакети в Git (Bundling)
- 5.13 Заместване
- 5.14 Credential Storage система
- 5.15 Обобщение
-
6. Настройване на Git
- 6.1 Git конфигурации
- 6.2 Git атрибути
- 6.3 Git Hooks
- 6.4 Примерна Git-Enforced политика
- 6.5 Обобщение
-
7. Git и други системи
- 7.1 Git като клиент
- 7.2 Миграция към Git
- 7.3 Обобщение
-
8. Git на ниско ниво
- 8.1 Plumbing и Porcelain команди
- 8.2 Git обекти
- 8.3 Git референции
- 8.4 Packfiles
- 8.5 Refspec спецификации
- 8.6 Транспортни протоколи
- 8.7 Поддръжка и възстановяване на данни
- 8.8 Environment променливи
- 8.9 Обобщение
-
9. Приложение A: Git в други среди
-
10. Приложение B: Вграждане на Git в приложения
- 10.1 Git от команден ред
- 10.2 Libgit2
- 10.3 JGit
- 10.4 go-git
- 10.5 Dulwich
-
A1. Приложение C: Git команди
- A1.1 Настройки и конфигурация
- A1.2 Издърпване и създаване на проекти
- A1.3 Snapshotting
- A1.4 Клонове и сливане
- A1.5 Споделяне и обновяване на проекти
- A1.6 Инспекция и сравнение
- A1.7 Дебъгване
- A1.8 Patching
- A1.9 Email команди
- A1.10 Външни системи
- A1.11 Административни команди
- A1.12 Plumbing команди
3.1 Клонове в Git - Накратко за разклоненията
Почти всички VCS системи разполагат с поддръжка на разклонения на версиите на кода под някаква форма. Разклоняването на кода означава, че вие се отделяте от основната линия на разработка (във ваш собствен клон, branch) и продължавате да работите без да се намесвате в тази основна линия. В множеството VCS системи това е процес, който изисква много ресурси и често сте принудени да копирате цялата си директория със сорс код, което може да е бавно при големи проекти.
Някои хора определят branching модела на Git като неговата “най-силна черта” и в действителност това е едно от нещата, които помагат на Git да изпъква сред другите VCS системи. Кое е толкова специално? Начинът, по който Git имплементира клоновете код е изключително олекотен, което прави branching операциите почти мигновени - това важи със същата сила и за превключването напред и назад по различните клонове код без оглед на мащаба на проекта. За разлика от другите VCS системи, Git окуражава работните процеси съдържащи чести разклонявания и сливания - дори по няколко пъти на ден. Ако успеете да овладеете тази страна на Git, ще разполагате с един мощен и уникален инструмент, който значително ще подобри и улесни методите ви на разработка.
Накратко за разклоненията
(Под клон, разклонение и branch ще имаме предвид едно и също нещо.) За да разберем как в действителност Git реализира разклоненията, трябва да се върнем стъпка назад и да си припомним как Git съхранява своите данни.
Както може би помните от Какво е Git, Git не съхранява информацията си като серии от промени или разлики, а вместо това пази серии от моментното състояние на проекта - snapshots.
Когато правите къмит, Git съхранява един commit обект, който съдържа указател към snapshot-а на индексираното съдържание (това, което е в индексната област). Този обект също така съдържа името и имейла на автора, къмит съобщението и също така - указатели към къмита или къмитите, които са правени директно преди текущия къмит (тоест, неговите родител/родители): първоначалният къмит няма родители, нормалният къмит има един родител, а къмитът създаден в резултат от сливане на няколко клона има множество родители.
За да илюстрираме това, нека допуснем, че имате директория с три файла и сте ги индексирали и къмитнали. Процесът по индексирането на файловете (staging) изчислява чексума за всеки от файловете (това е SHA-1 хеш стрингът за който говорихме по-рано в Какво е Git), записва версията на всеки файл в хранилището (Git третира файловете като blob-обекти) и добавя чексумите в индексната област (staging area):
$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'
След като изпълните git commit
, Git изчислява чексума за всяка поддиректория (в този случай само основната директория на проекта) и ги съхранява като дървовиден обект в Git хранилището.
След това Git създава commit-обект, който съдържа метаданните и указател към root-дървото на проекта, така че да може да пресъздаде snapshot-а (тоест йерархията от файлове и директории) по-късно, когато е необходимо.
Вашето Git хранилище сега съдържа 5 обекта: по един blob за всеки от трите файла, едно дърво описващо съдържанието на директорията и указващо кой файл под формата на кой blob се съхранява, и един къмит с указател към това основно дърво и всички метаданни за къмита.
![Един къмит и неговото дърво](png/commit-and-tree.png)
Ако направите някакви промени и къмитнете отново, следващият къмит ще съхранява указател към къмита направен веднага преди него.
![Къмити и родителски къмити](png/commits-and-parents.png)
Разклонението код (branch) в Git е просто олекотен, променлив указател към един от тези къмити.
Името на разклонението по подразбиране за Git е master
.
Когато започнете да правите къмити, вие разполагате с master
branch, който сочи към последния къмит, който сте направили.
Всеки път, когато къмитвате, той автоматично се премества и сочи към последния къмит.
Забележка
|
“master” клонът в Git не бива да се разглежда като специален такъв.
Той е подобен на всички останали клонове.
Единствената причина почти всяко хранилище да има master клон е, че командата |
![branch и неговата commit история](png/branch-and-history.png)
Създаване на ново разклонение
Какво се случва, когато създадете нов клон?
Git просто създава нов указател за вас, който да може да се премества.
Да кажем, че създавате клон с име testing
.
Това се прави с командата git branch
:
$ git branch testing
Това създава нов указател към същия къмит, на който сте в момента.
![Два клона сочещи към една и съща серия къмити](png/two-branches.png)
Как Git знае в кой клон сте в даден момент?
Системата си пази специален указател, който се нарича HEAD
.
Отбележете, че това е съвсем различно от HEAD
концепциите в други VCS от рода на Subversion или CVS.
В Git, това е указател към текущия локален клон от хранилището ви.
В този случай, вие още сте в master
клона.
Това е така, защото git branch
командата само създаде новия клон, но не превключи към него.
![HEAD указател сочещ към текущия branch](png/head-to-master.png)
Можете лесно да видите това изпълнявайки командата git log --decorate
, която отпечатва накъде сочат указателите на разклоненията.
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface
34ac2 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit
Виждате master
и testing
клоновете веднага до f30ab
-къмита.
Превключване на разклонения
За да превключите към съществуващ клон, изпълнете командата git checkout
.
Нека превключим към testing
клона:
$ git checkout testing
Това премества HEAD
указателя и сега той сочи към testing
клона.
![HEAD сочи към текущия клон](png/head-to-testing.png)
Какво означава това? Нека направим още един къмит:
$ vim test.rb
$ git commit -a -m 'made a change'
![HEAD клонът се премества напред при направен къмит](png/advance-testing.png)
Това е интересно, защото сега вашият testing
клон се премести напред, но master
клонът все още сочи към къмита, в който бяхте когато изпълнихте git checkout
за да превключите разклоненията.
Нека се върнем отново на master
клона:
$ git checkout master
Забележка
|
git log не показва всички клонове постоянно
Ако изпълните Клонът не е изчезнал, Git просто не знае, че се интересувате от него и се опитва да ви покаже това, което той мисли, че търсите.
С други думи, по подразбиране, Ако желаете историята на конкретен клон, ще трябва да го укажете изрично |
![HEAD се премества когато превключвате](png/checkout-master.png)
Тази команда направи две неща.
Тя премести HEAD указателя обратно към точката на master
клона - и също така върна обратно статуса на всички файлове в работната ви директория така че те сега съдържат това, което са съдържали в момента на последния къмит в master
клона.
Това също означава, че промените които предстои да правите занапред от тази точка на проекта, ще произлизат от по-стара негова версия.
Практически - връщането в master
клона заличи всички промени от testing
клона в работната директория и сега можете да тръгнете в различна посока.
Забележка
|
Превключването между клоновете променя файловете в работната директория
Важно е да се посочи, че когато превключвате клонове в Git, файловете в работната директория ще се променят. Ако превключите към по-ранен клон, вашата работна директория ще се превърти назад във времето и ще съдържа това, което е имала последния път когато сте направили къмит в този клон. Ако Git не може да направи това безпроблемно - то превключването няма да бъде позволено въобще. |
Нека направим няколко промени и да къмитнем отново:
$ vim test.rb
$ git commit -a -m 'made other changes'
Сега историята на проекта се отклони (виж Разклонена история).
Вие създадохте и превключихте към нов клон, направихте промени по кода в него, превключихте към основния клон и направихте други промени.
И двата вида промени са изолирани в отделни разклонения: можете да превключвате между тези разклонения и да ги слеете в едно, когато сте готови.
Направихте всичко това с прости команди като branch
, checkout
, и commit
.
![Разклонена история](png/advance-master.png)
Можете лесно да видите това и с командата git log
.
Ако изпълните git log --oneline --decorate --graph --all
, това ще отпечата историята на вашите къмити, показвайки къде са вашите branch указатели и как се е разклонила историята на проекта.
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Made other changes
| * 87ab2 (testing) Made a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project
Понеже клонът в Git на практика е обикновен файл съдържащ 40-символна SHA-1 чексума на къмита, към който клонът сочи, създаването и изтриването на разклонения в Git почти не изисква ресурси. Създаването на нов клон е толкова бързо и просто колкото е записа на 41 байта във файл (40-те символа от чексумата и символ за нов ред).
Това рязко контрастира с начина, по който повечето стари VCS системи управляват разклоненията, защото те копират всички файлове на проекта ви в отделна директория. При тях това може да отнеме много секунди и дори минути, според размера на проекта, докато при Git се прави почти мигновено. Също така, понеже записваме родителите когато къмитваме, намирането на правилната базова точка за сливане се осъществява автоматично за нас и е много лесно. Тези функции окуражават разработчиците да създават и използват разклонения колкото може по-често.
Нека видим защо е добре да го правим.
Забележка
|
Създаване на нов клон и превключване към него автоматично
Често се случва да искате да превключите веднага към новосъздаден клон — това може да стане на една стъпка с командата |
Забележка
|
From Git version 2.23 onwards you can use
|