Qwerty
Qwerty

Reputation: 778

Why "--cached" flag is required when entering "git diff" results after adding the file (git add) to GIT?

[gdaniel@vnc23 sx_fit_regression]$ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.

Changes to be committed: (use "git reset HEAD ..." to unstage)

   new file:   eth/fdb/configuration/eth_fdb_cli/eth_fdb_cli.cases
   new file:   eth/fdb/configuration/eth_fdb_cli/specific_test.py
   new file:   eth/fdb/configuration/eth_fdb_cli/test_suit_runner.py
   new file:   eth/fdb/configuration/eth_fdb_cli/test_wrapper.py
   modified:   eth/utilities/eth_constants.py
   modified:   eth/utilities/eth_fdb_tools.py
   modified:   libs/tools/string_manipulation_tools.py

Untracked files:#   (use "git add <file>..." to include in what will be committed)

   .project
   .pydevproject
   eth/utilities/Test.py

[gdaniel@vnc23 sx_fit_regression]$

[gdaniel@vnc23 sx_fit_regression]$ git diff --color  eth/utilities/eth_constants.py
[gdaniel@vnc23 sx_fit_regression]$< Blank Output>                                                 
[gdaniel@vnc23 sx_fit_regression]$ git diff --color --cached eth/utilities/eth_constants.py
diff --git a/eth/utilities/eth_constants.py b/eth/utilities/eth_constants.py
index 9c0df62..c94f04e 100755
--- a/eth/utilities/eth_constants.py
+++ b/eth/utilities/eth_constants.py

Output omitted...

Please clarify.

Thanks,

Qwerty

Upvotes: 1

Views: 1118

Answers (5)

devjoco
devjoco

Reputation: 484

Path of Least Resistance

The most common use case for git diff is when you've just made some changes to your working tree – the files you're currently working on – and you want to see those changes that could be further added to the next commit. You haven't staged them yet, which indicates you haven't determined them to be good enough for the next commit yet. In order to help you make that determination, you might want to run a git diff to see what those changes are exactly.

The files that have already been added to the index – the staging area for the next commit – have (presumably) already been reviewed, and determined to be ready and acceptable for the next commit.

In order to make it as easy as possible to check the changes that you've just made (without being distracted by the changes that you're already okay with being in the next commit), the default behavior of git diff using no other options is to check the working tree against the index:

git diff [<options>] [--] [<path>…​]
This form is to view the changes you made relative to the index (staging area for the next commit). In other words, the differences are what you could tell Git to further add to the index but you still haven’t. You can stage these changes by using git-add[1].

https://git-scm.com/docs/git-diff#Documentation/git-diff.txt-emgitdiffemltoptionsgt--ltpathgt82308203


Much Less Common

Of course, even if you have reviewed some changes and deemed them ready to go into the next commit, you may still want to double check what those changes are before committing them. Because this case is less common, it rightfully takes an additional option to perform it:

git diff [<options>] --cached [<commit>] [--] [<path>…​]
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 to HEAD. If HEAD does not exist (e.g. unborn branches) and <commit> is not given, it shows all staged changes. --staged is a synonym of --cached.

https://git-scm.com/docs/git-diff#Documentation/git-diff.txt-emgitdiffemltoptionsgt--cachedltcommitgt--ltpathgt82308203


Other Examples from the Documentation:

Various ways to check your working tree

$ git diff            (1)
$ git diff --cached   (2)
$ git diff HEAD       (3)
  1. Changes in the working tree not yet staged for the next commit.
  2. Changes between the index and your last commit; what you would be committing if you run git commit without -a option.
  3. Changes in the working tree since your last commit; what you would be committing if you run git commit -a

https://git-scm.com/docs/git-diff#Documentation/git-diff.txt-Variouswaystocheckyourworkingtree



Probably Unecessary Side Note

In case it seems odd that you would check the working tree against the index to see the changes that you've just made (even when the index is empty), rather than checking it against the HEAD – a reference to the most recent commit on the current branch (i.e. what you've just made changes to) – you might want to consider what happens when an index is committed: the resulting, new commit is the contents of HEAD with the addition (or subtraction) of the changes in the index. A hypothetical commit with no changes staged in the index will still be the contents of HEAD and the additions (or subtractions) from index; it's just that the index consists of no changes (i.e. HEAD + index = HEAD when index == 0). So, with that in mind, git diff with no options, and with no changes staged in the index, will be displaying changes in the working tree against the staging area for the next commit, but this effectively amounts to checking the working tree against HEAD, rendering the 1st and 3rd of those previous examples equivalent in this case.

Upvotes: 1

kostix
kostix

Reputation: 55463

The setting

Two places of information are in the picture here:

  • The work tree—that's where your files are checked out, where you modify them and from where you stage the changes you've made to them.
  • The staging area (also known as "the index" or "the cache"1).

The commits are normally created from the contents of the staging area.

Note that both the work tree and the staging area are (typically) based on the same single commit—the one the HEAD ref points at.

The git diff command

The git diff command with no special arguments (but may be with arguments specifying concrete paths to consider) compares the staging area to the work tree.

This is logical because it shows you the changes you might want to stage and then commit.

By extension, once you stage a change—and it's now in the staging area—git diff stops displaying this change because the work tree and the staging area now contain identical information.

If you instead want to ask Git "what would be committed if I do git commit now?" you have to run git diff --cached or git diff --staged to make Git compare the base commit, HEAD, with the contents of the staging area.

Note that if you have staged only some of the changes you've got in the work tree, you now have three possible diffs to consider:

  • The difference between the staging area and the work tree: "unstaged changes".

    Use git diff to see them.

  • The difference between the base commit, HEAD, and the staging area: "what will be committed".

    Use git diff --cached or git diff --staged to see them.

  • The difference between the base commit, HEAD, and the work tree: "total uncommitted changes".

    Use git diff HEAD to see them.


1 Originally, the basic idea of the staging area was to provide a data storage with very fast access which would reference all the metadata comprising the files checked out into the work tree as well as their modified contents (changes staged for the next commit). Since that was indeed a cache of the metadata (it enables the git status and similar operations to be lightning-fast even on trees containing insane quantities of files), this name was used, and stuck. IIRC, it then became known as "the index" and then rebranded as "the staging area" to help mere mortals grasp the concept more easily.

Upvotes: 1

Philip Whitehouse
Philip Whitehouse

Reputation: 4157

--cached is a little misleading here. It's a synonym for --staged.

So git diff is showing you unstaged changes, git diff --cached is showing you staged/cached changes.

Upvotes: 0

roman-roman
roman-roman

Reputation: 2796

Sometimes git syntax is a bit confusing, right?

git diff outputs the diff in your working copy. When you add --staged, or --cached, you tell git to diff already added files instead. You can treat them like two different commands, if it makes sense for you.

Also, if you want to see diff for new files as well, you have to add them first.

Upvotes: 1

knittl
knittl

Reputation: 265231

Because Git normally compares the working tree to the index. Once you add a file to the index (staging area), there is no difference. git diff --cached however compares the index (staging area) to the latest commit (HEAD).

Upvotes: 3

Related Questions