diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-06-03 10:24:02 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-06-03 13:00:54 -0700 |
commit | e813563bc0cc911188309ca8a2eb42228c38cf5e (patch) | |
tree | 577182679f682e06d6e4678628b5afb515d09860 | |
parent | f86f31ab33c3406adebbb9f9f61be550dcc5a472 (diff) | |
download | git-jc/log-missing-default-HEAD.tar.gz |
log: diagnose empty HEAD more clearlyjc/log-missing-default-HEAD
If you init or clone an empty repository, the initial message from
running "git log" is not very friendly:
$ git init
Initialized empty Git repository in /home/peff/foo/.git/
$ git log
fatal: bad default revision 'HEAD'
The user didn't say anything about 'HEAD'. This error is given only
because "git log" and friends blindly default to 'HEAD' without even
checking if that is a sensible default to use. We can instead detect
this case and give them a more friendly error message.
$ git log
fatal: you do not have a commit yet on your branch
In a future version of Git, if we are willing to accept an
incompatiblity to give a better end-user experience like we did at
2.0, it may even make more sense to turn this an non-error in such a
future version of Git. If you have one commit and ask "log", you
get one commit back. If you have no commit and ask "log", it is OK
to say that you should get nothing back without fuss. But that is
outside the scope of this change.
Note that we still do fail if the user explicitly says HEAD from the
command line, and this is very much deliberate:
$ git log HEAD --
fatal: bad revision 'HEAD'
$ git log HEAD
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
In these cases, unlike the parameter-less case where the command
implicitly defaults to use "HEAD", the user claims HEAD must be
usable as a valid committish object name, and we are diagnosing
that the claim is false and issuing an error.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin/log.c | 24 | ||||
-rw-r--r-- | revision.h | 1 | ||||
-rwxr-xr-x | t/t4202-log.sh | 11 |
3 files changed, 32 insertions, 4 deletions
diff --git a/builtin/log.c b/builtin/log.c index 4c4e6be28c..b07c89dfa9 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -148,6 +148,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT; argc = setup_revisions(argc, argv, rev, opt); + if (!rev->pending.nr && !opt->def) { + /* NEEDSWORK: use opt->def_HEAD_missing */ + die("you do not have a commit yet on your branch"); + } + /* Any arguments at this point are not recognized */ if (argc > 1) die(_("unrecognized argument: %s"), argv[1]); @@ -404,6 +409,17 @@ static int git_log_config(const char *var, const char *value, void *cb) return git_diff_ui_config(var, value, cb); } +static void default_to_head_if_exists(struct setup_revision_opt *opt) +{ + unsigned char unused[20]; + int flags; + + if (resolve_ref_unsafe("HEAD", 0, unused, &flags)) + opt->def = "HEAD"; + else + opt->def_HEAD_missing = flags; +} + int cmd_whatchanged(int argc, const char **argv, const char *prefix) { struct rev_info rev; @@ -416,7 +432,7 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) rev.diff = 1; rev.simplify_history = 0; memset(&opt, 0, sizeof(opt)); - opt.def = "HEAD"; + default_to_head_if_exists(&opt); opt.revarg_opt = REVARG_COMMITTISH; cmd_log_init(argc, argv, prefix, &rev, &opt); if (!rev.diffopt.output_format) @@ -530,7 +546,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) rev.diffopt.stat_width = -1; /* Scale to real terminal size */ memset(&opt, 0, sizeof(opt)); - opt.def = "HEAD"; + default_to_head_if_exists(&opt); opt.tweak = show_rev_tweak_rev; cmd_log_init(argc, argv, prefix, &rev, &opt); @@ -607,7 +623,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) init_reflog_walk(&rev.reflog_info); rev.verbose_header = 1; memset(&opt, 0, sizeof(opt)); - opt.def = "HEAD"; + default_to_head_if_exists(&opt); cmd_log_init_defaults(&rev); rev.abbrev_commit = 1; rev.commit_format = CMIT_FMT_ONELINE; @@ -629,7 +645,7 @@ int cmd_log(int argc, const char **argv, const char *prefix) init_revisions(&rev, prefix); rev.always_show_header = 1; memset(&opt, 0, sizeof(opt)); - opt.def = "HEAD"; + default_to_head_if_exists(&opt); opt.revarg_opt = REVARG_COMMITTISH; cmd_log_init(argc, argv, prefix, &rev, &opt); return cmd_log_walk(&rev); diff --git a/revision.h b/revision.h index 0ea8b4e255..0838ef1db3 100644 --- a/revision.h +++ b/revision.h @@ -228,6 +228,7 @@ extern volatile show_early_output_fn_t show_early_output; struct setup_revision_opt { const char *def; + int def_HEAD_missing; void (*tweak)(struct rev_info *, struct setup_revision_opt *); const char *submodule; int assume_dashdash; diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 1b2e981a00..658c440689 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -871,4 +871,15 @@ test_expect_success 'log --graph --no-walk is forbidden' ' test_must_fail git log --graph --no-walk ' +test_expect_success 'log diagnoses bogus HEAD' ' + git init empty && + test_must_fail git -C empty log 2>stderr && + test_i18ngrep "you do not have a commit yet" stderr && + git rev-parse HEAD >empty/.git/refs/heads/master && + test_must_fail git -C empty log 2>stderr && + test_i18ngrep "bad object HEAD" stderr && + test_must_fail git -C empty log --default totally-bogus 2>stderr && + test_i18ngrep bad.default.revision stderr +' + test_done |