summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2015-06-03 10:24:02 -0700
committerJunio C Hamano <gitster@pobox.com>2015-06-03 13:00:54 -0700
commite813563bc0cc911188309ca8a2eb42228c38cf5e (patch)
tree577182679f682e06d6e4678628b5afb515d09860
parentf86f31ab33c3406adebbb9f9f61be550dcc5a472 (diff)
downloadgit-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.c24
-rw-r--r--revision.h1
-rwxr-xr-xt/t4202-log.sh11
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