Every commit in Git gets a name you never picked. It shows up in the terminal right after you commit, a short run of hex digits like 346ca09, and most people copy it without wondering where it came from.
Git works that name out from the commit’s tree, its parents, the author, the committer and the message. Change any of them and the name changes too, so one hash points to one exact repository state.
It goes into git checkout, cherry-pick and revert commands, and from there into code review threads and CI logs.
Most guides describe a plain 40-character SHA-1 string, which is only half true now. Since Git 2.13.0 (GitHub Blog, 2017), the SHA-1 behind it is a collision-detecting variant that rejects objects showing signs of an attack. Repositories can also opt into SHA-256 instead.
What Is a Commit Hash?

Git gets the hash by running a function over the commit’s tree, parent commits, author, committer and message. The output identifies one exact repository state, and a change to any input produces a different value.
It points at a snapshot of the whole project at that moment, not at one file’s change.
You will hear it called a commit ID, which is just the everyday shorthand. SHA or commit SHA comes from the SHA-1 algorithm underneath. Git itself says object ID, since the same hashing covers every object it stores, commits included.
GitHub’s documentation describes the hash as the ID that identifies the specific changes, when they were made and who made them (GitHub Docs).
Here is a pair taken from the GitByBit Gitopedia entry. The full hash is 346ca091076783c70623aba03fb7139d3d27134f and the short hash is 346ca09. The short form works as a reference only while the prefix is unique in the repository.
Commit hashes carry no order. Most centralized version control systems count revisions upward, but Git has no central counter and names commits by content, so consecutive commits get unrelated hashes.
Each time a developer creates a commit, Git writes a new commit object and prints its abbreviated hash in the confirmation line.
How Does Git Calculate a Commit Hash?

Git runs SHA-1 over the commit object, which is a short header followed by the commit’s content. The 40-character result becomes the commit’s name.
Repositories created with the SHA-256 object format hash the same content with SHA-256 instead.
What goes into the hash
The git-commit-tree documentation spells out what a commit holds. The tree is the hash of the root tree object, a snapshot of every file and directory. Parents are the hashes of the previous commits (none for the first commit, two or more for a merge). Author and committer each carry a name, email and timestamp, one for the person who wrote the change and one for the person who recorded it. Then there’s the message, which is just the commit log text.
Because the parent hashes sit inside the content, every commit hash depends on the whole chain behind it.
Rewrite one old commit and every descendant gets a new hash.
Where Git stores the commit object
Pro Git documents the layout. The first 2 characters of the hash name a subdirectory under .git/objects, and the remaining 38 characters name the file inside it.
Splitting on the first 2 characters keeps any single directory small. In Pro Git’s example, the text “test content” lands at .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4.
These loose objects sit in the object database inside every Git repository. Git later bundles them into packfiles, and a commit is still found by its hash.
Reproducing a commit hash by hand
Hashing the commit text yourself shows that the hash is computed, not assigned.
- Print the raw commit object with
git cat-file -p HEAD. - Hash that text as a commit with
git cat-file -p HEAD | git hash-object -t commit --stdin. - Print the stored name with
git rev-parse HEAD. - Compare the two values. They match.
The hash-object command adds the header before hashing. It writes the word commit, then the content length in bytes, then a nul byte. The git-scm hash-function-transition document describes the same recipe for object names.
How Long Is a Commit Hash, and What Is a Short Hash?

In a SHA-1 repository the full hash runs 40 hexadecimal characters, and in a SHA-256 repository it runs 64. A short hash is a prefix of that string, kept long enough to stay unique in the repository.
The SHA-1 name is 40 hex characters, or 20 bytes, and the SHA-256 name is 64 hex characters, or 32 bytes (git-scm hash-function-transition). The historical short-hash default was 7 hex digits. Auto-sized examples run to 12 digits for the Linux kernel and 9 to 10 for Git itself (Git 2.11 release notes). The smallest value core.abbrev accepts is 4 (git-config documentation).
Seven digits looked generous in Git’s early days because they cover 268,435,456 values (167), which git/git commit dce9648 describes as more than 250 million.
Projects grew, and short names recorded in log messages stopped being unique. The commit that introduced auto-sizing reports that the Linux kernel needs 11 to 12 digits and Git itself 10.
Since Git 2.11 the default length scales with the estimated object count, and each extra hex digit allows four times as many objects. The release notes round the recommendation to 12 digits for the kernel and 9 to 10 for Git, so treat the figures as estimates, not guarantees.
A prefix that matches two objects is ambiguous. Git rejects it with an “ambiguous argument” error and, since 2.11, lists the conflicting objects (Git 2.11 release notes).
Quote the full hash in release notes, bug reports and CI logs, where a reference has to resolve years later.
Use the short form in chat and terminals. For a large repository that records short hashes in documentation, pin a longer length through Git configuration with git config --global core.abbrev 12, which accepts auto, no, or a number from 4 up to the full hash length.
How to Find a Commit Hash and Use It

