Reputation: 20875
I am aware that git reset myFile.txt
untracks myFile.txt.
If I make a file myFile.txt in a git repo, and then call git diff
, I can see myFile.txt listed as a difference. I can't see myFile.txt as a difference after I add it. This is expected since I am now tracking the file.
However, if I use git reset myFile.txt
to untrack myFile.txt, I can't see myFile.txt listed in git diff
. Why is that? Isn't git diff
supposed to show me my untracked changes?
Upvotes: 3
Views: 1553
Reputation: 83517
git diff
runs a diff against the files in the repo's index. If the file is not yet tracked, it is not in the index, so you will not see it listed in the output of git diff
.
When you run git add
, git adds the file to the index. This means that a subsequent git diff
will show the file in the output.
To see files that are untracked, run git status
instead.
Upvotes: 1
Reputation: 46992
git reset
doesn't always untrack the file. It only does that if it wasn't being tracked before. git diff
only shows you unstaged changes. If the file is untracked, git ignores it except in status output, where it let's you know that there's a file that you may want to track. Let's start off with a clean repository:
$ git init practice
$ cd practice
Now, let's add a file:
$ echo "Hello World" > hello.txt
At this point, git status
says the file is untracked:
$ 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)
So doing a git diff
here will show us nothing, since git is essentially ignoring the file right now:
$ git diff
Now, let's add hello.txt
to the index:
$ 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
#
git diff
still shows us nothing:
$ git diff
The reason for this is because git diff
will tell you the difference between the index and the working tree. Now that we've added hello.txt
to the index, the working tree matches, so there's nothing for git diff
to show.
If you'd like to see what is staged for commit, try git diff --cached
:
$ git diff --cached
diff --git a/hello.txt b/hello.txt
new file mode 100644
index 0000000..557db03
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1 @@
+Hello World
Just for reference, here is the help from the --cached
command line option:
This form is to view the changes you staged for the next commit relative to the named
<commit>
. Typically you would want comparison with the latest commit, so if you do not give<commit>
, it defaults toHEAD
. IfHEAD
does not exist (e.g. unborned branches) and<commit>
is not given, it shows all staged changes.--staged
is a synonym of--cached
.
When you do a reset at this point, you're not simply unstaging the contents of the file, git goes back to seeing the file as untracked:
$ git reset 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)
As a result, git diff
won't show you anything. Even if you did a git commit -a
, the file wouldn't get committed because it is untracked.
Once the file is tracked, the story changes. So let's add it, and commit it:
$ git add hello.txt
$ git commit -m "Initial commit."
[master (root-commit) 67cb14e] Initial commit.
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
$ git status
# On branch master
nothing to commit, working directory clean
Now, let's add more text:
$ echo "Hello again" >> hello.txt
$ 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")
The output of git status
has changed. We now see hello.txt
as modified, whereas before it was untracked. Now git diff
works because the file exists in the index and is being tracked. The index version is whatever you have staged, or it matches the last commit (HEAD
), if you haven't staged anything:
$ git diff
diff --git a/hello.txt b/hello.txt
index 557db03..49e9db5 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
Hello World
+Hello again
Let's stage it and look at the diff:
$ git add hello.txt
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: hello.txt
#
$ git diff
Now we're back to seeing no difference because what's in the index matches the working tree. Let's reset: $ git reset hello.txt Unstaged changes after reset: M hello.txt
Now we can see the changes again:
$ git diff
diff --git a/hello.txt b/hello.txt
index 557db03..49e9db5 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
Hello World
+Hello again
Git didn't untrack the file here, it just reset the content of the index. The file is still being tracked. Let's add hello.txt
to the index and make a change just to demonstrate one last part about comparing to the index:
$ git add hello.txt
$ echo "One final change" >> hello.txt
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: hello.txt
#
# 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
#
So now we see that hello.txt
has some changes staged for commit, and some that are not:
$ git diff
diff --git a/hello.txt b/hello.txt
index 49e9db5..97849b8 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,3 @@
Hello World
Hello again
+One final change
Notice it only shows the "One final change" line as being added. That's because git diff
is comparing the working tree against the index, and we added the "Hello again" line into the index when we did the last git add
. This does not show what changes are staged for commit though. For that, we go back to git diff --cached
:
$ git diff --cached
diff --git a/hello.txt b/hello.txt
index 557db03..49e9db5 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,2 @@
Hello World
+Hello again
At this point, let's reset and restore the index to the version in HEAD
:
$ git reset hello.txt
Since we no longer have any changes staged, git diff --cached
comes back clean:
$ git diff --cached
And git diff
will show both changes:
$ git diff
diff --git a/hello.txt b/hello.txt
index 557db03..97849b8 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,3 @@
Hello World
+Hello again
+One final change
Hopefully, that helps you to see how changes are transferred back and forth between the working tree and the index, that untracked files are essentially ignored, and how to see changes that have been staged. The best visualization I've seen of this is NDP Software's Git Cheatsheet which shows you how commands move content between the various stages in git.
Upvotes: 6