Git je v informatice distribuovaný systém správy verzí vytvořený Linusem Torvaldsem pro vývoj jádra Linuxu. Návrh Gitu byl ovlivněn projekty BitKeeper (dříve používán pro vývoj jádra Linuxu) a Monotone. V současnosti () je projekt Git používán mnoha známými projekty, například: jádro Linuxu, X.Org nebo Ruby on Rails. Projekt spravuje Junio Haman, je šířen pod GPL verze 2 a jedná se o svobodný software.
Historie Vývoj Gitu začal v dubnu 2005, když vývojáři jádra Linuxu opustili proprietární správu zdrojového kódu (SCM) BitKeeper, který používali od roku 2002. Autor projektu a držitel copyrightu Larry McVoy tehdy ukončil možnost volného používání, které zdůvodnil tím, že Andrew Tridgell pomocí reverzního inženýrství protokolu BitKeeperu vytvořil SourcePuller. Stejný incident inicioval vývoj podobného systému správy zdrojových kódů Mercurial.
Linus Torvalds chtěl mít distribuční systém, který bude moci používat stejně jako BitKeeper, ale žádný takový nebyl volně dostupný. Torvalds zmínil SCM, který za 30 sekund aplikuje patch a aktualizuje všechna související metadata a poznamenal, že takový systém nemůže zvládnout (nemůže škálovat pro) vývoj jádra, kde správci potřebují udělat takových změn 250 najednou. Designové kritérium (návrhový vzor), které stanovil, vyžadovalo aplikaci patche za ne více než 3 sekundy a přidal další tři požadavky:
CVS je příklad jak to nedělat a pokud budeme na pochybách, uděláme to obráceně podpora a distribuovanost podobně jako workflow BitKeeperu zahrnout velmi silnou ochranu proti poškození ať už z důvodu nehody nebo záměru
Tato tři kritéria eliminovala všechny tehdy existující systémy pro správu verzí s výjimkou Monotone, který však nesplňoval výkonnostní požadavky. Bezprostředně po vydání linuxového jádra verze 2.6.12-rc2 se Linus Torvalds rozhodl napsat svůj vlastní systém.
Charakteristika Git byl inspirován verzovacími systémy BitKeeper a Monotone. "Historické souvislosti" kolem předchůdců systému git Git byl původně navržen jako nízkoúrovňový nástroj, který by ostatním umožnil vytvoření uživatelského rozhraní (front end) jako je Cogito nebo StGIT. Jádro projektu Git se však postupně rozrostlo na kompletní systém pro správu revizí, který je použitelný bez doplňkových nástrojů.
Ze zřejmých důvodů byl Git původně psán pro operační systém Linux, ale je snadno přenositelný na ostatní UN*Xové systémy, včetně BSD, Solarisu a Darwina. Implementován je samozřejmě také pod Windows. Existuje také reimplementace JGit v Javě a podpora ve formě plug-inu EGit pro Eclipse.
Návrh systému Git byl syntézou zkušeností Linuse Torvaldse s údržbou rozsáhlého projektu (jádro Linuxu) vyvíjeného distribuovaným (kolektivním) způsobem, s důkladnou znalostí výkonnosti souborového systému a potřeby vytvořit v krátké době použitelný nástroj (viz níže). Uvedené vlivy vedly k následujícím implementačním rozhodnutím:
Mocná podpora pro nelineární vývoj. Git podporuje rychlé vytváření větví a rychlé slučování (merge). Obsahuje specifické nástroje pro vizualizaci a navigaci v nelineární historii vývoje projektu. Jedním z klíčových předpokladů (na kterých je Git založen) je to, že změna je začleňována (merge) do jiných větví častěji, než je vytvářena -- tak jak prochází rukama různých recenzentů. Distribuovaný vývoj. Podobně jako je tomu u systémů Darcs, BitKeeper, Mercurial, SVK, Bazaar a Monotone poskytuje Git každému vývojáři lokální kopii celé historie vývoje. Změny se kopírují z jednoho takového úložiště do jiného. Tyto změny se importují v podobě dalších vývojových větví, které mohou být začleněny do jiné větve stejným způsobem, jako lokálně vyvíjené větve. Úložiště může být zpřístupněno prostřednictvím protokolů HTTP, FTP, rsync nebo protokolu Git realizovaného buď přes obyčejné sokety nebo přes SSH. Git obsahuje rovněž emulaci CVS serveru, což umožňuje zpřístupnit úložiště Git i stávajícím CVS klientům a zásuvným modulům (plugin) pro vývojová prostředí (IDE). Úložiště systémů Subversion a svk mohou být používána přímo, nástrojem git-svn. Efektivní práce s velkými projekty. Torvalds popisuje Git jako velmi rychlý a škálovatelný. Výkonnostní testy uskutečněné sdružením Mozilla ukázaly, že Git je o jeden řád rychlejší (cca 10×) než jiné systémy pro správu revizí. Některé operace jsou dokonce o dva řády rychlejší (cca 100×)., benchmarking "git diff" against "bzr diff", and finding the former 100× faster in some cases., observing that "git log" is 100× faster than "svn log" because the latter has to contact a remote server. Kryptografická autentizace historie. Historie je v systému Git uložena takovým způsobem, že jméno konkrétní revize (v pojmech Git je nazýváno „commit“) závisí na celkové historii vývoje, která vede až k tomuto commitu. Jakmile je jednou zveřejněno, nelze staré verze změnit, aniž by to prošlo bez povšimnutí (tuto vlastnost mají i systémy Mercurial a Monotone). Navržen jako sada nástrojů (Toolkit design). Systém Git byl navržen jako sada programů napsaných v jazyce C a dalších shellovských skriptů, které volání těchto programů obalují., describing Git's script-oriented design Při přenosu Gitu do systému Microsoft Windows byla většina skriptů nahrazena programy v jazyce C, ale původní návrh je zachován. Díky tomu lze snadno řetězit funkčnost jednotlivých komponent s cílem dosáhnout jiných zajímavých efektů., praising Git's scriptability Zaměnitelné slučovací strategie (Pluggable merge strategies). Součástí návrhu ve formě sady nástrojů (toolkit design) je dobře definovaný model neúplného sloučení (incomplete merge) a několik algoritmů pro jeho dokončení. Na vrcholu procesu stojí uživatelské hlášení, že Git není schopen dokončit sloučení (merge) automaticky a že musí být provedena ruční editace. Nepotřebné soubory se hromadí až do úklidu. Přerušení operace nebo návrat ke stavu před změnami vede k tomu, že v databázi zůstávají viset nepotřebné objekty. V rámci průběžně narůstající historie chtěných objektů jde o malé zlomky, ale jejich odstraňování (garbage collection) pomocí git-gc --prune může být pomalé.
Pro dosažení maximální rychlosti zachycuje Git vývoj projektu jako sérii stavů adresářových stromů se soubory. Tím se liší od dřívějších verzovacích systémů jako SCCS a RCS, které se soustředily na úsporu místa ukládáním rozdílů mezi verzemi jednotlivých souborů, a koncept, kdy se sledují změny identifikovatelného souboru procházejícího jednotlivými revizemi projektu, převzaly i pozdější systémy. Torvalds však tuto koncepci odmítl, takže Git vztahy mezi jednotlivými revizemi jednoho souboru nijak neuchovává. Z toho plynou významné důsledky:
Zjištění stavu celého projektu v libovolném historickém okamžiku je velmi rychlé. Zjištění historie změn jednoho souboru je o něco náročnější než zjištění historie změn celého projektu. Git zjišťuje historii změn jednoho souboru tak, že projde globální historii, a zjišťuje, zda jednotlivé změny mohly vést ke změně daného souboru. Zjišťování historie libovolné sady souborů je pak stejně efektivní jako v případě jednoho souboru. Velmi běžné je například zjišťování historie pro podadresář zdrojových textů a přidruženého globálního hlavičkového souboru. Přejmenování je prováděno implicitně a ne explicitně. Mezi časté stížnosti na CVS patří to, že součástí historie revizí souborů je jeho jméno. Kvůli tomu nelze přejmenovat soubor, aniž by došlo k přerušení jeho historie, nebo přejmenování historie, které ji učiní nepřesnou. Většina systémů pro správu revizí novějších než CVS tento problém řeší tím, že souboru přidělí unikátní trvanlivé jméno (něco jako číslo inodu), které přežívá i po přejmenování. Git podobné identifikátory nepoužívá a považuje to za výhodu. Jako argument lze použít skutečnost, že zdrojové soubory jsou kromě prostého přejmenování občas také rozdělovány nebo slučovány. Zachycením této skutečnosti jako prosté přejmenování by jen zafixovalo nepřesné vyjádření toho, co se ve skutečnosti stalo, v rámci (později neměnitelné) historie. Git tento problém řeší detekcí přejmenování během zjišťování historie stavů projektu (snapshots) a nikoliv jeho zaznamenáváním při zachycování stavu (snapshot)., on using git-blame to show code moved between source files (Stručně: Pokud se v revizi N nachází nějaký soubor, pak soubor se stejným jménem v revizi N-1 je jeho předpokládaným předkem. Pokud ale v revizi N-1 není soubor podobného jména, pak Git hledá soubor, který existoval v revizi N-1 a je velmi podobný novému souboru.) Tento přístup ovšem při každém prohlížení historie vyžaduje více času procesoru a používání více voleb pro nastavení potřebných heuristik.
Někteří lidé kritizují model ukládání dat:
Opakované explicitní balení objektů. Git uchovává každý nově vytvořený objekt jako samostatný soubor. Ačkoliv je každý z nich komprimován, vede to k prostorové neefektivnosti. Tento problém je řešen používáním balíčků (pack), které ukládají více objektů v jednom souboru (nebo v jednom síťovém proudu dat) při zhušťování na základě uchovávání vzájemných rozdílů. Při kompresi balíčků se využívá heuristika, která vychází z toho, že soubory se stejným jménem jsou asi podobné. Ale na této heuristice není závislá korektnost. Nově vytvořené objekty (nově přidaná historie) jsou ukládány odděleně. Pro dosažení prostorové efektivnosti je nutné provést znovuzabalení (repacking). Git provádí periodické znovuzabalení automaticky, ale lze je provést i ručně provedením příkazu git gc.
Git implementuje několik slučovacích strategií (merging strategies). Nestandardní strategie může být zvolena v okamžiku zahájení slučování:
resolve Tradiční třícestný slučovací algoritmus (3-way merge). recursive Toto je standardní (default) strategie užívaná v případě, kdy dochází k přetažení (pulling) nebo sloučení (merging) jedné větve. Jde o variantu třícestného slučovacího algoritmu. „Pokud existuje více než jeden společný předek, který by mohl být použit pro třícestné slučování, vytvoří se sloučený strom společných předků a ten se použije jako referenční strom pro třícestné slučování. Tento přístup vede k méně slučovacím konfliktům aniž by docházelo k chybným slučováním. Bylo to potvrzeno testy na skutečných případech slučování (merge commits) převzatých z historie vývoje jádra Linux 2.6. Tento přístup navíc může detekovat a vyřešit slučování, jehož součástí je i přejmenování“. octopus Standardní (default) strategie při slučování více než dvou hlavních větví (when merging more than two heads).
Datové struktury Git není v podstatě jen systém pro správu zdrojových kódů (SCM):
K tomuto základu byla postupně, jak se ukázala jejich potřeba, doplněna řada funkcí, které jsou očekávány od tradičních SCM.
Git používá dvě základní datové struktury umístěné v adresáři .git: proměnlivý index (také nazývaný stage nebo cache), který ukládá informace o pracovním stromě a připravovaném commitu (revizi); a databázi, do které se pouze připisuje. Index slouží jako spojovací bod mezi objektovou databází a pracovním stromem. Databáze obsahuje čtyři typy objektů:
Blob slouží k uložení obsahu jednoho souboru. Blob objekt neobsahuje název souboru, časová razítka ani jiná metadata. Strom je ekvivalentem adresáře. Obsahuje seznam názvů souborů, z nichž ke každému je přiřazena řada bitových příznaků a název objektu typu blob nebo strom, které odpovídají jednotlivým souborům, symbolickým odkazům, nebo podadresářům. Tento objekt popisuje snapshot zdrojového adresáře, jejich hierarchie pak snapshot zdrojového stromu. Commit slouží k seřazení objektů strom do historie. Obsahuje název objektu strom (který odpovídá nejvyšší úrovni zdrojového adresáře), časové razítko, žurnálovací zprávy a jména commit objektů, které jsou bezprostředními předchůdci tohoto commitu; mnoho commitů má jednoho bezprostředního předchůdce, commity vzniklé slučováním mají dva nebo více předchůdců, nejstarší commit nemá žádného předchůdce.