How do I show the changes which have been staged?
Asked Answered
F

16

2607

I staged a few changes to be committed. How do I see the diffs of all files which are staged for the next commit? Is there a handy one-liner for this?

git status only shows names of files which are staged, but I want to see the actual diffs.

The git-diff(1) man page says:

git diff [--options] [--] […]

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).

Faucal answered 19/10, 2009 at 9:57 Comment(3)
git status -v works too. See my answer belowLechner
@Lechner I always use this, but piped to less, as in: git status -v | less – manageable chunks :)Epistle
How can I grep git diff --cached for a string and return a list of the file names where a diff mentioned that string? Ah, I found the answer: git diff --cached -G "your_search_string" | grep 'diff --git' | awk '{print $3}' | cut -d/ -f2-Petulah
A
3151

It should just be:

git diff --cached

--cached means show the changes in the cache/index (i.e. staged changes) against the current HEAD. --staged is a synonym for --cached.

--staged and --cached does not point to HEAD, just difference with respect to HEAD. If you cherry pick what to commit using git add --patch (or git add -p), --staged will return what is staged.

Alveolus answered 19/10, 2009 at 10:7 Comment(6)
If you want the file names only, do the following git diff --name-only --cached per post at https://mcmap.net/q/40916/-how-to-make-git-status-show-only-staged-filesEliaseliason
Use this with git difftool --staged rather than git diff --staged to launch the default visual diff tool on each file. difftool can be substituted for diff with any other arguments as well.Mcmullin
And you can use git difftool --staged -d to diff the two directories in a visual tool rather than one file at a time.Hawkinson
since this one is marked as answer and showing first it should include git diff at the top, then git [[others]], just my 2 centsAguste
And to view the changes in a single staged file, following will work: git diff --cached -- <stagedfile>Cubit
is there a simplified one?Fils
N
1760

A simple graphic makes this clearer:

Simple Git diffs

git diff

Shows the changes between the working directory and the index. This shows what has been changed, but is not staged for a commit.

git diff --cached

Shows the changes between the index and the HEAD (which is the last commit on this branch). This shows what has been added to the index and staged for a commit.

git diff HEAD

Shows all the changes between the working directory and HEAD (which includes changes in the index). This shows all the changes since the last commit, whether or not they have been staged for commit or not.

Also:

There is a bit more detail on 365Git.

Nominalism answered 19/10, 2009 at 9:57 Comment(9)
This is naive, I'm afraid (as is usually the case with any git explanation). If you have local modifications to foo.c and do not perform git add foo.c, then foo.c is not in the index; it is not staged for commit. If git diff foo.c naively compared to the working foo.c to the index, then it would have to show a giant diff between an empty/nonexistent file and the entire contents of foo.c. So in fact, when a file does not exist in the index, git diff falls back, for that file, on using the HEAD copy.Farhi
@Farhi strictly speaking, the index is not a blank slate. It's a virtual copy of the HEAD on which the staged changes are applied. Remember that Git works by saving changes, not by saving entire files. When you stage a file, it's only storing the changes made. If the index is blank like you imply, it wouldn't know how to save the changes in the index, and would have to save the entire file as "newly added" - which is wrong.Greave
@Farhi Both the index and the HEAD will have the unchanged version of the foo.c file (they are not physical copies, but just logical copies to you and me. To Git they are just the same data stream that every commit that ever involved that file refers to). So when you do git diff on the fully unstaged foo.c it's not really falling back to HEAD it's actually doing the diff with the Index (which happens to contain the exact same version of the file as HEAD does). So the graphic is correct.Greave
Hello, I would like to know what it means "index" in this context? Thanks!Noranorah
@Gab When you change a file it is not automatically going to be in the next commit. You have to do a git add operation to do this. That's what the index is. The changes that have been made that will be committed to the repository on the next commit.Nominalism
@Nominalism So the index is the staged changes?Noranorah
So how do these options compare to git status -v?Peru
@TomRussell git status -v is equivalent to git diff --cached (plus git status of course)Undoubted
@Gab是好人 More specifically, the index contains all tracked files, including the staged changes. See stackoverflow.com/a/47543410Undoubted
L
72

Note that git status -v also shows the staged changes! (meaning you need to have staged -- git add -- some changes. No staged changes, no diff with git status -v.
It does that since Git 1.2.0, February 2006)

In its long form (default), git status has an undocumented "verbose" option which actually display the diff between HEAD and index.

And it is about to become even more complete: see "Show both staged & working tree in git diff?" (git 2.3.4+, Q2 2015):

