51

After reading Git pre-commit hook : changed/added files, the following question arose:

Given I have a file with both staged and unstaged changes, how can I display a preview of the file's contents after staging?

Example:

echo "foo" >> file
git add file
echo "bar" >> file

Wanted output:

[previous contents of file]
foo
Community
  • 1
  • 1
user123444555621
  • 148,182
  • 27
  • 114
  • 126

4 Answers4

125

Use the : prefix to access objects in the current index (staged but not yet commited).

git show :file

See gitrevisions (which uses the term 'stage 0' for the "normal" index contents):

:[<n>:]<path>, e.g. :0:README, :README

A colon, optionally followed by a stage number (0 to 3) and a colon, followed by a path, names a blob object in the index at the given path. A missing stage number (and the colon that follows it) names a stage 0 entry. During a merge, stage 1 is the common ancestor, stage 2 is the target branch’s version (typically the current branch), and stage 3 is the version from the branch which is being merged.

user1686
  • 13,155
  • 2
  • 35
  • 54
  • Very nice indeed, however I'd prefer something that works with relative paths. Even though the docs state that `A path starting with ./ or ../ is relative to current working directory.`, this doesn't work for me. – user123444555621 Mar 01 '11 at 12:15
  • So given a dirty file README; `HEAD:README` shows file before changes. `:README` shows file with staged changes only. Is there any way to show the file with only non staged changes? I didn't see anything that would indicate so in the linked documentation. – JD Isaacks Sep 12 '13 at 03:26
  • @JDIsaacks: Not directly, no, because such a file does not exist anywhere in the repository (while `:README` exists in the index and `HEAD:README` exists in the current commit). You could, however, try applying `git diff README` output (which only shows unstaged changes) to a temporary copy of `HEAD:README`... – user1686 Sep 12 '13 at 13:41
  • I'm not having luck with `git show :file` if the file has not been previously committed. Is this expected? I had to fall back to `git ls-files -s ` and then `git cat-file -p `. – Christopher King Sep 14 '16 at 20:40
  • 1
    Note that the syntax is now (has long been) formalized as `::`, where the digit indicates which index *slot* to use: 0 (zero) is the slot containing the file that will be committed, while slots 1, 2, and 3 are used only during a merge conflict. – torek May 18 '18 at 14:20
  • @torek: Both `:path` and `:0:path` are documented in git's manual. The former is even listed both under `rev:path` (":path (with an empty part before the colon) is a special case") _and_ under `:n:path` ("A missing stage number (and the colon that follows it) names a stage 0 entry"). – user1686 May 18 '18 at 17:38
  • 1
    True - I'm suggesting that the answer could note that there's a fuller syntax to get at any of the possible index slots. (But the link to `gitrevisions` is probably sufficient) – torek May 18 '18 at 20:15
6

Update: the answer from grawity has a much neater solution

This recipe is from jleedev's answer to another question:

git cat-file blob $(git ls-files -s file | awk '{print $2}')

You might want to create a git alias for that if you're going to use it often.

Community
  • 1
  • 1
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
0

You can do git diff --cached, but this isn't exactly what you want.

git grep -h --cached ^ -- file

works for me.

Tollef Fog Heen
  • 201
  • 1
  • 1
-2

Just have a look at the top answer for this question: How do I show the changes which have been staged?

The --cached option is what you want.

Community
  • 1
  • 1
Daniel Böhmer
  • 14,463
  • 5
  • 36
  • 46
  • This will show the ***the diff*** of the staged file, but it won't show you the way the file would look if you just opened it in an editor or `cat` it. –  Aug 10 '13 at 18:33
  • Apologies for the downvote, but that's a perfectly good answer to a completely different question! :smile: – pvandenberk Oct 14 '14 at 19:12