Git fork

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 <gitster@pobox.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Nguyễn Thái Ngọc Duy and committed by
Junio C Hamano
a2b7a3b3 2e9c8789

+71 -2
+2
Documentation/git-diff.txt
··· 38 38 commit relative to the named <commit>. Typically you 39 39 would want comparison with the latest commit, so if you 40 40 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. 41 43 --staged is a synonym of --cached. 42 44 43 45 'git diff' [--options] <commit> [--] [<path>...]::
+5 -2
builtin/diff.c
··· 330 330 else if (!strcmp(arg, "--cached") || 331 331 !strcmp(arg, "--staged")) { 332 332 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 + } 335 338 break; 336 339 } 337 340 }
+11
t/t4013-diff-various.sh
··· 290 290 test_must_fail git log -S 291 291 ' 292 292 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 + 293 304 test_done
+38
t/t4013/diff.diff_--cached
··· 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
+15
t/t4013/diff.diff_--cached_--_file0
··· 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