If you’re very 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 Git Basic Commands Explained article, which I recommend you read next.
The Three File States
Git works with the concept of three 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). And any new file that 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 the modified state. And 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 you run
$ git commit you must run
$ git add to stage any file, files or whole directories. When you add files, they pass from modified (or untracked) to staged (staging area). 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 add and before commit) those change is not in the staging area. In this 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 file resides only in your working directory (i.e. it doesn’t exist in the Git directory).
Modified file resides both in your working directory and your Git directory, but have different versions (i.e. the working directory version was changed) and the file was not sent to the stagging area (running
$ git add).
Staged file resides in your working directory, may or may not reside in the Git directory, was changed (if it exists in the Git directory) or was an untracked file, and was added to the staging area running
$ git add.
Committed file resides 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.
Well, that was a bit complex and pretty much theoretical explanation. Don’t worry if things seem a little confusing right now. It’ll make much more sense when we start playing with the commands in practice, which is the subject of Git Basic Commands Explained article, which I recommend you read next.
Chacon, Scott. Pro Git. Apress, 2009.