🌐
Git
git-scm.com › docs › git-status
Git - git-status Documentation
See configuration variable column.status for option syntax. --column and --no-column without options are equivalent to always and never respectively. ... Display or do not display detailed ahead/behind counts for the branch relative to its upstream branch. Defaults to true. ... Turn on/off rename detection regardless of user configuration. See also git-diff[1] --no-renames.
🌐
GitHub
github.com › git-guides › git-status
Git Guides - git status · GitHub
The git status command only outputs information, it won't modify commits or changes in your local repository.
🌐
GitHub
githubstatus.com
GitHub Status
Resolved - On July 13, 2026, between 13:11 and 13:53 UTC, some customers experienced failures starting and running GitHub Actions workflows, which also affected Copilot cloud agent sessions and GitHub Pages builds since they depend on Actions. During the peak of the incident, 30% of Actions jobs failed to start and 2% were delayed more than 5 minutes.
🌐
CloudBees
cloudbees.com › blog › git-status-in-depth
Git Status in Depth: Understanding Your File States
November 1, 2021 - When you run the status command, your project files at any point in time can be in one of three states: untracked, no-history, or modified. Let’s see what each state means, and walk through some examples. Let’s begin by creating three empty text files inside our project. ... The letter on the right side of the filename represents the name of the state each file is in. In this case, we have an uppercase U for each file. ... $ git statusOn branch masterNo commits yetUntracked files: (use "git add <file>..." to include in what will be committed) file1.txt file2.txt file3.txtnothing added to commit but untracked files present (use "git add" to track)
🌐
Atlassian
atlassian.com › git › tutorials › inspecting a repository
Git Status: Inspecting a repository | Atlassian Git Tutorial
December 15, 2025 - The git status command displays the state of the working directory and the staging area. It lets you see which changes have been staged, which haven’t, and which files aren’t being tracked by Git.
🌐
GeeksforGeeks
geeksforgeeks.org › git › git-status
Git Status - GeeksforGeeks
March 14, 2026 - Now, It is showing changes to be committed which means the file is now included and ready to commit. We can commit files using the git commit -m "message" command. ... After committing, the status is now changed to nothing to commit because now the working tree is clean.
🌐
Linux Kernel
kernel.org › pub › software › scm › git › docs › git-status.html
git-status(1) Manual Page
See configuration variable column.status for option syntax. --column and --no-column without options are equivalent to always and never respectively. ... Display or do not display detailed ahead/behind counts for the branch relative to its upstream branch. Defaults to true. ... Turn on/off rename detection regardless of user configuration. See also git-diff(1) --no-renames.
🌐
Git Tower
git-tower.com › learn › git faq › how to use git status in git (with examples)
How to Use git status in Git (with Examples) | Learn Version Control with Git
3 days ago - git status shows the current state of your working copy — which files have changed, which are staged for the next commit, and whether your branch is in sync with its remote counterpart.
Find elsewhere
🌐
TheServerSide
theserverside.com › blog › Coffee-Talk-Java-News-Stories-and-Opinions › How-to-master-the-Git-status-command
How to master the Git status command
If a file is edited the status reported will be modified: $ echo "Hello World" >> index.html $ git status On branch feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a")
🌐
DataCamp
datacamp.com › tutorial › git-status
Git Status: How To Track Changes in Your Project with Confidence | DataCamp
April 1, 2025 - The git status command provides a real-time summary of the state of your Git repository. Specifically, it compares the working directory (your local files) and the staging area (also known as the index) with the last committed snapshot.
🌐
Initial Commit
initialcommit.com › blog › git-status
Git Status Command | Uses, Applications & Related Commands
April 5, 2022 - The git status command provides useful information about the current state of your Git repository. It outputs the active branch, remote sync status, and a list of modified files in the working directory and staging area.
🌐
GitHowTo
githowto.com › checking_status
3. Checking the status of the repository
Learn how to check the repository’s status. Use the git status command, to check the current state of the repository.
🌐
Educative
educative.io › answers › what-is-the-git-status--u-command-in-git
What is the git status -u command in Git?
The git status command is used to display the current status of the local repository.
🌐
GitHub
github.com › romkatv › gitstatus
GitHub - romkatv/gitstatus: Git status for Bash and Zsh prompt · GitHub
This will give you a basic yet functional prompt with git status in it. It's over 10x faster than any alternative that can give you comparable prompt. In order to customize it, set PROMPT and/or RPROMPT at the end of ~/.zshrc after sourcing gitstatus.prompt.zsh.
Starred by 1.8K users
Forked by 128 users
Languages   C++ 59.3% | Shell 40.1% | Makefile 0.6%
🌐
Gitbybit
gitbybit.com › gitopedia › git-commands › git-status
Gitopedia: git status — view working tree status
The git status command is used to display the current state of your Git repository. It shows which files have been modified, which files are staged for commit, and which files are not being tracked by Git.
🌐
TOOLSQA
toolsqa.com › git › git-status-command-in-git
What is Git Status Command in Git?
July 7, 2021 - Git status command is used in Git to know the status of the working tree. It shows the state of your working directory and helps you see all the files which are untracked by Git, staged, or unstaged.
🌐
Tim Mousk
timmousk.com › blog › git-status
How Does The Git Status Command Work? – Tim Mouskhelichvili
March 12, 2023 - In some rare instances, git may not recognize your changes... In that case, typing the git status command will show that you have no changes.
🌐
CodingNomads
codingnomads.com › git-status
Git Status
The `git status` command prints the status of a repository, so you can check on your files between your working directory, and your local / remote repo.
🌐
Graphite
graphite.com › guides › git-status
How to use the `git status` command - Graphite
git status provides detailed information about the working directory (where your code is stored on your local machine) and the index (the staging area where your changes live before being pushed to a remote repository).
Top answer
1 of 2
28

