{"thread":{"id":"12050","subject":"[Bug] git add -i fails in multiple ways prior to first commit.","startedAt":"2008-02-12T00:59:46Z","lastAt":"2008-02-13T13:45:59Z","messageCount":13,"participants":["Rhodes, Kate","Jeff King","Jakub Narebski","Junio C Hamano","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"68471","messageId":"C50196C5-B0C5-4536-AD4A-0F9C553782EE@gmail.com","threadId":"12050","inReplyTo":null,"subject":"[Bug] git add -i fails in multiple ways prior to first commit.","fromName":"Rhodes, Kate","fromEmail":"masukomi@gmail.com","sentAt":"2008-02-12T00:59:46Z","receivedAt":"2008-02-12T00:59:46Z","isPatch":false,"sender":{"key":"masukomi@gmail.com","avatar":null},"body":"$ git init\n$ touch foo.txt\n$ git add foo.txt\n$ git add -i\nfatal: bad revision 'HEAD'\n            staged     unstaged path\n\n\n*** Commands ***\n   1: [s]tatus\t  2: [u]pdate\t  3: [r]evert\t  4: [a]dd untracked\n   5: [p]atch\t  6: [d]iff\t  7: [q]uit\t  8: [h]elp\nWhat now>\n\n\n* status fails to report the current status\n* update fails to work at all\n* revert fails to work (not that there should be anything to revert  \nbut it shouldn't return a \"fatal: bad revision 'HEAD'\" message.\n* add untracked works\n* patch works\n* diff fails\n* help returns instructions that are incorrect owing to the fact that  \nhalf of the things don't work in this state.\n* quit, thankfully, works. :)\n\n\nWhy this is important:\ngit add's interactive mode is intended to make things easier, thus it  \nstands to reason that people new to git are going to want to use it.  \nPresenting them with so many broken commands so early on is,  \nobviously, a really bad idea.\n\n-masukomi\n"},{"id":"68623","messageId":"20080213101649.GA18444@coredump.intra.peff.net","threadId":"12050","inReplyTo":"C50196C5-B0C5-4536-AD4A-0F9C553782EE@gmail.com","subject":"Re: [Bug] git add -i fails in multiple ways prior to first commit.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-13T10:16:49Z","receivedAt":"2008-02-13T10:16:49Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 11, 2008 at 07:59:46PM -0500, Rhodes, Kate wrote:\n\n> * status fails to report the current status\n> * update fails to work at all\n\nBelow is a patch to address these two. It works by simulating the\ndiff as if HEAD contained nothing. The 'diff' command is still broken\n(it would need to generate fake diff output against an empty tree).\n\nHowever, I wonder if this is the best approach. It would be nice if\nthere were a shorthand for \"the empty tree\" for diffing, so you could\njust diff against that rather than HEAD, and have the regular plumbing\ngenerate.\n\nI suppose we could just create that tree object, though it adds a slight\namount of cruft to the object database.\n\n---\n git-add--interactive.perl |   62 ++++++++++++++++++++++++++++++++-------------\n 1 files changed, 44 insertions(+), 18 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 17ca5b8..b9f9abe 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -82,6 +82,17 @@ sub list_untracked {\n my $status_fmt = '%12s %12s %s';\n my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n \n+sub is_initial_commit {\n+\treturn system('git rev-parse HEAD -- >/dev/null 2>&1') != 0;\n+}\n+\n+sub count_blob_lines {\n+\tmy $sha1 = shift;\n+\tmy @lines = run_cmd_pipe(qw(git cat-file blob), $sha1);\n+\treturn scalar(@lines);\n+}\n+\n+\n # Returns list of hashes, contents of each of which are:\n # VALUE:\tpathname\n # BINARY:\tis a binary path\n@@ -103,27 +114,42 @@ sub list_modified {\n \t\treturn if (!@tracked);\n \t}\n \n-\tfor (run_cmd_pipe(qw(git diff-index --cached\n-\t\t\t     --numstat --summary HEAD --), @tracked)) {\n-\t\tif (($add, $del, $file) =\n-\t\t    /^([-\\d]+)\t([-\\d]+)\t(.*)/) {\n-\t\t\tmy ($change, $bin);\n-\t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n-\t\t\t\t$bin = 1;\n-\t\t\t}\n-\t\t\telse {\n-\t\t\t\t$change = \"+$add/-$del\";\n-\t\t\t}\n+\tif (is_initial_commit()) {\n+\t\tfor (run_cmd_pipe(qw(git ls-files --stage --exclude-standard\n+\t\t\t\t     --), @tracked)) {\n+\t\t\tmy ($sha1, $file) = /\\d+ ([0-9a-f]+) \\d\\t(.*)/\n+\t\t\t\tor die \"invalid ls-files output: $_\";\n+\t\t\tmy $n = count_blob_lines($sha1);\n \t\t\t$data{$file} = {\n-\t\t\t\tINDEX => $change,\n-\t\t\t\tBINARY => $bin,\n+\t\t\t\tINDEX => \"+$n/-0\",\n \t\t\t\tFILE => 'nothing',\n-\t\t\t}\n+\t\t\t\tINDEXADDDEL => 'create',\n+\t\t\t};\n \t\t}\n-\t\telsif (($adddel, $file) =\n-\t\t       /^ (create|delete) mode [0-7]+ (.*)$/) {\n-\t\t\t$data{$file}{INDEX_ADDDEL} = $adddel;\n+\t}\n+\telse {\n+\t\tfor (run_cmd_pipe(qw(git diff-index --cached\n+\t\t\t\t     --numstat --summary HEAD --), @tracked)) {\n+\t\t\tif (($add, $del, $file) =\n+\t\t\t    /^([-\\d]+)\t([-\\d]+)\t(.*)/) {\n+\t\t\t\tmy ($change, $bin);\n+\t\t\t\tif ($add eq '-' && $del eq '-') {\n+\t\t\t\t\t$change = 'binary';\n+\t\t\t\t\t$bin = 1;\n+\t\t\t\t}\n+\t\t\t\telse {\n+\t\t\t\t\t$change = \"+$add/-$del\";\n+\t\t\t\t}\n+\t\t\t\t$data{$file} = {\n+\t\t\t\t\tINDEX => $change,\n+\t\t\t\t\tBINARY => $bin,\n+\t\t\t\t\tFILE => 'nothing',\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\telsif (($adddel, $file) =\n+\t\t\t       /^ (create|delete) mode [0-7]+ (.*)$/) {\n+\t\t\t\t$data{$file}{INDEX_ADDDEL} = $adddel;\n+\t\t\t}\n \t\t}\n \t}\n \n-- \n1.5.4.1.1296.g34f89-dirty\n"},{"id":"68626","messageId":"m3k5l9cfzi.fsf@localhost.localdomain","threadId":"12050","inReplyTo":"20080213101649.GA18444@coredump.intra.peff.net","subject":"Re: [Bug] git add -i fails in multiple ways prior to first commit.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-02-13T10:23:48Z","receivedAt":"2008-02-13T10:23:48Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> However, I wonder if this is the best approach. It would be nice if\n> there were a shorthand for \"the empty tree\" for diffing,\n\n/dev/null? --root?\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"68627","messageId":"20080213103710.GA25808@coredump.intra.peff.net","threadId":"12050","inReplyTo":"m3k5l9cfzi.fsf@localhost.localdomain","subject":"Re: [Bug] git add -i fails in multiple ways prior to first commit.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-13T10:37:10Z","receivedAt":"2008-02-13T10:37:10Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 13, 2008 at 02:23:48AM -0800, Jakub Narebski wrote:\n\n> > However, I wonder if this is the best approach. It would be nice if\n> > there were a shorthand for \"the empty tree\" for diffing,\n> \n> /dev/null? --root?\n\n--root doesn't work since it is so entwined with diffing against an\nactual tree. I was thinking something more like turning the magic ref\n\"EMPTY_TREE\" internally into the empty tree, and then everything would\njust work.\n\nOr is that what you were suggesting \"/dev/null\" for? Another possible\nname is 4b825dc642cb6eb9a060e54bf8d69288fbee4904, which is the SHA-1 of\nthe empty tree (currently, but I don't suppose we are going to change the\ntree format anytime soon).\n\n-Peff\n"},{"id":"68628","messageId":"20080213105051.GA26522@coredump.intra.peff.net","threadId":"12050","inReplyTo":"20080213101649.GA18444@coredump.intra.peff.net","subject":"[PATCH] add--interactive: handle initial commit better","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-13T10:50:51Z","receivedAt":"2008-02-13T10:50:51Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 13, 2008 at 05:16:49AM -0500, Jeff King wrote:\n\n> However, I wonder if this is the best approach. It would be nice if\n> there were a shorthand for \"the empty tree\" for diffing, so you could\n> just diff against that rather than HEAD, and have the regular plumbing\n> generate.\n> \n> I suppose we could just create that tree object, though it adds a slight\n> amount of cruft to the object database.\n\nAnd here it is. I think this is a more sane approach in general than the\nlast patch. The only ugly thing is the empty tree hack, but that can be\naddressed with a patch to allow referencing the empty tree without it\nexisting in the object db.\n\n-- >8 --\n\nThere were several points where we looked at the HEAD\ncommit; for initial commits, this is meaningless. So instead\nwe:\n\n  - show staged status data as a diff against the empty tree\n    instead of HEAD\n  - show file diffs as creation events\n  - use \"git rm --cached\" to revert instead of going back to\n    the HEAD commit\n\nThe empty tree diff is a little hack-ish. We actually write\nthe empty tree object from a fake index using \"git\nwrite-tree\". This would be a bit cleaner if we could\nmagically reference the empty tree.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n git-add--interactive.perl |   64 +++++++++++++++++++++++++++++++++-----------\n 1 files changed, 48 insertions(+), 16 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 17ca5b8..bae631e 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -82,6 +82,28 @@ sub list_untracked {\n my $status_fmt = '%12s %12s %s';\n my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n \n+{\n+\tmy $initial;\n+\tsub is_initial_commit {\n+\t\t$initial = system('git rev-parse HEAD -- >/dev/null 2>&1') != 0\n+\t\t\tunless defined $initial;\n+\t\treturn $initial;\n+\t}\n+}\n+\n+{\n+\tmy $sha1;\n+\tsub get_empty_tree {\n+\t\tif (!$sha1) {\n+\t\t\tlocal $ENV{GIT_INDEX_FILE} = \"$GIT_DIR/empty_index\";\n+\t\t\t$sha1 = run_cmd_pipe(qw(git write-tree));\n+\t\t\tchomp $sha1;\n+\t\t\tunlink($ENV{GIT_INDEX_FILE});\n+\t\t}\n+\t\treturn $sha1;\n+\t}\n+}\n+\n # Returns list of hashes, contents of each of which are:\n # VALUE:\tpathname\n # BINARY:\tis a binary path\n@@ -103,8 +125,10 @@ sub list_modified {\n \t\treturn if (!@tracked);\n \t}\n \n+\tmy $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';\n \tfor (run_cmd_pipe(qw(git diff-index --cached\n-\t\t\t     --numstat --summary HEAD --), @tracked)) {\n+\t\t\t     --numstat --summary), $reference,\n+\t\t\t     '--', @tracked)) {\n \t\tif (($add, $del, $file) =\n \t\t    /^([-\\d]+)\t([-\\d]+)\t(.*)/) {\n \t\t\tmy ($change, $bin);\n@@ -476,21 +500,27 @@ sub revert_cmd {\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     list_modified());\n \tif (@update) {\n-\t\tmy @lines = run_cmd_pipe(qw(git ls-tree HEAD --),\n-\t\t\t\t\t map { $_->{VALUE} } @update);\n-\t\tmy $fh;\n-\t\topen $fh, '| git update-index --index-info'\n-\t\t    or die;\n-\t\tfor (@lines) {\n-\t\t\tprint $fh $_;\n+\t\tif (is_initial_commit()) {\n+\t\t\tsystem(qw(git rm --cached),\n+\t\t\t\tmap { $_->{VALUE} } @update);\n \t\t}\n-\t\tclose($fh);\n-\t\tfor (@update) {\n-\t\t\tif ($_->{INDEX_ADDDEL} &&\n-\t\t\t    $_->{INDEX_ADDDEL} eq 'create') {\n-\t\t\t\tsystem(qw(git update-index --force-remove --),\n-\t\t\t\t       $_->{VALUE});\n-\t\t\t\tprint \"note: $_->{VALUE} is untracked now.\\n\";\n+\t\telse {\n+\t\t\tmy @lines = run_cmd_pipe(qw(git ls-tree HEAD --),\n+\t\t\t\t\t\t map { $_->{VALUE} } @update);\n+\t\t\tmy $fh;\n+\t\t\topen $fh, '| git update-index --index-info'\n+\t\t\t    or die;\n+\t\t\tfor (@lines) {\n+\t\t\t\tprint $fh $_;\n+\t\t\t}\n+\t\t\tclose($fh);\n+\t\t\tfor (@update) {\n+\t\t\t\tif ($_->{INDEX_ADDDEL} &&\n+\t\t\t\t    $_->{INDEX_ADDDEL} eq 'create') {\n+\t\t\t\t\tsystem(qw(git update-index --force-remove --),\n+\t\t\t\t\t       $_->{VALUE});\n+\t\t\t\t\tprint \"note: $_->{VALUE} is untracked now.\\n\";\n+\t\t\t\t}\n \t\t\t}\n \t\t}\n \t\trefresh();\n@@ -956,7 +986,9 @@ sub diff_cmd {\n \t\t\t\t     HEADER => $status_head, },\n \t\t\t\t   @mods);\n \treturn if (!@them);\n-\tsystem(qw(git diff -p --cached HEAD --), map { $_->{VALUE} } @them);\n+\tmy $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';\n+\tsystem(qw(git diff -p --cached), $reference, '--',\n+\t\tmap { $_->{VALUE} } @them);\n }\n \n sub quit_cmd {\n-- \n1.5.4.1.1296.g34f89-dirty\n"},{"id":"68632","messageId":"20080213112504.GA26627@coredump.intra.peff.net","threadId":"12050","inReplyTo":"20080213105051.GA26522@coredump.intra.peff.net","subject":"Re: [PATCH] add--interactive: handle initial commit better","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-13T11:25:04Z","receivedAt":"2008-02-13T11:25:04Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 13, 2008 at 05:50:51AM -0500, Jeff King wrote:\n\n> And here it is. I think this is a more sane approach in general than the\n> last patch. The only ugly thing is the empty tree hack, but that can be\n> addressed with a patch to allow referencing the empty tree without it\n> existing in the object db.\n\nAnd this patch hard-codes the empty tree. I _think_ this shouldn't cause\nus any problems, as it just reuses the existing pretend_sha1_file\ninfrastructure. However that infrastructure is very rarely used.\n\nThis patch also contains the matching fix to git-add--interactive (on\ntop of my last patch). They should probably just be squashed together,\nbut I can submit a cleaned up 2-patch series if people agree that this\nis a good idea.\n\n-- >8 --\nhard-code the empty tree object\n\nNow any commands may reference the empty tree object by its\nsha1 (4b825dc642cb6eb9a060e54bf8d69288fbee4904). This is\nuseful for showing some diffs, especially for initial\ncommits.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n git-add--interactive.perl |   13 ++-----------\n sha1_file.c               |   11 +++++++++++\n 2 files changed, 13 insertions(+), 11 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex bae631e..a0a81f1 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -91,17 +91,8 @@ my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n \t}\n }\n \n-{\n-\tmy $sha1;\n-\tsub get_empty_tree {\n-\t\tif (!$sha1) {\n-\t\t\tlocal $ENV{GIT_INDEX_FILE} = \"$GIT_DIR/empty_index\";\n-\t\t\t$sha1 = run_cmd_pipe(qw(git write-tree));\n-\t\t\tchomp $sha1;\n-\t\t\tunlink($ENV{GIT_INDEX_FILE});\n-\t\t}\n-\t\treturn $sha1;\n-\t}\n+sub get_empty_tree {\n+\treturn '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n }\n \n # Returns list of hashes, contents of each of which are:\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 4179949..1a6c7c8 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1845,6 +1845,15 @@ static struct cached_object {\n } *cached_objects;\n static int cached_object_nr, cached_object_alloc;\n \n+static struct cached_object empty_tree = {\n+\t/* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */\n+\t\"\\x4b\\x82\\x5d\\xc6\\x42\\xcb\\x6e\\xb9\\xa0\\x60\"\n+\t\"\\xe5\\x4b\\xf8\\xd6\\x92\\x88\\xfb\\xee\\x49\\x04\",\n+\tOBJ_TREE,\n+\t\"\",\n+\t0\n+};\n+\n static struct cached_object *find_cached_object(const unsigned char *sha1)\n {\n \tint i;\n@@ -1854,6 +1863,8 @@ static struct cached_object *find_cached_object(const unsigned char *sha1)\n \t\tif (!hashcmp(co->sha1, sha1))\n \t\t\treturn co;\n \t}\n+\tif (!hashcmp(sha1, empty_tree.sha1))\n+\t\treturn &empty_tree;\n \treturn NULL;\n }\n \n-- \n1.5.4.1.1297.g3482b-dirty\n"},{"id":"68633","messageId":"7v63wtqejf.fsf@gitster.siamese.dyndns.org","threadId":"12050","inReplyTo":"20080213101649.GA18444@coredump.intra.peff.net","subject":"Re: [Bug] git add -i fails in multiple ways prior to first commit.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-13T11:30:44Z","receivedAt":"2008-02-13T11:30:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> However, I wonder if this is the best approach. It would be nice if\n> there were a shorthand for \"the empty tree\" for diffing, so you could\n> just diff against that rather than HEAD, and have the regular plumbing\n> generate.\n\nI guess you can set your worktree to an empty directory and run\ndiff-files backwards, like perhaps:\n\n\tmkdir /var/tmp/empty\n        (cd .git && GIT_WORK_TREE=/var/tmp/empty git diff -R)\n\nHave I tried it?  No --- I am not sick enough to be motivated.\n"},{"id":"68635","messageId":"20080213113418.GA2736@coredump.intra.peff.net","threadId":"12050","inReplyTo":"7v63wtqejf.fsf@gitster.siamese.dyndns.org","subject":"Re: [Bug] git add -i fails in multiple ways prior to first commit.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-13T11:34:18Z","receivedAt":"2008-02-13T11:34:18Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 13, 2008 at 03:30:44AM -0800, Junio C Hamano wrote:\n\n> > However, I wonder if this is the best approach. It would be nice if\n> > there were a shorthand for \"the empty tree\" for diffing, so you could\n> > just diff against that rather than HEAD, and have the regular plumbing\n> > generate.\n> \n> I guess you can set your worktree to an empty directory and run\n> diff-files backwards, like perhaps:\n> \n> \tmkdir /var/tmp/empty\n>         (cd .git && GIT_WORK_TREE=/var/tmp/empty git diff -R)\n> \n> Have I tried it?  No --- I am not sick enough to be motivated.\n\nActually, I thought of that already. It does work, though when I tried\nit, I failed to 'cd .git' which broke it. But yes, I think it is a\nnastier solution than just using the \"virtual\" empty tree.\n\n-Peff\n"},{"id":"68638","messageId":"alpine.LSU.1.00.0802131213270.30505@racer.site","threadId":"12050","inReplyTo":"20080213112504.GA26627@coredump.intra.peff.net","subject":"Re: [PATCH] add--interactive: handle initial commit better","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-13T12:19:26Z","receivedAt":"2008-02-13T12:19:26Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 13 Feb 2008, Jeff King wrote:\n\n> diff --git a/sha1_file.c b/sha1_file.c\n> index 4179949..1a6c7c8 100644\n> --- a/sha1_file.c\n> +++ b/sha1_file.c\n> @@ -1845,6 +1845,15 @@ static struct cached_object {\n>  } *cached_objects;\n>  static int cached_object_nr, cached_object_alloc;\n>  \n> +static struct cached_object empty_tree = {\n> +\t/* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */\n> +\t\"\\x4b\\x82\\x5d\\xc6\\x42\\xcb\\x6e\\xb9\\xa0\\x60\"\n> +\t\"\\xe5\\x4b\\xf8\\xd6\\x92\\x88\\xfb\\xee\\x49\\x04\",\n> +\tOBJ_TREE,\n> +\t\"\",\n> +\t0\n> +};\n> +\n>  static struct cached_object *find_cached_object(const unsigned char *sha1)\n>  {\n>  \tint i;\n> @@ -1854,6 +1863,8 @@ static struct cached_object *find_cached_object(const unsigned char *sha1)\n>  \t\tif (!hashcmp(co->sha1, sha1))\n>  \t\t\treturn co;\n>  \t}\n> +\tif (!hashcmp(sha1, empty_tree.sha1))\n> +\t\treturn &empty_tree;\n>  \treturn NULL;\n>  }\n\nHeh.  This is cute.  But it is also a bit hard to reference, no?  I mean, \nyou have to remember the SHA-1 of it...\n\nMaybe {} ?\n\nCiao,\nDscho\n"},{"id":"68642","messageId":"m3fxvxc87u.fsf@localhost.localdomain","threadId":"12050","inReplyTo":"alpine.LSU.1.00.0802131213270.30505@racer.site","subject":"Re: [PATCH] add--interactive: handle initial commit better","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-02-13T13:11:10Z","receivedAt":"2008-02-13T13:11:10Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Wed, 13 Feb 2008, Jeff King wrote:\n> >  \t}\n> > +\tif (!hashcmp(sha1, empty_tree.sha1))\n> > +\t\treturn &empty_tree;\n> >  \treturn NULL;\n> >  }\n> \n> Heh.  This is cute.  But it is also a bit hard to reference, no?  I mean, \n> you have to remember the SHA-1 of it...\n> \n> Maybe {} ?\n\nOr NULL? You can do this even without modifying git code, I think, by\nadding refs/NULL with appropriate sha-1...\n\n^{tree} I think resolves to HEAD^{tree}\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"68643","messageId":"20080213131523.GA3266@coredump.intra.peff.net","threadId":"12050","inReplyTo":"m3fxvxc87u.fsf@localhost.localdomain","subject":"Re: [PATCH] add--interactive: handle initial commit better","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-02-13T13:15:23Z","receivedAt":"2008-02-13T13:15:23Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 13, 2008 at 05:11:10AM -0800, Jakub Narebski wrote:\n\n> > Heh.  This is cute.  But it is also a bit hard to reference, no?  I mean, \n> > you have to remember the SHA-1 of it...\n> > \n> > Maybe {} ?\n> \n> Or NULL? You can do this even without modifying git code, I think, by\n> adding refs/NULL with appropriate sha-1...\n\nYou still need my patch, unless you want to create the empty tree object\nin the databsae. The existence of the object and its name are separate.\nIf you want to add a magic ref or syntax that maps to the correct SHA-1,\nthen that makes sense to me.\n\n-Peff\n"},{"id":"68644","messageId":"alpine.LSU.1.00.0802131321140.30505@racer.site","threadId":"12050","inReplyTo":"m3fxvxc87u.fsf@localhost.localdomain","subject":"Re: [PATCH] add--interactive: handle initial commit better","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-13T13:22:06Z","receivedAt":"2008-02-13T13:22:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 13 Feb 2008, Jakub Narebski wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > On Wed, 13 Feb 2008, Jeff King wrote:\n> > >  \t}\n> > > +\tif (!hashcmp(sha1, empty_tree.sha1))\n> > > +\t\treturn &empty_tree;\n> > >  \treturn NULL;\n> > >  }\n> > \n> > Heh.  This is cute.  But it is also a bit hard to reference, no?  I mean, \n> > you have to remember the SHA-1 of it...\n> > \n> > Maybe {} ?\n> \n> Or NULL?\n\nI was talking about a special handling: \"{}\" is not a valid refname.  But \n\"NULL\" _is_.  So I wanted to avoid that \"NULL\" explicitely.\n\nCiao,\nDscho\n"},{"id":"68650","messageId":"alpine.LSU.1.00.0802131344121.30505@racer.site","threadId":"12050","inReplyTo":"alpine.LSU.1.00.0802131321140.30505@racer.site","subject":"Re: [PATCH] add--interactive: handle initial commit better","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-13T13:45:59Z","receivedAt":"2008-02-13T13:45:59Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 13 Feb 2008, Johannes Schindelin wrote:\n\n> On Wed, 13 Feb 2008, Jakub Narebski wrote:\n> \n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > On Wed, 13 Feb 2008, Jeff King wrote:\n> > > >  \t}\n> > > > +\tif (!hashcmp(sha1, empty_tree.sha1))\n> > > > +\t\treturn &empty_tree;\n> > > >  \treturn NULL;\n> > > >  }\n> > > \n> > > Heh.  This is cute.  But it is also a bit hard to reference, no?  I \n> > > mean, you have to remember the SHA-1 of it...\n> > > \n> > > Maybe {} ?\n\nIOW something like this (on top of your two patches; feel free to merge):\n\n-- snipsnap --\n[PATCH] Make {} synonymous to the empty tree\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n cache.h     |    5 +++++\n sha1_file.c |    4 +---\n sha1_name.c |    5 +++++\n 3 files changed, 11 insertions(+), 3 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex f4c56fa..b71f772 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -266,6 +266,11 @@ static inline enum object_type object_type(unsigned int mode)\n #define INFOATTRIBUTES_FILE \"info/attributes\"\n #define ATTRIBUTE_MACRO_PREFIX \"[attr]\"\n \n+/* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */\n+#define EMPTY_TREE_SHA1 (unsigned char *)\\\n+\t\"\\x4b\\x82\\x5d\\xc6\\x42\\xcb\\x6e\\xb9\\xa0\\x60\" \\\n+\t\"\\xe5\\x4b\\xf8\\xd6\\x92\\x88\\xfb\\xee\\x49\\x04\"\n+\n extern int is_bare_repository_cfg;\n extern int is_bare_repository(void);\n extern int is_inside_git_dir(void);\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 1a6c7c8..cba629a 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1846,9 +1846,7 @@ static struct cached_object {\n static int cached_object_nr, cached_object_alloc;\n \n static struct cached_object empty_tree = {\n-\t/* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */\n-\t\"\\x4b\\x82\\x5d\\xc6\\x42\\xcb\\x6e\\xb9\\xa0\\x60\"\n-\t\"\\xe5\\x4b\\xf8\\xd6\\x92\\x88\\xfb\\xee\\x49\\x04\",\n+\tEMPTY_TREE_SHA1,\n \tOBJ_TREE,\n \t\"\",\n \t0\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 6cfd1f9..3a39a55 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -760,5 +760,10 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)\n \t\t\treturn get_tree_entry(tree_sha1, cp+1, sha1, mode);\n \t\t}\n \t}\n+\tif (ret && !strcmp(name, \"{}\")) {\n+\t\t*mode = 0755;\n+\t\thashcpy(sha1, EMPTY_TREE_SHA1);\n+\t\tret = 0;\n+\t}\n \treturn ret;\n }\n"}]}