git status -v -v
Lechner answered 18/3, 2015 at 7:22 Comment(6)
The last line should be git diff HEADBigler
@Bigler why? The point of the answer is to mention that git status -vv also includes what git diff HEAD does.Lechner
Does not work on git version 1.8.3.1. I know it's old, but if possible, note when this flag was introduced.Rodrickrodrigez
@onebree 1.8.3.1 is June 2013, old indeed. But git status -v is older (github.com/git/git/commit/…, git 1.2.0, February 2006!). Note that it displays the diff between the index and HEAD: if you have added anything to the index (no git add), then git status -v would not display any diff. git status -v -v is more recent (Git 2.3.4, March 2015)Lechner
@Lechner that was my mistake... I did git diff -v.Rodrickrodrigez
Thank you so much! I have git diff configured to use a GUI for comparison, but often times I just want a console printout of changes. This is exactly that.Ulphia
C
58

If you'd be interested in a visual side-by-side view, the diffuse visual diff tool can do that. It will even show three panes if some but not all changes are staged. In the case of conflicts, there will even be four panes.

Screenshot of diffuse with staged and unstaged edits

Invoke it with

diffuse -m

in your Git working copy.

If you ask me, the best visual differ I've seen for a decade. Also, it is not specific to Git: It interoperates with a plethora of other VCS, including SVN, Mercurial, Bazaar, ...

See also: Show both staged & working tree in git diff?

Creight answered 24/10, 2012 at 21:5 Comment(5)
Thanks, this looks like a nice tool. I've found Meld to be the best visual diff tool for Linux so far, but I missed being able to diff text from the clipboard -- Meld requires files for input. Diffuse allows this, as well as manual realignment. Will try it out for a while.Garthgartner
Broken link to diffuse.sourceforge.net, use sourceforge.net/projects/diffuse for now.Waugh
brew install diffuse works on OS X. Doesn't show 3 panes if both unstaged and staged changes - did you mean changes not yet in the index?Hegel
Which version of diffuse do you have? Yes -- if you add a file and then modify it locally, it should show three panes.Creight
You could also setup diffuse as your default difftool and use that built-in mechanism/tool/alias to launch it. See my answer here: <https://mcmap.net/q/40484/-how-do-i-show-the-changes-which-have-been-staged>Mcmullin
B
47

For Staging Area vs Repository(last commit) comparison use

$ git diff --staged

The command compares your staged($ git add fileName) changes to your last commit. If you want to see what you’ve staged that will go into your next commit, you can use git diff --staged. This command compares your staged changes to your last commit.

For Working vs Staging comparison use

$ git diff 

The command compares what is in your working directory with what is in your staging area. It’s important to note that git diff by itself doesn’t show all changes made since your last commit — only changes that are still unstaged. If you’ve staged all of your changes($ git add fileName), git diff will give you no output.

Also, if you stage a file($ git add fileName) and then edit it, you can use git diff to see the changes in the file that are staged and the changes that are unstaged.

Biotic answered 25/2, 2017 at 21:16 Comment(1)
"For Working vs Repository comparison use $ git diff". I'm pretty sure git diff compares between Working vs Staging. See stackoverflow.com/a/1587952Undoubted
M
36

USING A VISUAL DIFF TOOL

The Default Answer (at the command line)

The top answers here correctly show how to view the cached/staged changes in the Index:

$ git diff --cached

or $ git diff --staged which is an alias.



Launching the Visual Diff Tool Instead

The default answer will spit out the diff changes at the git bash (i.e. on the command line or in the console). For those who prefer a visual representation of the staged file differences, there is a script available within git which launches a visual diff tool for each file viewed rather than showing them on the command line, called difftool:

$ git difftool --staged

This will do the same this as git diff --staged, except any time the diff tool is run (i.e. every time a file is processed by diff), it will launch the default visual diff tool (in my environment, this is VS Code, using the code executable).

After the tool launches, the git diff script will pause until your visual diff tool is closed. Therefore, you will need to close each file in order to see the next one.



You Can Always Use difftool in place of diff in git commands

For all your visual diff needs, git difftool will work in place of any git diff command, including all options.

For example, to have the visual diff tool launch without asking whether to do it for each file, add the -y option (I think usually you'll want this!!):

$ git difftool -y --staged

In this case it will pull up each file in the visual diff tool, one at a time, bringing up the next one after the tool is closed.

Or to look at the diff of a particular file that is staged in the Index:

$ git difftool -y --staged <<relative path/filename>>

For all the options, see the man page:

$ git difftool --help


Setting up Visual Git Tool

To use a visual git tool other than the default, use the -t <tool> option:

$ git difftool -t <tool> <<other args>>

Or, see the difftool man page for how to configure git to use a different default visual diff tool.



Example .gitconfig entries for vscode as diff/merge tool

Part of setting up a difftool involves changing the .gitconfig file, either through git commands that change it behind the scenes, or editing it directly.

You can find your .gitconfig in your home directory,such as ~ in Unix or normally c:\users\<username> on Windows).