For the full hash of the current commit, run git rev-parse HEAD. For recent commits with their abbreviated hashes, git log --oneline does the job. Hosting sites show the same value beside every commit, with a button that copies the full string.
Finding a hash in the terminal
git rev-parse HEADresolves the HEAD reference to a full hash.git rev-parse maindoes the same for a branch or tag name, and adding--shorttrims the output.git log --onelineprints one line per commit, hash first, then the subject.- For a single commit in detail,
git show <hash>prints the metadata and the diff.
Plain git log prints each full hash with author, date and message, which helps when the one-line view is too terse to recognize the commit.
Finding a hash on GitHub and GitLab

The commit list shows the abbreviated hash, and the copy button beside it hands you the full one.
GitHub’s compare view accepts hashes directly. The GitHub Docs example compares two commits with compare/f75c570..3391dcc, and 96d29b7~5...96d29b7 compares a commit with the one five commits before it.
Link to a hash, not a branch name, when the reference has to stay put. A branch URL shows different code after the next push, while a hash URL always shows the same commit.
Commands that take a commit hash
Only cherry-pick and revert create a commit with a new hash. The rest read from a commit or move a pointer to it.
| Command | Role of the hash | Effect on hashes |
|---|---|---|
| git checkout <hash> | Moves HEAD to that commit | None |
| git cherry-pick <hash> | Copies that commit onto the current branch | The copy gets a new hash |
| git revert <hash> | Adds a commit that undoes that commit | One new commit, original untouched |
| git reset <hash> | Points the current branch at that commit | None, only the branch pointer moves |
| git blame | Names the commit that last touched each line | None, read only |
Git bisect takes one good hash and one bad hash, then checks out commits in between until it finds the first bad one.
Check out a hash and HEAD becomes detached. Commits made there belong to no branch until you create one with git switch -c.
Why Does a Commit Hash Change After Amend, Rebase or Cherry-Pick?
Commits are immutable, so anything that looks like an edit actually builds a replacement commit with its own hash. The original stays in the object database, untouched, until garbage collection removes it.
Alembic’s walkthrough makes the same point: amend and rebase replace a commit and never delete it. GitLab’s documentation says a rebase rewrites the commit history, which is why every replayed commit gets a new parent and a new hash.
| Operation | New hash? | What happens to the old commit |
|---|---|---|
| git commit –amend | Yes, for the tip commit | Stays in the object database |
| git rebase | Yes, for every replayed commit | Stays until pruned |
| git cherry-pick | Yes, for the copy | Original stays on its own branch |
| Fast-forward merge | No | Nothing replaced, the branch pointer moves |
| Branch or tag creation | No | Nothing replaced, a new name points at the same hash |
Recovering a commit after its hash changes
- Run
git reflogto list where HEAD pointed before each move. - Find the entry from before the amend or rebase and copy its hash.
- Return to it with
git reset --hard <hash>, or keep both histories withgit branch rescue <hash>.
Alembic notes that knowing the old hash makes it easy to undo almost any command with git reset and the hard option. That option also discards uncommitted work, so commit or stash first.
The git-gc documentation sets reflog entries to expire after 90 days by default, and entries no longer reachable from the branch tip after 30 days.
A replaced commit is exactly that kind of unreachable entry, so the practical window after an amend or rebase is 30 days, not 90. Unreachable loose objects are pruned after 2 weeks when git gc runs, but a commit still named in the reflog survives that pruning.
One catch. The reflog lives in your clone only. After a rebased branch is pushed, teammates still hold the old hashes, and the remote rejects a plain push until you force it.
Can Two Commits Share a Hash?

