Գիթ

**Գիթ** (), վարկածների կառավարման ապակենտրոն համակարգ, որը հետևում է կատարված փոփոխություններին համակարգչում ընտրված  ֆայլերի մեջ։ Հիմնականում կիրառվում է ծրագրի կոդի ստեղծման ժամանակ, միմյանցից անկախ աշխատող ծրագրավորողների աշխատանքը համակարգելու համար։ Այն ապահովում է կոդի կառավարման արագություն, տվյալների ամբողջականություն, ապակենտրոն՝ ոչ-գծային ձևով կոդի ստեղծում (տարբեր համակարգիչներում կարող են լինել փոփոխությունների հազարավոր ճյուղեր, որոնք չկան մյուսների մոտ)։

Գիթը հեղինակել է Լինուս Տորվալդսը 2005 թվականին, դրա  ստեղծման նպատակն էր, կառավարել աշխարհի տարբեր մասերում գտնվող ծրագրավորողների հետ համատեղ Լինուքս միջուկի կոդը գրելու գործընթացը։ Սկսած 2005 թվականից գիթի հիմնական մշակումն արել է Ջունիո Համանոն։ Ինչպես մնացած վարկածների կառավարման ապակենտրոն համակարգերը, այնպես էլ գիթի պահոցի յուրաքանչյուր պատճեն իր մեջ ունի ֆայլերի փոփոխությունների ամբողջական պատմությունը, և ի տարբերություն կլիենտ-սերվեր համակարգերի, գիթը կախված չէ ցանցի հասանելիությունից և ինչ-որ կենտրոնական սերվերից։
Գիթը ազատ ծրագրային ապահովում է և ունի բաց ելակոդ։ Ծրագիրը տարածվում է միայն GPL-2.0 արտոնագրով։

Ստեղծումից հետո գիթը դարձել է ամենաշատ օգտագործվող վարկածների կառավարման համակարգը․ 2022-ին ծրագրավորողների հետ արված հարցումների համաձայն այն ունի մոտ 95% տարածվածություն։ Գիթի բազմաթիվ հոսթինգ ծառայություններից ամենահայտնիներն են GitHub, SourceForge, Bitbucket և Gitlab։

## Պատմություն
Գիթի մշակումը սկսել է Տորվալդսը 2005 թվականի ապրիլին, երբ Լինուքսի միջուկի համար օգտագործվող սեփականատիրական վերահսկման կառավարման համակարգը՝ BitKeeper-ը, որը օգտագործում էին սկսած 2002 թվականից, չեղյալ համարեց իր ազատ արտոնագիրը Լինուքս միջուկի մշակման համար։

Տորվալդսը ցանկանում էր այնպիսի համակարգ, որը նա կարող էր օգտագործել ինչպես Bitkeeper-ը, բայց եղած ոչ մի համակարգ չէր բավարարում պահանջներին։
Նա ցույց տվեց վարկածների կառավարման համակարգի օրինակ, որին պետք է 30 վայրկյան փոփոխությունները կիրառելու և հարակից մետա տվյալները ավելացնելու համար և պնդեց, որ նման համակարգը չի կարող օգտագործվել Լինուքս միջուկի նման մեծ կոդի հետագա մշակման համար, երբ յուրաքանչյուր նոր մասնագետի միանալը նախագծին առաջին անգամ կարող է պահանջել 250 նման գործողություն միանգամից։
Նրա չափանիշների համաձայն փոփոխությունների կիրառումը չի կարող տևել 3 վայրկյանից ավելի երկար։ Նա նշեց ևս երեք հիմնական սկզբունք.

* Վերցնել Concurrent Versions System (CVS) համակարգը որպես օրինակ, թե ինչ պետք է չանել, եթե ինչ-որ հարցում լինեն կասկածներ ապա նայել ինչ է արված CVS-ում և անել դրա հակառակը։
* Օգտագործել bitkeeper-ի նման ապակենտրոն կառուցվածքը։
* Կիրառել խիստ հսկողություն տվյալների վնասվելու դեմ, անկախ նրանից կլինի այն պատահական թե միտումնավոր։

