@matheusbsbs / matheus-bagliano / commits / 18bc76164d
Fork 0

add--interactive: handle initial commit better

There were several points where we looked at the HEAD commit; for initial commits, this is meaningless. So instead we: - show staged status data as a diff against the empty tree instead of HEAD - show file diffs as creation events - use "git rm --cached" to revert instead of going back to the HEAD commit We magically reference the empty tree to implement this. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 13, 2008 at 05:50 UTC 18bc76164dbf4f6d54b8fa9c9c29db9ca66c7877
2 files changed +108 -16
git-add--interactive.perl
+39 -16
@@ -82,6 +82,19 @@ sub list_untracked {
82 my $status_fmt = '%12s %12s %s';
83 my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');
84
85 +{
86 + my $initial;
87 + sub is_initial_commit {
88 + $initial = system('git rev-parse HEAD -- >/dev/null 2>&1') != 0
89 + unless defined $initial;
90 + return $initial;
91 + }
92 +}
93 +
94 +sub get_empty_tree {
95 + return '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
96 +}
97 +
98 # Returns list of hashes, contents of each of which are:
99 # VALUE: pathname
100 # BINARY: is a binary path
@@ -103,8 +116,10 @@ sub list_modified {
116 return if (!@tracked);
117 }
118
119 + my $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';
120 for (run_cmd_pipe(qw(git diff-index --cached
107 - --numstat --summary HEAD --), @tracked)) {
121 + --numstat --summary), $reference,
122 + '--', @tracked)) {
123 if (($add, $del, $file) =
124 /^([-\d]+) ([-\d]+) (.*)/) {
125 my ($change, $bin);
@@ -476,21 +491,27 @@ sub revert_cmd {
491 HEADER => $status_head, },
492 list_modified());
493 if (@update) {
479 - my @lines = run_cmd_pipe(qw(git ls-tree HEAD --),
480 - map { $_->{VALUE} } @update);
481 - my $fh;
482 - open $fh, '| git update-index --index-info'
483 - or die;
484 - for (@lines) {
485 - print $fh $_;
494 + if (is_initial_commit()) {
495 + system(qw(git rm --cached),
496 + map { $_->{VALUE} } @update);
497 }
487 - close($fh);
488 - for (@update) {
489 - if ($_->{INDEX_ADDDEL} &&
490 - $_->{INDEX_ADDDEL} eq 'create') {
491 - system(qw(git update-index --force-remove --),
492 - $_->{VALUE});
493 - print "note: $_->{VALUE} is untracked now.\n";
498 + else {
499 + my @lines = run_cmd_pipe(qw(git ls-tree HEAD --),
500 + map { $_->{VALUE} } @update);
501 + my $fh;
502 + open $fh, '| git update-index --index-info'
503 + or die;
504 + for (@lines) {
505 + print $fh $_;
506 + }
507 + close($fh);
508 + for (@update) {
509 + if ($_->{INDEX_ADDDEL} &&
510 + $_->{INDEX_ADDDEL} eq 'create') {
511 + system(qw(git update-index --force-remove --),
512 + $_->{VALUE});
513 + print "note: $_->{VALUE} is untracked now.\n";
514 + }
515 }
516 }
517 refresh();
@@ -956,7 +977,9 @@ sub diff_cmd {
977 HEADER => $status_head, },
978 @mods);
979 return if (!@them);
959 - system(qw(git diff -p --cached HEAD --), map { $_->{VALUE} } @them);
980 + my $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';
981 + system(qw(git diff -p --cached), $reference, '--',
982 + map { $_->{VALUE} } @them);
983 }
984
985 sub quit_cmd {
t/t3701-add-interactive.sh new
+69
@@ -0,0 +1,69 @@
1 +#!/bin/sh
2 +
3 +test_description='add -i basic tests'
4 +. ./test-lib.sh
5 +
6 +test_expect_success 'setup (initial)' '
7 + echo content >file &&
8 + git add file &&
9 + echo more >>file &&
10 + echo lines >>file
11 +'
12 +test_expect_success 'status works (initial)' '
13 + git add -i </dev/null >output &&
14 + grep "+1/-0 *+2/-0 file" output
15 +'
16 +cat >expected <<EOF
17 +new file mode 100644
18 +index 0000000..d95f3ad
19 +--- /dev/null
20 ++++ b/file
21 +@@ -0,0 +1 @@
22 ++content
23 +EOF
24 +test_expect_success 'diff works (initial)' '
25 + (echo d; echo 1) | git add -i >output &&
26 + sed -ne "/new file/,/content/p" <output >diff &&
27 + diff -u expected diff
28 +'
29 +test_expect_success 'revert works (initial)' '
30 + git add file &&
31 + (echo r; echo 1) | git add -i &&
32 + git ls-files >output &&
33 + ! grep . output
34 +'
35 +
36 +test_expect_success 'setup (commit)' '
37 + echo baseline >file &&
38 + git add file &&
39 + git commit -m commit &&
40 + echo content >>file &&
41 + git add file &&
42 + echo more >>file &&
43 + echo lines >>file
44 +'
45 +test_expect_success 'status works (commit)' '
46 + git add -i </dev/null >output &&
47 + grep "+1/-0 *+2/-0 file" output
48 +'
49 +cat >expected <<EOF
50 +index 180b47c..b6f2c08 100644
51 +--- a/file
52 ++++ b/file
53 +@@ -1 +1,2 @@
54 + baseline
55 ++content
56 +EOF
57 +test_expect_success 'diff works (commit)' '
58 + (echo d; echo 1) | git add -i >output &&
59 + sed -ne "/^index/,/content/p" <output >diff &&
60 + diff -u expected diff
61 +'
62 +test_expect_success 'revert works (commit)' '
63 + git add file &&
64 + (echo r; echo 1) | git add -i &&
65 + git add -i </dev/null >output &&
66 + grep "unchanged *+3/-0 file" output
67 +'
68 +
69 +test_done