Git — Basic Principles Four, Working Directory and Staging Area
DevOps useful Git operation tips

Git Working Directory
Git working directory is the directory on your local filesystem where your project files are located. It contains all the files and folders in your project, including those that are tracked by Git and those that are not.
When you make changes to your files, create new files, or delete files, you’re doing so in the working directory. The working directory represents the current state of your project files, which may not yet be committed to the Git repository.
The working directory is important because it allows you to make changes, test your code, and experiment with new features without immediately affecting the committed history in your repository. Once you’re satisfied with your changes, you can stage them (add them to the staging area) and then commit them to the repository, creating a new snapshot of your project’s history.
Git Staging Area
Git’s staging area, also known as the index or cache, is an intermediate area that stores changes to tracked files before they are committed to the repository. It serves as a way to organize and review the changes you have made to your project before creating a new commit.
Git’s staging area, also known as the index or cache, is an intermediate area that stores changes to tracked files before they are committed to the repository. It serves as a way to organize and review the changes you have made to your project before creating a new commit.
The staging area allows you to:
- Selectively add changes: You can choose specific changes in your working directory to be staged for the next commit, allowing you to create focused and well-organized commits.
- Review changes: Before committing, you can review the changes in the staging area to ensure they are correct and complete.
- Modify staged changes: If you find that you need to make additional changes to a staged file, you can modify the file in the working directory and stage it again to update the staged version.
- Split changes into multiple commits: If you have made several changes to your project, you can stage and commit them separately, which helps maintain a clean and understandable commit history.
The process of using the staging area typically involves the following steps:
- Make changes to files in the working directory.
- Stage the changes using
git add <file>orgit add -p(for interactive staging of specific changes). - Review the staged changes using
git statusorgit diff --staged. - If satisfied with the changes, commit them using
git commit -m "Commit message". This creates a new commit in the repository with the changes from the staging area.
Git Working Directory to Staging Process Flow

From the above diagram, we can see that
- The developer makes changes to files in the working directory.
- The developer uses
git add <files>to stage the modified files, moving them to the staging area. - The developer uses
git commit -m "Commit message"to commit the staged files to the repository. - The developer uses
git checkout -- <files>to discard changes in the working directory, if needed. - The developer uses
git restore --staged <files>to unstage files and move them back to the working directory, if needed.
Git index file
The .git/index is a binary file located inside the .git directory of your Git repository. It represents the Git index (also known as the staging area or cache) and stores information about the files and their states that will be included in the next commit.
The .git/index file is an internal data structure used by Git to track the differences between the working directory and the repository, helping you manage changes to your project files more effectively. It plays a crucial role in Git's workflow, as it helps stage specific changes, review staged changes, modify staged changes, and split changes into multiple commits.
If you directly open .git/index file, you will see the following:
$ cat .git/index
DIRCdK��20]dK��20]����������L�0U��������D�test.txtdK��+��WdK��+��W����������L�0U��������D�� test2.txt��]"�[�Fv���әHowever, you can use git ls-files command to check:
$ git ls-files -s
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0 test.txt
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0 test2.txtThe “git ls-files” command is used to list all the files that are currently being tracked by Git in the repository. This command displays the names of all the files in the repository, including those that are in the working directory, staging area, and committed to the Git repository.
How Does Git Know File Changed
Git uses a combination of methods to detect changes in files and determine which files need to be staged and committed to the repository. Here are a few of the key mechanisms that Git uses to detect changes:
- Timestamps: Git tracks the modification time of each file in the working directory. When you modify a file, its timestamp changes, and Git can use this information to detect that the file has been changed.
- Content Hashing: Git calculates a hash value for the contents of each file in the working directory. When you modify a file, its hash value changes, and Git can use this information to detect that the file has been changed.
When you run the “git status” command, Git compares the current state of the working directory with the state of the repository’s staging area and committed history to determine which files have been modified, added, or deleted. This information is then displayed in the output of the “git status” command, allowing you to see which files are ready to be committed to the repository.
For example, let’s say we have two files: file1.txt and file2.txt :
$ git ls-files -s
100644 a5bce3fd2565d8f458555a0c6f42d0504a848bd5 0 file1.txt
100644 180cf8328022becee9aaa2577a8f84ea2b9f3827 0 file2.txt
$ tree .git/objects/
.git/objects/
├── 18
│ └── 0cf8328022becee9aaa2577a8f84ea2b9f3827
├── a5
│ └── bce3fd2565d8f458555a0c6f42d0504a848bd5
├── info
└── pack
4 directories, 2 filesNow let’s make some changes to file1.txt :
$ echo "new test" > file1.txt
$ $ git ls-files -s
100644 efbee594d27c2e2cfc9dcea464acc9904bc34a4d 0 file1.txt
100644 180cf8328022becee9aaa2577a8f84ea2b9f3827 0 file2.txtNow you can see file1.txt hash has changed, as well as the objects folder:
$ tree .git/objects/ .git/objects/ ├── 18 │ └── 0cf8328022becee9aaa2577a8f84ea2b9f3827 ├── a5 │ └── bce3fd2565d8f458555a0c6f42d0504a848bd5 ├── ef │ └── bee594d27c2e2cfc9dcea464acc9904bc34a4d ├── info └── pack
Now we have tree objects, a5/ and ef/ belongs to file1.txt and 18/ belongs to file2.txt .






