22
I think we can better understand these states by creating a project from scratch. First I will create a folder called "project" and enter it:
$ mkdir projeto
$ cd projeto/
For now it is empty. I will use git init
to boot it as a Git repository:
$ git init
Initialized empty Git repository in C:/Users/usuario/projeto/.git/
Now I will start my project by adding a file (with "hello world" content inside it), and then check the status of this file with git status
:
$ echo "hello world" > hello.txt
$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.txt
nothing added to commit but untracked files present (use "git add" to track)
See that file hello.txt
is listed as "Untracked files". Meaning, Git is not "trackeando" this file. We can say that Git is not controlling the life cycle of this file (and I confess that I don’t know if "life cycle" is the technically correct term).
It’s like Git said: "I saw that there’s a file here, but I’m not responsible for it".
For Git to be responsible for the file, use git add
:
$ git add hello.txt
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.txt
Now the file is listed as "Changes to be Committed", that is, he will be part of the next commit. It is then said that the file is "staged" (or is in staging area, or in the index, or in the cache, I don’t know why so many names for the same thing).
Anyway, note that there is even an instruction to remove the file from the staging area (use "git rm --cached ..." to unstage).
Instead of unstagear the file, let’s go commit him (I love these foreign...)
$ git commit -m"Primeiro commit"
[master (root-commit) ccc2a05] Primeiro commit
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
$ git status
On branch master
nothing to commit, working tree clean
After the commit, the git status
says there’s nothing to show ("Nothing to commit, Working Tree clean"), that is, all files are updated: their content matches the last commit, there was no change). It can be said then that the file hello.txt
is unmodified (there are no modifications, if compared to the last commit).
So let’s change the file by adding some text to its end:
$ echo "Novo texto" >> hello.txt
$ cat hello.txt
hello world
Novo texto
Now the file has 2 lines, let’s see what the git status
showcase:
$ git status
On branch master
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: hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
It shows that the file is modified, that is, it was modified, if compared to the last commit. But note that this modification will not be in the next commit, because the file is listed as "Changes not staged for commit" and at the end still appears the message "no changes Added to commit".
I can see the modifications using git diff
:
$ git diff
diff --git a/hello.txt b/hello.txt
index 3b18e51..7d34649 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
hello world
+Novo texto
The excerpt +Novo texto
indicates that this line has been added (+
). For the change to become available in the next commit, just use git add
:
$ git add hello.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: hello.txt
Note that the file continues with status "modified" (after all, he’s different from the last commit), but now you’ll be in the next commit ("Changes to be Committed").
I mean, he’s at the same time modified (different compared to the last commit) and staged (for it is in staging area).
The fact that you’re in staging area causes git diff
don’t show the differences anymore:
$ git diff
(não mostra nada)
To know what has changed, you must use the option --cached
, that compares the staging area (also called cache) with the last commit:
$ git diff --cached
diff --git a/hello.txt b/hello.txt
index 3b18e51..7d34649 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
hello world
+Novo texto
By the way, --cached
is equivalent to --staged
- that is, compare the files that are staged with the last commit.
In short:
- untracked: git doesn’t know anything about the file. I mean, it even knows it exists, but it won’t control its life cycle
- staged: those in the staging area/index/cache. They’re the ones on the next commit
- modified: those that have been amended, if compared to the last commit
- unmodified: those that have not been changed
Finally, it is worth remembering that the documentation says there are actually only two states: tracked and untracked. That is, or Git is controlling the life cycle of your file (tracked) or is not (untracked). Being that a file in the state tracked may be staged, modified or unmodified.
Very good! Excellent!
– rbz
@Thank you very much! I forgot to mention that I used git 2.11.0 for windows, so it might be that some messages are different in other versions (I’m not sure). But the idea is the same, regardless of that.
– hkotsubo