In principle, yes. SHA-1 squeezes unlimited input into 160 bits, and researchers have produced two different files with the same SHA-1 hash. In practice Git detects the known attack pattern, so a commit hash is unique by engineering margin, not by proof.
What SHAttered changed for Git
Producing the first SHA-1 collision took about 6,500 CPU-years and 110 GPU-years of computation (Google and CWI Amsterdam, shattered.io, 2017).
The researchers described the attack as more than 100,000 times faster than a brute-force search, so the cryptanalytic shortcut mattered more than the raw compute.
Git 2.13.0 (May 2017) made the collision-detecting SHA-1 the default and rejects objects that show signs of an attack, per the GitHub Blog. GitHub.com had started using the same detection code in March 2017.
The detector implements the counter-cryptanalysis method of Marc Stevens, who also co-authored SHAttered. According to the sha1collisiondetection README, it takes less than twice as long as regular SHA-1.
The guarantee has a defined scope, though. The detector covers attacks built on the 32 most likely disturbance vectors (git/sha1collisiondetection README). Git’s transition document says that Git 2.13.0 and later use a hardened SHA-1 that isn’t vulnerable to the SHAttered attack, but it still calls SHA-1 weak and treats a move to a stronger hash as prudent.
SHA-256 commit hashes today

Git creates a SHA-256 repository on request with git init --object-format=sha256, and every commit hash in it has 64 hex characters. Support started as experimental in Git 2.29 (October 2020), according to DeployHQ’s Git 3.0 overview.
| Attribute | SHA-1 repository | SHA-256 repository |
|---|---|---|
| Default for new repositories (Git 2.56, September 2026) | Yes | No, opt-in |
| Git 3.0 plan | Stays supported, not deprecated | Planned default |
| Older Git versions | Can read it | Cannot read it |
| Fetch and push across formats | Limited | Limited |
| Created with | git init | git init –object-format=sha256 |
Git’s breaking-changes document plans the SHA-256 default for Git 3.0 and states there is no plan to deprecate the SHA-1 format. As of Git 2.56 (released September 28, 2026), that document still lists no planned release date for Git 3.0, and new repositories still default to SHA-1.
Sources disagree on interoperability. The hash-function-transition document lists communication between SHA-256 repositories and SHA-1 servers as a goal, while a mid-2026 DEV Community overview describes interoperability between the two formats as still limited.
Any build pipeline that stores or validates commit hashes needs a 64-character column or pattern before repositories switch. A 40-character field rejects or truncates the longer value.
Commit Hash FAQ
Can a commit hash be reversed to recover the commit?
No. Hashing is one-way, so no practical method recovers a commit’s content from its hash.
The hash only locates the object. You read the content from the repository with git cat-file -p <hash>.
Are commit hashes the same in every clone and fork?
Yes. A hash depends only on commit content, so a clone and a fork hold each commit under the same hash.
The copies diverge only when someone rewrites history, because an amend or rebase in one copy creates new hashes there.
Why do some short hashes contain only digits?
Each hex character is one of 16 symbols, and 10 of them are digits. A 7-character prefix is all digits with a probability of about 3.7 percent, or roughly 1 in 27.
All-digit short hashes are ordinary and carry no meaning.
How is a commit hash different from a tag?
A tag is a readable name that points at a commit hash, while the hash is the content-derived name itself.
A lightweight tag is only a pointer. An annotated Git tag is a separate object with its own hash.
Does a commit hash prove who wrote the commit?
No. The hash fingerprints the commit, author field included, but anyone can set that field to any name and email.
Git reads author details from configuration or environment variables, so only a signed commit proves authorship.
Which command puts a commit hash into a build version string?
Run git rev-parse --short HEAD in the build script and append the output to the version.
Semantic versioning allows this as build metadata after a plus sign, for example 1.4.2+346ca09. The command git describe --always returns a tag-plus-hash string such as v2.9.3-599-g2376d31787.
Which Commit Hash Should Release Notes Record?
Release notes, bug reports and CI logs should record the full commit hash of a commit already merged to a shared branch, because later work on that branch does not change it.
A hash copied from a feature branch before a rebase names a commit the shared branch never receives.
Merge to the shared branch first and copy the full hash from there. Then tag the commit and push the tag.
The tag costs one more ref to maintain, because git push does not send tags unless told to. In return, the tag keeps the commit reachable, so garbage collection leaves it alone.
As of Git 2.56 (September 28, 2026), new repositories still default to SHA-1. Git’s transition document specifies a stored mapping between SHA-1 and SHA-256 names, so references written today keep resolving after a repository changes object format.
A recorded hash is also the argument you pass when you need to revert a commit in Git.
- Notepad++ Android Options: Apps That Come Close - October 21, 2026
- MongoDB Cheat Sheet - October 20, 2026
- Adding AI Video Generation to a Software Product: Architecture, Cost Guardrails and QA - October 20, 2026




