Git Harpon
Git Harpon

Reputation: 171

Get added and deleted files from git diff output with HEAD

I'm using git diff to get the differences between a commit and his parent for a specific file. I'm using this command :

git diff parent-sha child-sha  -- file/to/path

Here is my problem : with this command I can get added, deleted and modified files for a specific commit. But when I try it on my current commit, I can only get modified/deleted files. I'm looking for a way to get deleted and added files for the current commit (comparing to his parent).

For instance here's my uncommitted changes : enter image description here

If I run git diff HEAD -- yarn.lock

I get this

diff --git a/yarn.lock b/yarn.lock
deleted file mode 100644
index c06acb9..0000000
--- a/yarn.lock
+++ /dev/null
@@ -1,10383 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"7zip-bin@~4.1.0":
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-4.1.0.tgz#33eff662a5c39c0c2061170cc003c5120743fff0"
-  integrity sha512-AsnBZN3a8/JcNt+KPkGGODaA4c7l3W5+WpeKgGSbstSLxqWtTXqd1ieJGBQ8IFCtRg8DmmKUcSkIkUc0A4p3YA==
-
-"@angular-devkit/[email protected]":
-  version "0.11.4"
-  resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.11.4.tgz#f0cc3b4f1dd0128f6b41d3bb760bcf4c324cd063"
-  integrity sha512-2zi6S9tPlk52vyqN67IvFoeNgd0uxtrPlwl3TdvJ3wrH7sYGJnkQ+EzAE7cKUGWAV989BbNtx2YxhRDHnN21Fg==

But nothing on git diff -- src/app/models/DiffFileInformation.ts

Upvotes: 1

Views: 2739

Answers (4)

Hadi tavakoli
Hadi tavakoli

Reputation: 1317

I figured out that for new files added to git which are not staged yet, you could try:

git diff /dev/null "src/app/models/DiffFileInformation.ts"

Upvotes: 0

torek
torek

Reputation: 489035

ElpieKay's answer is correct (and I've upvoted it) but it might help you think about the problem if you take a step back and think about commits and how Git works.

Every commit holds several things, which we can break up into two major categories, data and metadata. The data in a commit is the source code snapshot, and the metadata is extra information about the data, such as who made the snapshot, when, and so on (and importantly, the parent hash ID for the parent of this commit, or if it's a merge commit, all of its parent hash IDs, but I think you have that part well under control now). Note that everything inside the commit is frozen for all time. You cannot change any part of either the data or the metadata.

In fact, this is the case for all of Git's internal objects. The hash ID of the Git object is a cryptographic checksum of the contents of that object. This is great for archival—every commit, once made, can never be changed—but it's completely useless for getting any new work done. To do new work, Git must provide some place(s) where files can be modified.

Every version control system has this problem, and in general, they all solve it the same way: the place where you work on your file is your work-tree. Files in the work-tree are malleable. Files in commits are not. That means there's something fundamentally different about a work-tree than there is about a commit. The work-tree could be a proposed commit, but it's still malleable, so it's not an actual commit. (It doesn't have any metadata, either.)

So, in Git, a work-tree does not have a hash ID. But for some reason, Git takes this even further. Instead of just having the work-tree be the proposed next commit, Git adds a third entity, sitting between HEAD—the current commit—and the work-tree. This third entity is called the index, or the staging area, or even sometimes the cache. (You'll see all three names in Git documentation. They all refer to the same thing.) This index is where Git stores the proposed next commit. Git then provides commands like git add that copy from the work-tree (where you have your files and can work on them) to the index (to update the proposed next commit).

This means git diff needs to be able to:

  • compare commit vs commit
  • compare commit vs index
  • compare commit vs work-tree
  • compare index vs work-tree

It provides four different ways to do this, depending on the arguments and --cached flag you pass to git diff:

  • git diff hash1 hash2 compares commit vs commit
  • git diff --cached hash compares commit vs index
  • git diff hash compares commit vs work-tree
  • git diff compares index vs work-tree

Pick which one you want, add -- <path> to restrict the diff output, and you're all set.

Upvotes: 4

ElpieKay
ElpieKay

Reputation: 30888

The following 3 commands are not the same:

git diff
git diff HEAD
git diff HEAD^ HEAD

Suppose we have initialized a repo and made two commits and some extra uncommitted changes.

git init foo
cd foo
touch a.txt b.txt
git add .
git commit -m 'first commit'

echo hello >> a.txt
echo hello >> b.txt
git commit -m 'hello'

echo world >> a.txt
echo world >> b.txt
# stage a.txt and leave b.txt alone
git add a.txt
  1. What does git diff return?

git diff compares the working tree and the index. The working tree has the modified version of a.txt and b.txt, and the index has only the modified version of a.txt. So the difference lies between the working tree's b.txt and the index's b.txt:

hello
world

VS

hello

git diff returns:

diff --git a/b.txt b/b.txt
index ce01362..94954ab 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1,2 @@
 hello
+world
  1. What does git diff HEAD return?

It compares the files in the revision of HEAD with the files in the working tree. a.txt in HEAD is

hello

a.txt in the working tree is

hello
world

b.txt is the same with a.txt, so git diff HEAD returns:

diff --git a/a.txt b/a.txt
index ce01362..94954ab 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,2 @@
 hello
+world
diff --git a/b.txt b/b.txt
index ce01362..94954ab 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1,2 @@
 hello
+world
  1. What does git diff HEAD^ HEAD return?

It compares the files of the former revision with the files of the latter. In HEAD^, both a.txt and b.txt are empty. In HEAD, both are:

hello

So we get the output of git diff HEAD^ HEAD as:

diff --git a/a.txt b/a.txt
index e69de29..ce01362 100644
--- a/a.txt
+++ b/a.txt
@@ -0,0 +1 @@
+hello
diff --git a/b.txt b/b.txt
index e69de29..ce01362 100644
--- a/b.txt
+++ b/b.txt
@@ -0,0 +1 @@
+hello

If we swap HEAD^ and HEAD, git diff HEAD HEAD^ returns:

diff --git a/a.txt b/a.txt
index ce01362..e69de29 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +0,0 @@
-hello
diff --git a/b.txt b/b.txt
index ce01362..e69de29 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +0,0 @@
-hello

HEAD and HEAD^ could be any commits reachable in the repository. Instead of swapping the revisions, we can also get the reversed diff with the option -R, git diff -R HEAD^ HEAD.

Not sure what your purpose exactly is. Maybe you can find the solution here. More syntaxes of git diff are described.

Upvotes: 2

padawin
padawin

Reputation: 4476

git diff HEAD -- path will show you your local modifications.

The file src/app/models/DiffFileInformation.ts is untracked and unstaged, so it won't appear in your diff.

To see it in the diff, you will need to stage it (add it) first.

Upvotes: 1

Related Questions