Նշված չափանիշները բացառում էին այն ժամանակ եղած համակարգերից որևէ մեկի օգտագործումը։ Լինուքս միջուկի 2.6.12-rc2 վարկածի թողարկումից անմիջապես հետո Տորվալդսը սկսեց իր սեփական վարկածների կառավարման համակարգի մշակումը։ Ապրիլի 18-ին նա հրապարակեց գիթի կոդի սկզբնական տարբերակը։ Ապրիլի 29-ին նա ստացավ իր սահմանած արագագործությունը՝ համակարգը կարողանում էր մեկ վայրկյանում կիրառել 6.7 փոփոխություն։ Հունիսի 18-ին թողարկվեց Լինուքս միջուկի 2.6.12 վարկածը, դրա փոփոխությունները ղեկավարվել էր գիթի միջոցով։

2005 թվականի հուլիսի 26-ին Տորվալդսը նախագծի ղեկավարումը փոխանցել է Ջունիո Համանոյին։ Համանոն կատարել է ծրագրի կոդի հետագա փոփոխությունների հիմնական մասը և դեկտեմբերի 21-ին թողարկել է գիթի 1.0 վարկածը։

## Անվանումը
Git բառը բրիտանական անգլերեն ժարգոնում նշանակում է «տհաճ մարդ»։ Տորվալդսը այս մասին հեգնանքով ասում է, որ նա իր բոլոր նախագծերին իր անունն է տալիս․ սկզբում Linux, իսկ հիմա git։ Գիթի Man էջը նկարագրում է այն որպես «հիմար բովանդակության հետևող»։

Ծրագրի ելակոդում այն նկարագրված է որպես տեղեկատվական կառավարիչ դժոխքից»։

## Բնութագրեր
Գիթը նախագծելուց Տորվալդսը միավորել է իր փորձը, որը նա ստացել էր Լինուքսի կոդի մշակման ժամանակ, երբ օգտագործում էր կոդի ապակենտրոն փոփոխությունների ղեկավարման գործիքներ, և իր գիտելիքները, որ նա ուներ ֆայլային համակարգի արագագործության մասին։ Նաև նոր համակարգը պետք է պատրաստ լիներ հնարավոր կարճ ժամանակում։ Նշված ազդեցությունները առաջացրեցին նախագծի հետևյալ բնութագրերը՝

; Ապահովել կոդի ոչ գծային մշակումը
: Գիթում ճյուղավորումներ ստեղծելը կամ ճյուղերը միացնելը շատ արագ է լինում։ Ծրագիրը ունի հատուկ գործիքներ ոչ գծային փոփոխությունների ճյուղերը պատկերելու համար։ Գիթը նախագծված է այնպես, որ փոփոխությունները հնարավոր լինի հաճախ միավորել և փոխանցել նախագծի այլ մասնակիցների, կոդը վերստուգելու համար։ Ճյուղը (branch) ցուցիչ է դեպի փոփոխությունների փաթեթը (commit)։
; Կոդի ապակենտրոն մշակում
: Darcs, BitKeeper, Mercurial, Bazaar և Monotone համակարգերի նման գիթը նույնպես յուրաքանչյուր լոկալ պատճենի  մեջ պահում է փոփոխությունների ամբողջ պատմությունը։ Արտաքին պահոցներից ներբեռնված ճյուղերը հնարավորր է ձուլել այլ ճյուղերի հետ նույն պարզ քայլերով, ինչպես այն կարվեր եթե ճյուղերը ստեղծված լինեին լոկալ համակարգում։
; Համատեղելիությունը արդեն առկա համակարգերի հետ
: Գիթը աշխատում է հիմնական հայտնի պրատակոլների հետ. HTTPS, SSH, FTP։ Նաև ունի համատաղելիություն SVC-ի հետ, որը հնարավորություն է տալիս գոյություն ունեցող պահոցները և IDE հավելվածները օգտագործել գիթի հետ, subversion համակարգի պահոցները հնարավոր է օգտագործել git-svn հավելվածի միջոցով։
; Մեծ պահոցների արդյունավետ կառավարում
: Mozilla-ի կատարած թեստերի արդյունքները ցույց են տվել, որ գիթը անհամեմատ ավելի արագ է քան Mercurial և GNU Bazaar համակարգերը փոփոխությունները ներբեռնելու ժամանակ, եթե փոփոխությունները գտնվում են լոկալ համակարգում ապա արագությունը հարյուրվոր անգամ ավելի մեծ է։
; Պատմության նույնականացում կրիպտոգրաֆիկ գործիքներով
: Գիթ պատմությունը պահվում է այնպես, որ որոշակի տարբերակի ID-ն (commit Git-ի տերմիններով) կախված է զարգացման ամբողջական պատմությունից, որը տանում է դեպի այդ commit-ը։ Հրապարակվելուց հետո հնարավոր չէ աննկատ կատարել փոփոխություն հին commit-ների մեջ։
; Մոդուլային կառուցվածք
: Գիթը կազմված է փոքր ֆունկցինալություն ունեցող բազմաթիվ ծրագրերից։ Այդ ծրագրերը հիմնականում գրված են C լեզվով, որի արդյունքում ունեն բարձր արագություն։
; Ճյուղերի ձուլման ղեկավարում
: Որպես առանձին մոդուլ գիթում կա ճյուղերը ձուլելու համակարգ։ Ավտոմատ ձուլման համար մոդուլում կան մի շարք ալգորիթմներ։ Եթե ճյուղերի ձուլումը հնարավոր չէ, ապա գիթը տեղեկացնում է այդ մասին օգտվողին և նշում է կոդի այն հատվածները որոնք հնարավոր չի եղել միավորել։
; Աղբը կուտակվում է մինչև մաքրելը
: Ընդհատված գործողությունների արդյունքում առաջացած օբյեկտները կամ չօգտագործվող օբյեկտները որոշ ժամանակ մնում են գիթում և հասանելի են այդ ընթացքում։ Գիթը ավտոմատ կմաքրի աղբը, երբ բավականաչափ աղբ կկուտակվի հիշողությունում։ Օգտվողը նույնպես կարող է իրականացնել մաքրելու գործողությունը կանչելով `git gc` հրամանը։
; Օբյեկտների փաթեթների արխիվացում
: Git-ը պահում է յուրաքանչյուր օբյեկտ որպես առանձին ֆայլ։ Թեև դրանք յուրաքանչյուրը սեղմված են, բայց օբյեկտնրը առանձին-առանձին պահելը մեծ տարածք է զբաղեցնում և անարդյունավետ է։ Խնդիրը լուծվում է փաթեթների արխիվացմամբ։ Արխիվացվում են միմյանց հետ որոշ ձևով կապված կամ նման օբյեկտները մեկ արխիվի մեջ․ այդ արխիվները կոչվում են packfile: Գիթը ավտոմատ կատարում է այս գործողությունը որոշ պարբերությամբ, բայց այն նույնպես հնարավոր է կանչել `git gc` հրամանով։

