If you’re new to Git don’t try to run the commands showed in this article, they have missing parameters. This article was written to be a conceptual explanation about the Git workflow. Playing with its commands to better understand its concepts is the subject of the next article: Git Basic Commands Explained, which I recommend you read next.
The Three File States
Git works with the concept of three different file states: committed, modified and staged (Chacon 8). Each state relates to a specific Git section: working directory, staging area and Git directory (repository) (Chacon 8). Additionally, any new file you add to the working directory is an untracked file, which means the file doesn’t exist in the repository.
When you create a new repository from scratch running
$ git init in an empty directory, your working directory (the physical directory that the files reside on your local machine) is empty. And if you
$ git clone some remote repository, your working directory is fully synchronized with the Git directory (repository). Thereafter, any changes you make on any file automatically puts it in a modified state. If you add new files, those will be untracked. At this time (with modified and/or untracked files), trying to run
$ git commit to send files from the working directory to the local repository (Git directory) will have no effect. Git only send files that are in the staged state, which conceptually resides in the staging area, to the repository. So, before running
$ git commit you must run
$ git add to stage files and directories. When you add files, they go from modified (or untracked) state to staged (staging area) state. After that, running
$ git commit will change the state of the files from staged to committed, leaving the staging area and going to the Git directory (repository). Each
$ git commit represents a snapshot of the project.
When you run
$ git add, Git sends a snapshot of the file to the staging area, not a reference of the file itself, which means if you change that file again after adding and before commiting, that change is not in the staging area. In such case you need to run
$ git add again for that same file. This is an important detail and illustrates how Git works with the snapshot concept.
Working directory is your local physical directory, where you make changes to your files.
Staging area is a place where Git keeps a reference of all modifications (snapshot of files) to be sent in the next commit.
Git directory is the repository, the Git database which stores all files in a compressed form.
Untracked files reside only in your working directory (i.e. they don’t exist in the Git directory).
Modified files reside both in your working directory and your Git directory, but they have different versions, i.e., the working directory files were changed, but those changes weren’t sent to the stagging area by running
$ git add.
Staged files reside in your working directory, and a) reside in the Git directory if they are existing files being changed, or b) do not reside in the Git directory if they are new files being added to the repository for the first time.
Committed files reside both in your working directory and Git directory with the exact same version.
You can run
$ git status at any time to check the state of your files.
Phew! That was a bit complex, and a pretty much theoretical explanation. Don’t worry if things seem a little confusing right now. It’ll make a lot more sense once we start playing with the commands in practice, which is the subject of the next Git article: Git Basic Commands Explained, which I recommend you read next.
Chacon, Scott. Pro Git. Apress, 2009.