Skip to content

Commit a2b7a3b

Browse files
pcloudsgitster
authored andcommitted
diff: support --cached on unborn branches
"git diff --cached" (without revision) used to mean "git diff --cached HEAD" (i.e. the user was too lazy to type HEAD). This "correctly" failed when there was no commit yet. But was that correctness useful? This patch changes the definition of what particular command means. It is a request to show what _would_ be committed without further "git add". The internal implementation is the same "git diff --cached HEAD" when HEAD exists, but when there is no commit yet, it compares the index with an empty tree object to achieve the desired result. Signed-off-by: Junio C Hamano <[email protected]> Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2e9c878 commit a2b7a3b

File tree

5 files changed

+71
-2
lines changed

5 files changed

+71
-2
lines changed

Documentation/git-diff.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ directories. This behavior can be forced by --no-index.
3838
commit relative to the named <commit>. Typically you
3939
would want comparison with the latest commit, so if you
4040
do not give <commit>, it defaults to HEAD.
41+
If HEAD does not exist (e.g. unborned branches) and
42+
<commit> is not given, it shows all staged changes.
4143
--staged is a synonym of --cached.
4244

4345
'git diff' [--options] <commit> [--] [<path>...]::

builtin/diff.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
330330
else if (!strcmp(arg, "--cached") ||
331331
!strcmp(arg, "--staged")) {
332332
add_head_to_pending(&rev);
333-
if (!rev.pending.nr)
334-
die("No HEAD commit to compare with (yet)");
333+
if (!rev.pending.nr) {
334+
struct tree *tree;
335+
tree = lookup_tree((const unsigned char*)EMPTY_TREE_SHA1_BIN);
336+
add_pending_object(&rev, &tree->object, "HEAD");
337+
}
335338
break;
336339
}
337340
}

t/t4013-diff-various.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,15 @@ test_expect_success 'log -S requires an argument' '
290290
test_must_fail git log -S
291291
'
292292

293+
test_expect_success 'diff --cached on unborn branch' '
294+
echo ref: refs/heads/unborn >.git/HEAD &&
295+
git diff --cached >result &&
296+
test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached" result
297+
'
298+
299+
test_expect_success 'diff --cached -- file on unborn branch' '
300+
git diff --cached -- file0 >result &&
301+
test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result
302+
'
303+
293304
test_done

t/t4013/diff.diff_--cached

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
diff --git a/dir/sub b/dir/sub
2+
new file mode 100644
3+
index 0000000..992913c
4+
--- /dev/null
5+
+++ b/dir/sub
6+
@@ -0,0 +1,8 @@
7+
+A
8+
+B
9+
+C
10+
+D
11+
+E
12+
+F
13+
+1
14+
+2
15+
diff --git a/file0 b/file0
16+
new file mode 100644
17+
index 0000000..10a8a9f
18+
--- /dev/null
19+
+++ b/file0
20+
@@ -0,0 +1,9 @@
21+
+1
22+
+2
23+
+3
24+
+4
25+
+5
26+
+6
27+
+A
28+
+B
29+
+C
30+
diff --git a/file1 b/file1
31+
new file mode 100644
32+
index 0000000..b1e6722
33+
--- /dev/null
34+
+++ b/file1
35+
@@ -0,0 +1,3 @@
36+
+A
37+
+B
38+
+C

t/t4013/diff.diff_--cached_--_file0

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
diff --git a/file0 b/file0
2+
new file mode 100644
3+
index 0000000..10a8a9f
4+
--- /dev/null
5+
+++ b/file0
6+
@@ -0,0 +1,9 @@
7+
+1
8+
+2
9+
+3
10+
+4
11+
+5
12+
+6
13+
+A
14+
+B
15+
+C

0 commit comments

Comments
 (0)