Git-ը ուղիղ ձևով չի պահում ամեն մի ֆայլի փոփոխությունը, այլ պահում է  ֆայլերի ծառի (tree) ընթացիկ վիճակը։ Այս մեթոդի պատճառով գիթում առանձին ֆայլի պատմությունը դուրս բերելը մի փոքր ավելի երկար է տևում, բայց արագագործությունը աճում է ֆայլերի խմբի հետ աշխատելու դեպքում։

Git -ում ձուլումը իրականացվում է [three-way merge](https://en.wikipedia.org/wiki/Merge_(version_control)#Three-way_merge) ալգորիթմով։

## Տվյալների կառուցվածք
Git-ի էլեմենտները վերցված չեն ծրագրային կոդի կառավարման համակարգերից։ Տորվալդսը սա բացատրել է.
; : Շատ դեպքերում գիթին կարող եք դիտարկել, որպես ֆայլային համակարգ։ Այն հետևում է ֆայլերի բովանդակությանը և ավելացնում է փոփոխությունների վարկածները։ Ես գիթը նախագծել եմ հաշվի առնելով ֆայլային համակարգերը։ Ես օպերացիոն համակարգի միջուկ եմ ստեղծում և ես ոչ մի հետաքրքրություն չունեի կոդի կառավարման համակարգերի հետ։

Սկզբում գիթը չի ունեցել բոլոր ֆունկցիաները, որ ունեն կոդի կառավարման դասական համակարգերը։ Այդ ֆունկցիաները ավելացրել են երբ դրանց կարիքն է եղել։ Ժամանակի ընթացքում դրանք զտվել են կամ ընդլայնվել, կախված դրա անհրաժեշտությունից։

Գիթը ունի տվյալները պահելու երկու հիմնական հատված․ ոչ մշտական ցուցակ, որը ներառում է ընթարիկ ֆայլերի փոփոխությունները, որոնք հաջորդ կրահրանվել որպես հաջորդ վարկած (commit), այս հատվածը նաև կոչվում է stage կամ cache։ Երկրորդ տեսակի պահոցը օբյեկտների տվյալների բազան է, որը մշտական է։

Ոչ մշտական ցուցակը միացման կետ է ընթացիկ դիրեկտորիի և օբյեկտների տվյալների բազայի միջև։

Օբյեկտների տվյալների բազայում պահվում են հետևյալ օբյեկտները.
* **Blob** (երկուական տվյալներ) սրա մեջ պահվում է ֆայլի բովանդակությունը։ Այս օբյեկտում չկա ֆայլի անուն, ժամային նշումներ (timestamp) կամ այլ մետա տվյալներ։ Blob -ի անունը ֆայլի բովանդակության հեշն է։
* **Tree** (ծառ) այս օբյեկտը համարժեք է ֆայլային համակարգի դիրեկտորիներին։ Այստեղ պահվում է ֆայլերի անունները, ցուցիչ դեպի blob -ը (որի մեջ ֆայլերի բովանդակությունն է) կամ ցուցիչ դեպի այլ ծառի որի մեջ ֆայլերն են։ Օբյեկտը կարող է լինել սիմվոլային հղում կամ դիրեկտորիի բովանդակություն։ Այս օբյեկտները ելակետային ֆայլերի ու ենթադիրեկտորիների պատկերումն է (snapshot)։ Այս տիպի ծառերի հեշը կազմվում է ծառի ամբողջ բովանդակությունից․ անկախ ֆայլերի և դիրեկտորիների քանակից, ծառի հեշով հնարավոր է նույնականացնել դրա ամբողջ պարունակությունը։
* **Commit**, այս օբյեկտը միացնում է ծառին նախագծի ընդհանուր պատմությանը։ Commit-ի մեջ պահվում է ծառի անունը, ժամանակային նշագրումը, զրո կամ ավելի ծնող commit-ների հղումները։
* **Tag** (պիտակ), այս օբյեկտի մեջ պահվում է հղում դեպի այլ օբյեկտ։ Նաև կարող է պարունակել մետա տվյալներ այլ օբյեկտի վերաբերյալ։ Հիմնականում օգտագործվում է կոնկրետ commit-ին հղում անելու համար, երբ tag-ի միջոցով նշվում են կոդի վերջնական տարբերակները։
* **Packfile** այս zip ֆայլերի մեջ արխիվացվում են գիթի օբյեկտները։ Այս ֆայլերը օգտագործվում են տարածք խնայելու և օբյեկտները ցանցով ավելի հարմար տեղափոխելու համար։

Բոլոր օբյեկտները նույնականացվում են դրանց բովանդակության SHA-1 հեշի միջոցով։ Հեշի սկզբի երկու նիշերով գիթը ստեղծում է դիրեկտորի և դրա մեջ պահում օբյեկտը, իսկ հեշի մնացած նիշերով անվանում է օբյեկտի ֆայլը։ Նոր օբյեկտները սեղմվում են zip-ով և պահվում են ուղիղ ձևով։ Արդյունքում հիշողությունը շատ արագ կարող է լցվել, այս խնդիրը լուծելու համար օբյեկտները միավորվում են pack ֆայլերում և սեղմվում delta compression մեթոդով․ երբ blob-ները կարող են դառնալ ցուցիչ դեպի նախորդ փոփոխության ժամանակ եղած blob-ի վրա։

Git-ի կարևոր մաս են կազմում ճյուղերը (branch)։ Դրանք կարելի է դիտարկել, որպես անուն ունեցող ցուցիչ commit-ի վրա։ Commit-ի հեշը գրվում է տվյալ ճյուղի HEAD անունով ֆայլի մեջ։ Երբ օգտվողը ավելացնում է նոր commit, այդ ժամանակ HEAD ֆայլի պարունակությունը փոխարինվում է նոր commit-ի հեշով։

Գիթի օբյեկտների բազայում գտնվող այն օբյեկտները, որոնց վրա չկա հղում, կարող են ջնջվել ավտոմատ կամ `git gc` հրամանի միջոցով։

## Գիթ սպասարկիչ
Գիթը կոդի կառավարման ապակենտրոն համակարգ է, այն կարելի է օգտագործել որպես առանձին սպասարկիչ։ Դրա համար գիթը ունի պատրաստի հրաման `git daemon`։ Գիթ սպասարկիչները հիմնականում լսում են 9418 համարի պորտին։

Բաց կոդով գիթի հայտնի սպասարկիչներ են 
* Gerrit
* Phabricator և Phabricator Community Edition
* Kallithea
* Gitea

## Ծանոթագրություններ