The answer is bit too long and will take a while to write so here is the summary.

The short answer is that git uses the SHA-1 to check track changes but the name of the file is stored somewhere else.


The content is stored in a pack (*1- read below) while the names are stored in a idx.
When you run git status, git check to see if already have this path in the idx file (metadata) and based upon the result it decide if it's a new file or not.

If it's not a new file, git comparing the SHA-1 to track changes.


Why do I have to use git mv to move files and not a simple mv?

When you execute git status git search your working directory looking for a match between the "registered" paths in the idx file and your working directory.

When you move a file with mv your working directory does not have the "original" path stored by git, and since git can't find the "registered" path anymore, the file is marked as deleted.

But on the same time git see a new file, the new path you just the moved the file to, so the new file will be marked as a new file.

On the other hand, when using git mv, git updates the metadata to point to the new name and the content will be marked as rename. In this case git updates the registered path of the file in the idx file.
If you move and update it will be marked as rename + modified as well.


How can I find out what is the SHA-1 of a file?

Use the git ls-tree internal command to find out what is the SHA-1 of your files.


Note

Git starts to track content when you just add it to the staging area.
Once the file is added git store the following information in the file

[blob][1 white space][content length][null][content]

If you have a file with the string `hello` it will look like this:
blob 5\0Hello

