HowItWorks:Git: Difference between revisions

From Wikibase
Jump to navigation Jump to search
Creating HowItWorks:Git — AI-assisted (RonzzWikiCowriter) (via create-page on MediaWiki MCP Server)
 
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{HowItWorks}}
{{HowItWorks}}


'''Git''' is a free and open source distributed version control system, designed to handle everything from small to very large projects with speed and efficiency.<ref>{{#cite:Q1455}}</ref> Written in C and released under the GNU General Public License v2, it was created by [[Person:Linus Torvalds|Linus Torvalds]] in April 2005 to manage the Linux kernel source code, and is today maintained by [[Person:Junio Hamano|Junio C. Hamano]].<ref>{{#cite:Q1465}}</ref><ref>{{#cite:Q1456}}</ref> Unlike most other version control systems, which store data as a list of file-based changes, Git stores data as a series of snapshots of a miniature filesystem.<ref>{{#cite:Q1457}}</ref>
'''Git''' is a free and open source distributed version control system, designed to handle projects of any size with speed and efficiency.<ref>{{#cite:Q1455}}</ref> Written in C and released under the GNU General Public License v2, it was created by [[Person:Linus Torvalds|Linus Torvalds]] in April 2005 to manage the Linux kernel source code, and is today maintained by [[Person:Junio Hamano|Junio C. Hamano]].<ref>{{#cite:Q1465}}</ref><ref>{{#cite:Q1456}}</ref>


== Git, a distributed version control system ==
== Git, a distributed version control system ==
Line 7: Line 7:
A '''version control system''' (VCS) records changes to a set of files over time, so that any past version can be recalled later. Without one, a project is just a folder of files that only moves forward: a wrong edit cannot be undone, and two people editing the same files quickly overwrite each other.
A '''version control system''' (VCS) records changes to a set of files over time, so that any past version can be recalled later. Without one, a project is just a folder of files that only moves forward: a wrong edit cannot be undone, and two people editing the same files quickly overwrite each other.


Most older systems — CVS, Subversion, Perforce — are '''centralized''': one server holds the canonical repository, and anything that needs history must travel over the network to that server. Git is '''distributed''': every clone of a repository is a complete repository with the entire history, so nearly every operation can be done locally, without a network connection.<ref>{{#cite:Q1457}}</ref>
Most older systems, such as CVS, Subversion, and Perforce, are '''centralized''': one server holds the canonical repository, and anything that needs history must travel over the network to that server. In contrast, Git is '''distributed''': every clone of a repository is a complete repository with the entire history, so nearly every operation can be done locally, without a network connection.<ref>{{#cite:Q1457}}</ref>


Git has three main states that files can reside in — '''modified''', '''staged''' and '''committed''' — matching the three main sections of a project: the working tree, the staging area, and the Git directory.<ref>{{#cite:Q1457}}</ref>
Git functions by storing multiple versions of each tracked file, classified into three states:


* The '''working tree''' is a single checkout of one version of the project — the files on disk that you edit.<ref>{{#cite:Q1457}}</ref>
* '''Committed''': immutable, permanent snapshots in the project's history, made when user calls <code>git commit</code>. Git stores those snapshots in its object database in the '''Git directory''' (normally <code>.git/</code>), alongside the project metadata. When you clone a repository, this is what gets copied.<ref>{{#cite:Q1457}}</ref> User can recall any snapshot later with <code>git checkout</code> or <code>git switch</code>.
* The '''staging area''' is a file, generally contained in the Git directory, that stores information about what will go into your next commit; its technical name is the "index".<ref>{{#cite:Q1457}}</ref>
* '''Modified''': This is the on-disk version of a file. Any changes since the last commit are stored in a '''working tree'''<ref>{{#cite:Q1457}}</ref>
* The '''Git directory''' (normally <code>.git/</code>) is where Git stores the metadata and object database of your project; it is what gets copied when you clone a repository.<ref>{{#cite:Q1457}}</ref>
* '''Staged''': A temporary snapshot of a modified file made when user called <code>git add</code> on the file. Technically named the "index", it becomes a new immutable, permanent snapshot (commit) when user gives Git the go-ahead by calling the <code>git commit</code> command.<ref>{{#cite:Q1457}}</ref>


The basic Git workflow: you modify files in the working tree; you selectively stage the changes you want in the next commit, which adds them to the staging area; you commit, which takes the files as they are in the staging area and stores that snapshot permanently in the Git directory.<ref>{{#cite:Q1457}}</ref>
Those different versions of the same file becomes the base of the '''Git history''', a permanent record of changes made to files in a project. Via various commands, users can search it, revert the project to a particular state, or even cherry-pick certain changes on top of each other in a desired order on top of a base state to make a new state. Furthermore, users can even create parallel sub-tracks in the Git history via branches to allow the project to simultaneously evolve in different directions, temporarily or permanently, facilitating multi-user collaboration.<ref>{{#cite:Q1457}}</ref>
 
As of 2026, Git is effectively THE standard for version control in software development.<ref>{{#cite:Q1456}}</ref>


== A short history ==
== A short history ==


Git was born out of the needs of the Linux kernel project. From 1991 to 2002, kernel changes were passed around as patches and archived files; in 2002, the project began using BitKeeper, a proprietary distributed version control system.<ref>{{#cite:Q1458}}</ref>
Git was born out of the needs of the Linux kernel project.<ref>{{#cite:Q1458}}</ref>


In 2005, the relationship between the kernel community and the company that developed BitKeeper broke down, and the tool's free-of-charge status was revoked. That prompted the Linux development community — in particular [[Person:Linus Torvalds|Linus Torvalds]], the creator of Linux — to build their own tool based on the lessons learned from BitKeeper. The stated goals of the new system: speed; simple design; strong support for non-linear development (thousands of parallel branches); fully distributed; and able to handle large projects like the Linux kernel efficiently.<ref>{{#cite:Q1458}}</ref>
In the early days of Linux, from 1991 to 2002, kernel changes were passed around as patches and archived files, which worked fine as the number of contributors is relatively low.


On April 7, 2005, Torvalds made the first commit to the new system — commit <code>e83c5163</code> — with the self-deprecating message "Initial revision of 'git', the information manager from hell".<ref>{{#cite:Q1465}}</ref> The name itself is a joke: "git" is British slang for an unpleasant person, and the README of that first commit lists what it "can mean anything, depending on your mood" — "global information tracker" when you are in a good mood, and "goddamn idiotic truckload of sh*t" when it breaks.<ref>{{#cite:Q1465}}</ref> Git was able to manage its own source code from the start, and within months Torvalds handed the project over to [[Person:Junio Hamano|Junio C. Hamano]], who has maintained it ever since.<ref>{{#cite:Q1456}}</ref>
Around 2002, as the number of developers increased, this spontaneous, haphazard system started to break down. It became increasingly cumbersome to keep everyone on the same page. A version control system, became therefore a necessity. BitKeeper, a proprietary distributed version control system, was offered free-of-charge to the Linux kernel project and was adopted.<ref>{{#cite:Q1458}}</ref>


In April 2008, [[Collective:GitHub|GitHub]] launched as a web-based hosting service for Git repositories and grew into what its own description calls "the world's most widely adopted, AI-powered developer platform where millions of developers, businesses, and the largest open source community build software".<ref>{{#cite:Q1430}}</ref> In August 2008, Git 1.6.0 became the project's first deliberately backward-incompatible ("breaking") release.<ref>{{#cite:Q1464}}</ref>
In 2005, the relationship between the kernel community and BitMover Inc., the company that owns BitKeeper, broke down. BitMover Inc., citing a violation of its license terms, revoked the Linux kernel project's free-of-charge access to BitKeeper. Rather than making concessions to negotiate a new term of access with BitMover Inc., the Linux development community — in particular [[Person:Linus Torvalds|Linus Torvalds]], the creator of Linux, decided to build their own better, more efficient version-control tool based on the lessons learned from BitKeeper. The stated goals of the new system was ambitious: speed; simple design; strong support for non-linear development (thousands of parallel branches); fully distributed; and able to handle large projects like the Linux kernel efficiently.<ref>{{#cite:Q1458}}</ref>


In May 2014, Git 2.0 was released. Since then the project uses two-part <code>major.minor</code> release numbers; before that, releases were numbered <code>1.major.minor</code>, with the jump to 2.0 reserved for "really large backward-compatibility breaking changes".<ref>{{#cite:Q1464}}</ref>
On April 7, 2005, after about 10 days of devoted development, Torvalds made the first commit to the new system — commit <code>e83c5163</code> — with the self-deprecating message "Initial revision of 'git', the information manager from hell".<ref>{{#cite:Q1465}}</ref> The name 'git' itself is a joke: it is a British slang for an unpleasant person. According to the README included in that very first commit, "it can mean anything, depending on your mood": "global information tracker" when you are in a good mood, and "goddamn idiotic truckload of sh*t" when it breaks.<ref>{{#cite:Q1465}}</ref>


On October 19, 2020, Git 2.29 introduced experimental support for the SHA-256 object format alongside the long-standing SHA-1.<ref>{{#cite:Q1460}}</ref>
Later in 2005, to reconcentrate himself on Linux kernel development, Torvalds handed the project over to [[Person:Junio Hamano|Junio C. Hamano]], who has maintained it ever since.<ref>{{#cite:Q1456}}</ref>


In April 2025, the project turned 20; the annual contributor conference Git Merge 2025 celebrated two decades of Git.<ref>{{#cite:Q1461}}</ref>
In May 2014, Git 2.0, which carried large backward-incompatible changes, was released<ref>{{#cite:Q1464}}</ref>


As of September 2026, the latest feature release is Git 2.55.0, published on June 29, 2026.<ref>{{#cite:Q1455}}</ref> The project is preparing Git 3.0, a breaking release that plans to make SHA-256 the default hash function for new repositories, switch the default reference storage to the reftable format, adopt "main" as the default branch name, and make Rust a mandatory part of the build.<ref>{{#cite:Q1464}}</ref>
In 2020, Git 2.29 introduced experimental support for the SHA-256 object format alongside the long-standing SHA-1.<ref>{{#cite:Q1460}}</ref>
 
As of September 2026, the project is preparing for Git 3.0, a breaking release that plans to make SHA-256 the default hash function for new repositories, switch the default reference storage to the reftable format, adopt "main" as the default branch name, and make Rust a mandatory part of the build.<ref>{{#cite:Q1464}}</ref>


== Components and interactions ==
== Components and interactions ==


A Git repository normally consists of a working directory with a <code>.git</code> subdirectory at the top level. The <code>.git</code> directory contains, among other things, a compressed object database representing the complete history of the project, an index file that links that history to the current contents of the working tree, and named pointers into that history — tags and branch heads.<ref>{{#cite:Q1456}}</ref>
A Git repository consists usually of a working directory with a <code>.git</code> subdirectory at the top level.  
 
The <code>.git</code> directory contains, among other things, a compressed object database representing the complete history of the project, an index file that links that history to the current contents of the working tree, and named pointers into that history — tags and branch heads.<ref>{{#cite:Q1456}}</ref>


<uml>
<uml>
Line 87: Line 93:
@enduml
@enduml
</uml>
</uml>
The main pieces:
* '''The object database''' — "objects of three main types: blobs, which hold file data; trees, which point to blobs and other trees to build up directory hierarchies; and commits, which each reference a single tree and some number of parent commits". A fourth object type, the annotated tag, exists to vouch for a specific commit. "All objects are named by the SHA-1 hash of their contents, normally written as a string of 40 hex digits. Such names are globally unique."<ref>{{#cite:Q1456}}</ref> Git itself describes this as "a content-addressable filesystem... at the core of Git is a simple key-value data store: you can insert any kind of content into a Git repository, for which Git will hand you back a unique key you can use later to retrieve that content".<ref>{{#cite:Q1463}}</ref>
* '''The index''' — the staging area on disk. It is "initialized with a list of all paths and, for each path, a blob object and a set of attributes" taken from the corresponding working-tree file; subsequent changes are found by comparing those attributes, and new commits are created from the content stored in the index.<ref>{{#cite:Q1456}}</ref>
* '''Refs''' — "named pointers called refs mark interesting points in history. A ref may contain the SHA-1 name of an object or the name of another ref (the latter is called a 'symbolic ref')". Branch heads live under <code>refs/heads/</code>, tags under <code>refs/tags/</code>, and the symbolic ref <code>HEAD</code> names the currently checked-out branch.<ref>{{#cite:Q1456}}</ref>
* '''Packfiles''' — "when first created, objects are stored in individual files, but for efficiency may later be compressed together into 'pack files'".<ref>{{#cite:Q1456}}</ref>
* '''Porcelain and plumbing''' — Git deliberately splits its command set in two: "high level ('porcelain') commands" for everyday use — <code>git add</code>, <code>git commit</code>, <code>git log</code>, <code>git status</code> — and "low level ('plumbing') commands" for scripting — <code>git hash-object</code>, <code>git cat-file</code>, <code>git update-index</code>, <code>git write-tree</code>. The low-level interfaces are "meant to be a lot more stable than Porcelain level commands, because these commands are primarily for scripted use".<ref>{{#cite:Q1456}}</ref>
* '''Remotes''' — other repositories to synchronize with. <code>git fetch</code> "downloads objects and refs from another repository", <code>git push</code> "updates remote refs along with associated objects", and <code>git clone</code> "clones a repository into a new directory".<ref>{{#cite:Q1456}}</ref>


== Git in action ==
== Git in action ==
Line 130: Line 127:
</uml>
</uml>


In detail:
<ref>{{#cite:Q1463}}</ref>
 
# You modify files in the working tree.
# <code>git add</code> takes each changed file, compresses it, computes its SHA-1 and stores it as a '''blob''' in the object database; it then registers the file in the index. Nothing is yet part of history.
# <code>git commit</code> reads the index and writes a '''tree''' object — the full snapshot of the project at that moment — then a '''commit''' object that points at that tree, at the parent commit(s), and carries the author, committer, message and timestamp.
# The current branch ref — and with it <code>HEAD</code> — moves to the new commit.
# The snapshot is now permanent: <code>git log</code> shows it, and because the commit contains the tree and the tree contains the blobs, the entire snapshot is reachable and safe.
 
This is exactly what the plumbing commands do by hand: "You've just done the low-level operations to build up a Git history without using any of the front end commands. This is essentially what Git does when you run the git add and git commit commands — it stores blobs for the files that have changed, updates the index, writes out trees, and writes commit objects that reference the top-level trees and the commits that came immediately before them."<ref>{{#cite:Q1463}}</ref>


=== Syncing with a remote ===
=== Syncing with a remote ===
Line 171: Line 160:
@enduml
@enduml
</uml>
</uml>
* <code>git clone &lt;url&gt;</code> copies the whole repository — object database and refs — to your machine, sets up remote-tracking refs like <code>origin/main</code>, and checks out the default branch. Because every clone carries the full history, any clone can act as a backup, a fork, or a new remote.<ref>{{#cite:Q1457}}</ref>
* <code>git fetch</code> downloads objects and refs the remote has and you do not, without touching your working tree. <code>git pull</code> is fetch followed by integration (a merge, or a rebase if configured).<ref>{{#cite:Q1456}}</ref>
* <code>git push</code> uploads your new objects and asks the remote to update its refs. When both sides changed the same lines, the integration produces '''conflicts''': Git writes both versions into the file with markers, and you resolve them by editing and committing.


== Key design decisions ==
== Key design decisions ==
Line 180: Line 165:
=== Snapshots, not differences ===
=== Snapshots, not differences ===


The founding decision, and the one that "makes Git reconsider almost every aspect of version control that most other systems copied from the previous generation": most VCSs store information as a set of files and the changes made to each file over time (delta-based version control); Git instead thinks of its data "more like a series of snapshots of a miniature filesystem". Every commit is a picture of all files at that moment. To stay efficient, "if files have not changed, Git doesn't store the file again, just a link to the previous identical file it has already stored".<ref>{{#cite:Q1457}}</ref>
The radical difference between Git and earlier version control systems is that instead of storing commits as deltas (changes made in comparison to previous version), Git stores commits as snapshots: exact state of changed files at commit time.<ref>{{#cite:Q1457}}</ref>
 
This snapshot approach is robust: unlike in delta-based version control systems, corruption of a commit state would not propagate to all newer commits based on that commit.
 
What's more, this approach also renders large rollbacks trivial: rolling back to the state of any commit, even those from 5 years ago, consists of a simple object database query to pull up a particular snapshot, and not mathematically computing the desired state by reverting all new deltas from the latest state.


=== Nearly every operation is local ===
=== Nearly every operation is local ===


"Most operations in Git need only local files and resources to operate — generally no information is needed from another computer on your network." Because the entire history lives on your disk, browsing history, diffing old versions, committing and branching all work instantly and offline — on a plane, on a train, or with a broken VPN. Centralized systems cannot commit without the server; Git can.<ref>{{#cite:Q1457}}</ref>
Another important difference between Git and earlier version-control systems is that most operations can be completed locally.
 
While most earlier systems rely on the central, authoritative "bookkeeping" server for almost every operation, Git is distributed. Each repository clone contains the entire Git history, which means most git operations, like browsing and diffing old versions, committing and branching all work instantly and offline. Syncing with a server is entirely optional. <ref>{{#cite:Q1457}}</ref>


=== Integrity by content addressing ===
This distributed design made Git extremely suitable for large Opensource projects with thousands of contributors. The load on the central "bookkeeping" server is minimal: contributors call <code>git clone</code> to copy the repository to their local machine once, then everything happens locally on their machine, until they have arrived at something meaningful to be shared back with the entire community, at which point they call <code>git push</code> to sync back their changes to the central server.


"Everything in Git is checksummed before it is stored and is then referred to by that checksum. This means it's impossible to change the contents of any file or directory without Git knowing about it." The checksum is the SHA-1 hash of the object's content (plus a small header), written as a 40-character hexadecimal string; Git stores everything in its database "not by file name but by the hash value of its contents".<ref>{{#cite:Q1457}}</ref><ref>{{#cite:Q1463}}</ref>
=== Storage by hash value, not file name ===


The weakness of SHA-1 (NIST deprecated it in 2011, and practical collision attacks appeared from 2015 on) is a known problem: Git 2.29 (October 19, 2020) added experimental support for the SHA-256 object format, explicitly noting "there is no interoperability between SHA-1 and SHA-256 repositories yet", and Git 3.0 is planned to make SHA-256 the default hash for new repositories.<ref>{{#cite:Q1460}}</ref><ref>{{#cite:Q1464}}</ref>
Git stores everything in its database by the hash value of its contents, not file name.<ref>{{#cite:Q1457}}</ref><ref>{{#cite:Q1463}}</ref>
 
This design offers multiple benefits:
 
* '''Guaranteed integrity''': Any corruption to a file's content becomes immediately obvious to Git at retrieval time: the hash value simply would not match.
* '''Safe indefinite caching''': A cached version of any file never becomes silently stale. Git can instantly verify its freshness by comparing the hash value to the latest version.
* '''Zero-cost file renaming''': When user renames a file (e.g., from README to README.md), the hash value, which is calculated uniquely based on a file's content, stays constant. Therefore, no change is needed in Git's object storage when a file is renamed.


=== Branches are cheap pointers ===
=== Branches are cheap pointers ===


A branch is not a copy of the tree, not a container of commits — it is just a ref, a pointer to a commit. Creating a branch writes a 41-byte file; switching branches only updates <code>HEAD</code> and the working tree. This makes branching and merging a first-class, everyday operation and delivers the original design goal of "strong support for non-linear development (thousands of parallel branches)".<ref>{{#cite:Q1456}}</ref><ref>{{#cite:Q1458}}</ref> Merging two lines of development is simply creating a commit with two parents.<ref>{{#cite:Q1456}}</ref>
A branch is not a copy of the Git tree nor a container of commits — it is just a thin <code>ref</code>, a 41-byte pointer to a commit. Therefore, creating and merging branches cost next-to-nothing, delivering the original design goal of "strong support for non-linear development (thousands of parallel branches)".<ref>{{#cite:Q1456}}</ref><ref>{{#cite:Q1458}}</ref><ref>{{#cite:Q1456}}</ref>


=== A three-part staging model ===
=== A three-part staging model ===


Git interposes the '''index''' between the working tree and the repository. Nothing is committed unless it is explicitly staged: <code>git add</code> moves changes into the index, <code>git commit</code> snapshots the index. The cost is one extra step compared with systems where any saved file is automatically versioned; the payoff is that a commit can contain exactly what you want it to contain — a surgical selection of changes across many files, reviewed with <code>git diff --cached</code> before it becomes history.<ref>{{#cite:Q1457}}</ref>
By interposes the '''index (staging area)''' between the working tree and the repository, Git ensures that nothing is committed unless user explicitly requests it with <code>git add</code>. In addition to providing surgical precision for each commit, this design also discourages contributors from making odd-time commits just to "save work".<ref>{{#cite:Q1457}}</ref>


=== Plumbing and porcelain ===
=== Plumbing and porcelain ===


Git is built as a toolkit, not a monolith: a stable set of low-level plumbing commands that manipulate objects, the index and refs directly, with a thin porcelain layer of user-friendly commands on top. The plumbing interfaces are deliberately stable "because these commands are primarily for scripted use", while porcelain commands may change to improve the end-user experience. This design is what lets a huge ecosystem of GUIs, hosting services and tools build on Git without forking it.<ref>{{#cite:Q1456}}</ref>
For small-scale projects with only a few contributors, manually managing Git history is quite doable. However, for large projects with thousands of contributors, manual Git history management can quickly become a full-time job, making scripting/advanced Git management tools highly desirable.
 
To satisfy both needs, Git exposes two sets of commands: a "'''porcelain'''" set of high-level commands designed to be directly called by human users, and a "'''plumbing'''" set of low-level commands exposing direct object storage, index, and ref manipulation, designed primarily for scripted use. The "plumbing" commands are deliberately stable across versions to ensure lasting compatibility of user scripts and tools.<ref>{{#cite:Q1456}}</ref>
 
=== Git stores everything ===
 
Git is built within the 21st century context: storage is cheap; data loss is costly.


=== Git generally only adds data ===
Once a Git commit is made, the commit-time project snapshot stays in the project's Git object storage forever. Even commands that rewrites Git history, such as <code>amend</code>, <code>rebase</code>, and <code>reset</code> do not erase them.<ref>{{#cite:Q1457}}</ref>


"When you do actions in Git, nearly all of them only add data to the Git database. It is hard to get the system to do anything that is not undoable or to make it erase data in any way." Uncommitted work can be lost, but once a snapshot is committed — and especially once it is pushed to another repository — it is very difficult to lose. Because objects are immutable and content-addressed, nothing is ever overwritten: history only grows. This is what makes Git's rewriting commands (amend, rebase, reset) safe to use: they create new commits and move refs, never destroying the old ones until garbage collection reclaims them.<ref>{{#cite:Q1457}}</ref>
Although the "store everything" approach inevitably introduces an storage overhead, the storage overhead's size is much smaller than the mathematical product of the number of commits and the repo's size, thanks to Git's backend performing aggressive compression and optimisation on its object storage. The data-integrity benefits outweigh the additional storage cost by far on any reasonably modern computer system.


=== Backward compatibility, broken deliberately ===
=== Backward compatibility is broken only when strictly necessary ===


"The Git project aims to ensure backwards compatibility to the best extent possible. Minor releases will not break backwards compatibility unless there is a very strong reason to do so." But the project "irregularly releases breaking versions that deliberately break backwards compatibility", to stay "relevant, safe and maintainable going forward". So far there have been two: Git 1.6.0 (August 2008) and Git 2.0 (May 2014), with the numbering scheme changing from <code>1.major.minor</code> to <code>major.minor</code> at 2.0. The next one, Git 3.0, is planned to change the default hash to SHA-256, the default reference storage to reftable, the default branch name to "main", and to require Rust in the build.<ref>{{#cite:Q1464}}</ref>
According to Git's official website: "the Git project aims to ensure backwards compatibility to the best extent possible. Minor releases will not break backwards compatibility unless there is a very strong reason to do so." But the project "irregularly releases breaking versions that deliberately break backwards compatibility", to stay "relevant, safe and maintainable going forward".
 
Two decades onward since Git's birth, there have only been two breaking changes : once in 2008 with Git 1.6.0, and once in 2014 with Git 2.0. The next one, Git 3.0, is planned for end of 2026.<ref>{{#cite:Q1464}}</ref>


== Try it yourself ==
== Try it yourself ==


The web-based checks below were verified live on 2026-09-01; the local command outputs are reproduced from Git's official documentation (the [[Q1459|Pro Git book]]<ref>{{#cite:Q1459}}</ref> and the git manual), as marked.
Commands reproduced from Git's official documentation.<ref>{{#cite:Q1459}}</ref>


<pre>
<blockquote>
Syntax of certain commands may be different on Windows.
</blockquote>
 
<syntaxhighlight lang="bash" copy>
# 1. Which version do you have?
# 1. Which version do you have?
git --version
git --version
</pre>
</syntaxhighlight>


Documented output (your version depends on your install):
Output (your version depends on your install):


<pre>
<pre>
Line 227: Line 236:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 2. The very first commit of git.git, via the GitHub API (live check, 2026-09-01)
# 2. The very first commit of git.git, via the GitHub API
curl -s "https://api.github.com/repos/git/git/commits/e83c5163316f89bfbde7d9ab23ca2e25604af290" \
curl -s "https://api.github.com/repos/git/git/commits/e83c5163316f89bfbde7d9ab23ca2e25604af290" \
   | grep -E '"name"|"date"|"message"'
   | grep -E '"name"|"date"|"message"'
</pre>
</syntaxhighlight>


Output (verified live):
Output (liveness check performed 2026-09-01):


<pre>
<pre>
Line 243: Line 252:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 3. The latest feature release and its date, from the official website (live check, 2026-09-01)
# 3. The latest feature release and its date, from the official website
curl -s https://git-scm.com/ | grep -oE "2\.55\.0|2026-06-29" | sort -u
curl -s https://git-scm.com/ | grep -oE "2\.55\.0|2026-06-29" | sort -u
</pre>
</syntaxhighlight>


Output (verified live):
Output (liveness check performed 2026-09-01):


<pre>
<pre>
Line 255: Line 264:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 4. Git is a content-addressable store: hash some content, get back its key
# 4. Git is a content-addressable store: hash some content, get back its key
echo 'test content' | git hash-object -w --stdin
echo 'test content' | git hash-object -w --stdin
</pre>
</syntaxhighlight>


Documented output:<ref>{{#cite:Q1463}}</ref>
Output:


<pre>
<pre>
Line 266: Line 275:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 5. Read the object back by its key
# 5. Read the object back by its key
git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
</pre>
</syntaxhighlight>


Documented output:
Output:


<pre>
<pre>
Line 277: Line 286:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 6. Where did it go? Objects are stored under .git/objects, sharded by hash
# 6. Where did it go? Objects are stored under .git/objects, sharded by hash
find .git/objects -type f
find .git/objects -type f
</pre>
</syntaxhighlight>


Documented output:
Output:


<pre>
<pre>
Line 288: Line 297:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 7. A real project: init, add, commit, log
# 7. A real project: init, add, commit, log
mkdir demo && cd demo
mkdir demo && cd demo
git init
git init
</pre>
</syntaxhighlight>


Documented output (path depends on where you run it):
Output (path depends on where you run it):


<pre>
<pre>
Line 300: Line 309:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
echo "Hello, Git!" > README.md
echo "Hello, Git!" > README.md
git add README.md
git add README.md
git commit -m "first commit"
git commit -m "first commit"
</pre>
</syntaxhighlight>


Documented output (hashes and authorship vary):
Output (hashes and authorship vary):


<pre>
<pre>
Line 314: Line 323:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
git log --oneline
git log --oneline
</pre>
</syntaxhighlight>


Documented output:
Output:


<pre>
<pre>
Line 324: Line 333:
</pre>
</pre>


<pre>
<syntaxhighlight lang="bash" copy>
# 8. A commit object is just text: tree, author, committer, message
# 8. A commit object is just text: tree, author, committer, message
git cat-file -p HEAD
git cat-file -p HEAD
</pre>
</syntaxhighlight>


Documented output (hashes, identity and timestamps vary):<ref>{{#cite:Q1463}}</ref>
Output (hashes, identity and timestamps vary):<ref>{{#cite:Q1463}}</ref>


<pre>
<pre>
Line 338: Line 347:
First commit
First commit
</pre>
</pre>
'''Verification:''' outputs 2–3 were checked against the live GitHub API and git-scm.com on 2026-09-01; outputs 1 and 4–8 are reproduced from Git's official documentation — the Pro Git book chapters "What is Git?" and "Git Objects", and the git manual page.<ref>{{#cite:Q1463}}</ref><ref>{{#cite:Q1457}}</ref><ref>{{#cite:Q1456}}</ref>


== References ==
== References ==

Latest revision as of 14:25, 1 September 2026

Explains how things actually work — part of our technology dissections collection.

Git is a free and open source distributed version control system, designed to handle projects of any size with speed and efficiency.[1] Written in C and released under the GNU General Public License v2, it was created by Linus Torvalds in April 2005 to manage the Linux kernel source code, and is today maintained by Junio C. Hamano.[2][3]

Git, a distributed version control system

A version control system (VCS) records changes to a set of files over time, so that any past version can be recalled later. Without one, a project is just a folder of files that only moves forward: a wrong edit cannot be undone, and two people editing the same files quickly overwrite each other.

Most older systems, such as CVS, Subversion, and Perforce, are centralized: one server holds the canonical repository, and anything that needs history must travel over the network to that server. In contrast, Git is distributed: every clone of a repository is a complete repository with the entire history, so nearly every operation can be done locally, without a network connection.[4]

Git functions by storing multiple versions of each tracked file, classified into three states:

  • Committed: immutable, permanent snapshots in the project's history, made when user calls git commit. Git stores those snapshots in its object database in the Git directory (normally .git/), alongside the project metadata. When you clone a repository, this is what gets copied.[4] User can recall any snapshot later with git checkout or git switch.
  • Modified: This is the on-disk version of a file. Any changes since the last commit are stored in a working tree[4]
  • Staged: A temporary snapshot of a modified file made when user called git add on the file. Technically named the "index", it becomes a new immutable, permanent snapshot (commit) when user gives Git the go-ahead by calling the git commit command.[4]

Those different versions of the same file becomes the base of the Git history, a permanent record of changes made to files in a project. Via various commands, users can search it, revert the project to a particular state, or even cherry-pick certain changes on top of each other in a desired order on top of a base state to make a new state. Furthermore, users can even create parallel sub-tracks in the Git history via branches to allow the project to simultaneously evolve in different directions, temporarily or permanently, facilitating multi-user collaboration.[4]

As of 2026, Git is effectively THE standard for version control in software development.[3]

A short history

Git was born out of the needs of the Linux kernel project.[5]

In the early days of Linux, from 1991 to 2002, kernel changes were passed around as patches and archived files, which worked fine as the number of contributors is relatively low.

Around 2002, as the number of developers increased, this spontaneous, haphazard system started to break down. It became increasingly cumbersome to keep everyone on the same page. A version control system, became therefore a necessity. BitKeeper, a proprietary distributed version control system, was offered free-of-charge to the Linux kernel project and was adopted.[5]

In 2005, the relationship between the kernel community and BitMover Inc., the company that owns BitKeeper, broke down. BitMover Inc., citing a violation of its license terms, revoked the Linux kernel project's free-of-charge access to BitKeeper. Rather than making concessions to negotiate a new term of access with BitMover Inc., the Linux development community — in particular Linus Torvalds, the creator of Linux, decided to build their own better, more efficient version-control tool based on the lessons learned from BitKeeper. The stated goals of the new system was ambitious: speed; simple design; strong support for non-linear development (thousands of parallel branches); fully distributed; and able to handle large projects like the Linux kernel efficiently.[5]

On April 7, 2005, after about 10 days of devoted development, Torvalds made the first commit to the new system — commit e83c5163 — with the self-deprecating message "Initial revision of 'git', the information manager from hell".[2] The name 'git' itself is a joke: it is a British slang for an unpleasant person. According to the README included in that very first commit, "it can mean anything, depending on your mood": "global information tracker" when you are in a good mood, and "goddamn idiotic truckload of sh*t" when it breaks.[2]

Later in 2005, to reconcentrate himself on Linux kernel development, Torvalds handed the project over to Junio C. Hamano, who has maintained it ever since.[3]

In May 2014, Git 2.0, which carried large backward-incompatible changes, was released[6]

In 2020, Git 2.29 introduced experimental support for the SHA-256 object format alongside the long-standing SHA-1.[7]

As of September 2026, the project is preparing for Git 3.0, a breaking release that plans to make SHA-256 the default hash function for new repositories, switch the default reference storage to the reftable format, adopt "main" as the default branch name, and make Rust a mandatory part of the build.[6]

Components and interactions

A Git repository consists usually of a working directory with a .git subdirectory at the top level.

The .git directory contains, among other things, a compressed object database representing the complete history of the project, an index file that links that history to the current contents of the working tree, and named pointers into that history — tags and branch heads.[3]

Git in action

Two flows cover most of everyday Git: recording a commit (the snapshot machine) and syncing with a remote (the distributed part).

Recording a commit

[8]

Syncing with a remote

Key design decisions

Snapshots, not differences

The radical difference between Git and earlier version control systems is that instead of storing commits as deltas (changes made in comparison to previous version), Git stores commits as snapshots: exact state of changed files at commit time.[4]

This snapshot approach is robust: unlike in delta-based version control systems, corruption of a commit state would not propagate to all newer commits based on that commit.

What's more, this approach also renders large rollbacks trivial: rolling back to the state of any commit, even those from 5 years ago, consists of a simple object database query to pull up a particular snapshot, and not mathematically computing the desired state by reverting all new deltas from the latest state.

Nearly every operation is local

Another important difference between Git and earlier version-control systems is that most operations can be completed locally.

While most earlier systems rely on the central, authoritative "bookkeeping" server for almost every operation, Git is distributed. Each repository clone contains the entire Git history, which means most git operations, like browsing and diffing old versions, committing and branching all work instantly and offline. Syncing with a server is entirely optional. [4]

This distributed design made Git extremely suitable for large Opensource projects with thousands of contributors. The load on the central "bookkeeping" server is minimal: contributors call git clone to copy the repository to their local machine once, then everything happens locally on their machine, until they have arrived at something meaningful to be shared back with the entire community, at which point they call git push to sync back their changes to the central server.

Storage by hash value, not file name

Git stores everything in its database by the hash value of its contents, not file name.[4][8]

This design offers multiple benefits:

  • Guaranteed integrity: Any corruption to a file's content becomes immediately obvious to Git at retrieval time: the hash value simply would not match.
  • Safe indefinite caching: A cached version of any file never becomes silently stale. Git can instantly verify its freshness by comparing the hash value to the latest version.
  • Zero-cost file renaming: When user renames a file (e.g., from README to README.md), the hash value, which is calculated uniquely based on a file's content, stays constant. Therefore, no change is needed in Git's object storage when a file is renamed.

Branches are cheap pointers

A branch is not a copy of the Git tree nor a container of commits — it is just a thin ref, a 41-byte pointer to a commit. Therefore, creating and merging branches cost next-to-nothing, delivering the original design goal of "strong support for non-linear development (thousands of parallel branches)".[3][5][3]

A three-part staging model

By interposes the index (staging area) between the working tree and the repository, Git ensures that nothing is committed unless user explicitly requests it with git add. In addition to providing surgical precision for each commit, this design also discourages contributors from making odd-time commits just to "save work".[4]

Plumbing and porcelain

For small-scale projects with only a few contributors, manually managing Git history is quite doable. However, for large projects with thousands of contributors, manual Git history management can quickly become a full-time job, making scripting/advanced Git management tools highly desirable.

To satisfy both needs, Git exposes two sets of commands: a "porcelain" set of high-level commands designed to be directly called by human users, and a "plumbing" set of low-level commands exposing direct object storage, index, and ref manipulation, designed primarily for scripted use. The "plumbing" commands are deliberately stable across versions to ensure lasting compatibility of user scripts and tools.[3]

Git stores everything

Git is built within the 21st century context: storage is cheap; data loss is costly.

Once a Git commit is made, the commit-time project snapshot stays in the project's Git object storage forever. Even commands that rewrites Git history, such as amend, rebase, and reset do not erase them.[4]

Although the "store everything" approach inevitably introduces an storage overhead, the storage overhead's size is much smaller than the mathematical product of the number of commits and the repo's size, thanks to Git's backend performing aggressive compression and optimisation on its object storage. The data-integrity benefits outweigh the additional storage cost by far on any reasonably modern computer system.

Backward compatibility is broken only when strictly necessary

According to Git's official website: "the Git project aims to ensure backwards compatibility to the best extent possible. Minor releases will not break backwards compatibility unless there is a very strong reason to do so." But the project "irregularly releases breaking versions that deliberately break backwards compatibility", to stay "relevant, safe and maintainable going forward".

Two decades onward since Git's birth, there have only been two breaking changes : once in 2008 with Git 1.6.0, and once in 2014 with Git 2.0. The next one, Git 3.0, is planned for end of 2026.[6]

Try it yourself

Commands reproduced from Git's official documentation.[9]

Syntax of certain commands may be different on Windows.

# 1. Which version do you have?
git --version

Output (your version depends on your install):

git version 2.55.0
# 2. The very first commit of git.git, via the GitHub API
curl -s "https://api.github.com/repos/git/git/commits/e83c5163316f89bfbde7d9ab23ca2e25604af290" \
  | grep -E '"name"|"date"|"message"'

Output (liveness check performed 2026-09-01):

"name":"Linus Torvalds",
"date":"2005-04-07T22:13:13Z",
"name":"Linus Torvalds",
"date":"2005-04-07T22:13:13Z",
"message":"Initial revision of \"git\", the information manager from hell",
# 3. The latest feature release and its date, from the official website
curl -s https://git-scm.com/ | grep -oE "2\.55\.0|2026-06-29" | sort -u

Output (liveness check performed 2026-09-01):

2026-06-29
2.55.0
# 4. Git is a content-addressable store: hash some content, get back its key
echo 'test content' | git hash-object -w --stdin

Output:

d670460b4b4aece5915caf5c68d12f560a9fe3e4
# 5. Read the object back by its key
git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4

Output:

test content
# 6. Where did it go? Objects are stored under .git/objects, sharded by hash
find .git/objects -type f

Output:

.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
# 7. A real project: init, add, commit, log
mkdir demo && cd demo
git init

Output (path depends on where you run it):

Initialized empty Git repository in /tmp/demo/.git/
echo "Hello, Git!" > README.md
git add README.md
git commit -m "first commit"

Output (hashes and authorship vary):

[master (root-commit) 6f1d2a3] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
git log --oneline

Output:

6f1d2a3 (HEAD -> master) first commit
# 8. A commit object is just text: tree, author, committer, message
git cat-file -p HEAD

Output (hashes, identity and timestamps vary):[8]

tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700

First commit

References

  1. ↑ Torvalds, L. (n.d.). Git (Website).
  2. ↑ ↑ ↑ Torvalds, L. (2005). Initial revision of "git", the information manager from hell (Webpage). In GitHub · Change is constant. GitHub keeps you ahead. (Website).
  3. ↑ ↑ ↑ ↑ ↑ ↑ ↑ Torvalds, L. (n.d.). git - the stupid content tracker (Webpage). In Git (Website).
  4. ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Chacon, S. (2014). What is Git? (Webpage). In Git (Website).
  5. ↑ ↑ ↑ ↑ Chacon, S. (2014). A Short History of Git (Webpage). In Git (Website).
  6. ↑ ↑ ↑ Hamano, J. (n.d.). Git BreakingChanges Documentation (Webpage). In Git (Website).
  7. ↑ Hamano, J. (2020). Git 2.29 Release Notes (Webpage). In GitHub · Change is constant. GitHub keeps you ahead. (Website).
  8. ↑ ↑ ↑ Chacon, S. (2014). Git Objects (Webpage). In Git (Website).
  9. ↑ Chacon, S. (2014). Pro Git (Book). In Pro Git (Book) (p. 456). Apress.

Further reading