Or, you can open the user .gitconfig in your default Git editor with git config -e --global.

Here are example entries in my global user .gitconfig for VS Code as both diff tool and merge tool:

[diff]
    tool = vscode
    guitool = vscode
[merge]
    tool = vscode
    guitool = vscode
[mergetool]
    prompt = true
[difftool "vscode"]
    cmd = code --wait --diff \"$LOCAL\" \"$REMOTE\"
    path = c:/apps/vscode/code.exe
[mergetool "vscode"]
    cmd = code --wait \"$MERGED\"
    path = c:/apps/vscode/code.exe
Mcmullin answered 14/8, 2017 at 23:33 Comment(0)
K
29

You can use this command.

git diff --cached --name-only

The --cached option of git diff means to get staged files, and the --name-only option means to get only names of the files.

Katti answered 31/8, 2016 at 10:5 Comment(2)
Please edit with more information. Code-only and "try this" answers are discouraged, because they contain no searchable content, and don't explain why someone should "try this".Aspire
Not sure why I would want this, with the --name-only option I might as well use the regular git statusGemma
S
21

From version 1.7 and later it should be:

git diff --staged
Sporades answered 19/7, 2016 at 17:39 Comment(0)
W
10

If your intentions are to push-target a remote repo branch and your first pass at a commit change log were incomplete, you can correct the commit statement before pushing like this.

Locally

... make some changes ...

git diff # look at unstaged changes

git commit -am"partial description of changes"

... recall more changes unmentioned in commit ...

git diff origin/master # look at staged but not pushed changes

... amend staged commit statement ...

git commit --amend -m"i missed mentioning these changes ...."

git push
Weak answered 14/10, 2015 at 18:32 Comment(0)
S
9

If you have more than one file with staged changes, it may more practical to use git add -i, then select 6: diff, and finally pick the file(s) you are interested in.

Supervisor answered 14/3, 2012 at 14:30 Comment(0)
V
9

To see the differences for a specific stage file (or files) you can use

git diff --staged -- <path>...

For example,

git diff --staged -- app/models/user.rb
Vizier answered 25/1, 2022 at 18:36 Comment(0)
D
8

By default git diff is used to show the changes which is not added to the list of git updated files. But if you want to show the changes which is added or stagged then you need to provide extra options that will let git know that you are interested in stagged or added files diff .

$ git diff          # Default Use
$ git diff --cached # Can be used to show difference after adding the files 
$ git diff --staged # Same as 'git diff --cached' mostly used with latest version of git 

Example

$ git diff 
diff --git a/x/y/z.js  b/x/y/z.js index 98fc22b..0359d84 100644
--- a/x/y/z.js 
+++ b/x/y/z.js @@ -43,7 +43,7 @@ var a = function (tooltip) {

-        if (a)
+        if (typeof a !== 'undefined')
             res = 1;
         else
             res = 2;

$ git add x/y/z.js
$ git diff
$

Once you added the files , you can't use default of 'git diff' .You have to do like this:-

$ git diff --cached
diff --git a/x/y/z.js  b/x/y/z.js index 98fc22b..0359d84 100644
    --- a/x/y/z.js 
    +++ b/x/y/z.js @@ -43,7 +43,7 @@ var a = function (tooltip) {

    -        if (a)
    +        if (typeof a !== 'undefined')
                 res = 1;
             else
                 res = 2;
Dalrymple answered 20/11, 2017 at 6:30 Comment(0)
S
3

git gui and git-cola are graphical utilities that let you view and manipulate the index. Both include simple visual diffs for staged files, and git-cola can also launch a more sophisticated side-by-side visual diff tool.

See my closely related answer at How to remove a file from the index in git?, and also this official catalog of Git - GUI Clients.

Selectivity answered 13/4, 2016 at 14:31 Comment(0)
Y
1

The --cached didn't work for me, ... where, inspired by git log

git diff origin/<branch>..<branch> did.

Yoruba answered 24/6, 2020 at 19:52 Comment(0)
L
1

Another tool that makes this easy is Magit mode in Emacs. Its default view lists both staged and unstaged changes. It acts like git add -p on steroids, because you can easily stage or unstage hunks (or even single lines of code) with editor commands. It's important to know the standard git porcelain, but I rarely use git diff --cached anymore.

https://magit.vc/

Lucillalucille answered 28/7, 2021 at 18:19 Comment(0)
O
0

Think about the gitk tool also , provided with git and very useful to see the changes

Odometer answered 3/8, 2016 at 10:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.