Now git calculate the SHA-1 of this file (using sha1sumn) compress it with z-lib and save the file with this SHA-1 as the name nuder the `.git/objects'.

When git packs the repository it will go into the pack file.

How can I view the content of the file?

Since the file is compressed with z-lib we have several options to get the content:

  • First option is to view the zipped stored in the file
  • Second is to view the unzipped content (as explained above)
  • See the content of the file only without any git metadata.

And to show that git actually use the content as described above here is the same command as git executes behind the scenes to calculate the SHA-1


This is the illustration of a commit and how it handles file names.

(http://shafiulazam.com/gitbook/1_the_git_object_model.html)

2 of 2
19

CodeWizard's answer is wrong in a few important details, as Edward Thomson noted in a comment.

The super-short version is that git status runs git diff.

In fact, it runs it twice, or more precisely, it runs two different internal variations on git diff: one to compare HEAD to the index/staging-area, and one to compare the staging-area to the work-tree. It runs each diff with a request to search for renames, i.e., sets the -M flag (see below). Finally, it presents the results from these diffs to you in whichever format you requested. In no case does it show the actual changes between files, though (so in effect it runs these diffs with --name-status as well).

Using the various diffs

You can run both of these internal diffs manually: one has a front-end command spelled git diff-index --cached, and one has a front-end command spelled git diff-files. This front-end selection is captured in the slightly oddly placed section titled Raw output format (I have had to modify this a bit to display better on StackOverflow):

The raw output format from git-diff-index, git-diff-tree, git-diff-files and git diff --raw are very similar.

These commands all compare two sets of things; what is compared differs:

git-diff-index tree-ish
      compares the tree-ish and the files on the filesystem.

git-diff-index --cached tree-ish
      compares the tree-ish and the index.

git-diff-tree [-r] tree-ish-1 tree-ish-2 [pattern ...]
      compares the trees named by the two arguments.

git-diff-files [pattern ...]
      compares the index and the files on the filesystem.

(You can invoke these with regular git diff as well: git diff --cached compares the current (HEAD) commit to the staging-area, and git diff with no additional arguments compares the staging-area to the work-tree.)

Mapping trees back to paths

CodeWizard's answer has the keys to this process. Essentially, a tree object contains the path-name component (such as the foo or bar in foo/bar) and another object ID. If the component represents a directory, the object ID locates another tree object; if it represents a file, the object ID locates a blob object. In either case the ID is Git's internal name, which enables Git to find it in the repository.

(This is not true for the index/staging-area itself, whose format is not very well documented. It is a flat list of all files, with full path names but using a name compression technique as well, so that VeryLongDirectory/AnotherLongDirectory/bar followed by VeryLongDirectory/AnotherLongDirectory/baz does not have to spell out VeryLongDirectory/AnotherLongDirectory each time.)

(Tree objects also store the mode that Git should assign to the file, upon extraction, except that in the tree object, each file mode is only ever 100644 or 100755; the final rwx bits are set based on your umask, assuming a Unix-like host, with x being always-clear if the stored mode is 100644, otherwise set-except-as-cleared-by-umask.)

Unstaged files and detecting renames

How does git internally know if a file has been deleted, added, or edited (specifically, how does it compute the changes you see when you type git status)?

A file that is in the work-tree, but is neither in the HEAD commit nor in the index/staging-area is unstaged (this is in fact the definition of "unstaged"). Git finds such files by looking at all three (and using the index/staging-area for cache information to speed up the process). All the unstaged file paths are generally fed to the "ignore" code, which makes git shut up about them if they are listed in .gitignore or any of the other ignore-some-paths files.

Having dispensed with unstaged paths, let's consider the remaining paths, which (by definition) appear in at least one of HEAD or the index/staging-area.

In general—there are more flags for controlling this in finer detail, although git status does not set any of them—Git first compares the path names available in the "A" side (a/foo/bar) to those in the "B" side (b/foo/bar). If the same path appears in both sides, chances are that the file was simply modified in place, and Git starts with that assumption. If a path appears in A but not in B, and some other path appears in B but not in A, the two paths are paired up and given to to the rename detector (if it is enabled).

All the internal diffs share a bunch of code, and also share the documentation. Click on one of the above links and search for -M or --find-renames:

-M[n] --find-renames[=n]

Detect renames. If n is specified, it is a threshold on the similarity index (i.e. amount of addition/deletions compared to the file’s size). For example, -M90% means Git should consider a delete/add pair to be a rename if more than 90% of the file hasn’t changed. Without a % sign, the number is to be read as a fraction, with a decimal point before it. I.e., -M5 becomes 0.5, and is thus the same as -M50%. Similarly, -M05 is the same as -M5%. To limit detection to exact renames, use -M100%. The default similarity index is 50%.

The rename-detector can be enabled by default by setting diff.renameLimit to 0 in your configuration. Otherwise, it is currently disabled by default, but will be enabled by default in an upcoming Git release (I am not sure which one).

For further detail on the similarity matching, see this answer from Edward Thomson.

Once the rename detector decides that some A-to-B change is a rename, it pulls both names out of the "only in A" and "only in B" lists.

Added and deleted

After running the rename detector (if enabled), any files that are found only on the A side are "deleted", and any found only on the B side are "added". For git status, this concludes the whole process (except for displaying the results). For regular git diff we usually go on to produce actual diff output, when some file is modified or renamed-and-modified.

(Note that all of Git's diffs share all of this machinery, so they will all find the same set of renames, provided you turn on rename detection and set the same thresholds. These are also used during git merge.)

Side note: renames are detected, not recorded

Many other version control systems (Mercurial, ClearCase, Perforce) require that you register a file-rename with them: hg mv and so on. This is because they record the rename with each commit. A system that does this necessarily gives each file some kind of identifier (this could be a true object ID as in ClearCase, or simply "its name in the current commit", which is then munged as needed as we move from commit to commit). The advantage to this system is that the VCS can follow the file no matter how changed it gets. A disadvantage is that you must record the change, and a file that is accidentally deleted, then resurrected, can get a new ID (see ClearCase "evil twins").

Git simply re-discovers the rename, every time it goes to compare one commit to another (or a commit to the index, or the index to the work-tree, etc). This means you do not have to use git mv: you can git rm --cached the old path and git add the new one, to get the same effect. (You can, of course, use git mv whenever it is more convenient, which is most of the time. But this is a significant difference from version control systems that record, with each check-in or commit, directory modifications: with these systems you must invoke the VCS-specific mv command, such as hg mv or cleartool mv, to inform the VCS that the file moved, rather than letting the VCS figure it out later.)