reset: give better reflog messages

The reset command creates its reflog entry from argv. However, it does so after having run parse_options, which means the only thing left in argv is any non-option arguments. Thus you would end up with confusing reflog entries like: $ git reset --hard HEAD^ $ git reset --soft HEAD@{1} $ git log -2 -g --oneline 8e46cad HEAD@{0}: HEAD@{1}: updating HEAD 1eb9486 HEAD@{1}: HEAD^: updating HEAD However, we must also consider that some scripts may set GIT_REFLOG_ACTION before calling reset, and we need to show their reflog action (with our text appended). For example: rebase -i (squash): updating HEAD On top of that, we also set the ORIG_HEAD reflog action (even though it doesn't generally exist). In that case, the reset argument is somewhat meaningless, as it has nothing to do with what's in ORIG_HEAD. This patch changes the reset reflog code to show: $GIT_REFLOG_ACTION: updating {HEAD,ORIG_HEAD} as before, but only if GIT_REFLOG_ACTION is set. Otherwise, show: reset: moving to $rev for HEAD, and: reset: updating ORIG_HEAD for ORIG_HEAD (this is still somewhat superfluous, since we are in the ORIG_HEAD reflog, obviously, but at least we now mention which command was used to update it). While we're at it, we can clean up the code a bit: - Use strbufs to make the message. - Use the "rev" parameter instead of showing all options. This makes more sense, since it is the only thing impacting the writing of the ref. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 22, 2011 at 10:12 UTC d04520e3446acdcbdf1d30c812aa31d6a003c171
2 files changed +20 -37
builtin/reset.c
+16 -33
@@ -33,25 +33,6 @@ static const char *reset_type_names[] = {
33 N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL
34 };
35
36 -static char *args_to_str(const char **argv)
37 -{
38 - char *buf = NULL;
39 - unsigned long len, space = 0, nr = 0;
40 -
41 - for (; *argv; argv++) {
42 - len = strlen(*argv);
43 - ALLOC_GROW(buf, nr + 1 + len, space);
44 - if (nr)
45 - buf[nr++] = ' ';
46 - memcpy(buf + nr, *argv, len);
47 - nr += len;
48 - }
49 - ALLOC_GROW(buf, nr + 1, space);
50 - buf[nr] = '\0';
51 -
52 - return buf;
53 -}
54 -
36 static inline int is_merge(void)
37 {
38 return !access(git_path("MERGE_HEAD"), F_OK);
@@ -215,14 +196,18 @@ static int read_from_tree(const char *prefix, const char **argv,
196 return update_index_refresh(index_fd, lock, refresh_flags);
197 }
198
218 -static void prepend_reflog_action(const char *action, char *buf, size_t size)
199 +static void set_reflog_message(struct strbuf *sb, const char *action,
200 + const char *rev)
201 {
220 - const char *sep = ": ";
202 const char *rla = getenv("GIT_REFLOG_ACTION");
222 - if (!rla)
223 - rla = sep = "";
224 - if (snprintf(buf, size, "%s%s%s", rla, sep, action) >= size)
225 - warning(_("Reflog action message too long: %.*s..."), 50, buf);
203 +
204 + strbuf_reset(sb);
205 + if (rla)
206 + strbuf_addf(sb, "%s: %s", rla, action);
207 + else if (rev)
208 + strbuf_addf(sb, "reset: moving to %s", rev);
209 + else
210 + strbuf_addf(sb, "reset: %s", action);
211 }
212
213 static void die_if_unmerged_cache(int reset_type)
@@ -241,7 +226,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
226 unsigned char sha1[20], *orig = NULL, sha1_orig[20],
227 *old_orig = NULL, sha1_old_orig[20];
228 struct commit *commit;
244 - char *reflog_action, msg[1024];
229 + struct strbuf msg = STRBUF_INIT;
230 const struct option options[] = {
231 OPT__QUIET(&quiet, "be quiet, only report errors"),
232 OPT_SET_INT(0, "mixed", &reset_type,
@@ -261,8 +246,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
246
247 argc = parse_options(argc, argv, prefix, options, git_reset_usage,
248 PARSE_OPT_KEEP_DASHDASH);
264 - reflog_action = args_to_str(argv);
265 - setenv("GIT_REFLOG_ACTION", reflog_action, 0);
249
250 /*
251 * Possible arguments are:
@@ -357,13 +340,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
340 old_orig = sha1_old_orig;
341 if (!get_sha1("HEAD", sha1_orig)) {
342 orig = sha1_orig;
360 - prepend_reflog_action("updating ORIG_HEAD", msg, sizeof(msg));
361 - update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
343 + set_reflog_message(&msg, "updating ORIG_HEAD", NULL);
344 + update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
345 }
346 else if (old_orig)
347 delete_ref("ORIG_HEAD", old_orig, 0);
365 - prepend_reflog_action("updating HEAD", msg, sizeof(msg));
366 - update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
348 + set_reflog_message(&msg, "updating HEAD", rev);
349 + update_ref_status = update_ref(msg.buf, "HEAD", sha1, orig, 0, MSG_ON_ERR);
350
351 switch (reset_type) {
352 case HARD:
@@ -380,7 +363,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
363
364 remove_branch_state();
365
383 - free(reflog_action);
366 + strbuf_release(&msg);
367
368 return update_ref_status;
369 }
t/t1412-reflog-loop.sh
+4 -4
@@ -21,10 +21,10 @@ test_expect_success 'setup reflog with alternating commits' '
21
22 test_expect_success 'reflog shows all entries' '
23 cat >expect <<-\EOF
24 - topic@{0} two: updating HEAD
25 - topic@{1} one: updating HEAD
26 - topic@{2} two: updating HEAD
27 - topic@{3} one: updating HEAD
24 + topic@{0} reset: moving to two
25 + topic@{1} reset: moving to one
26 + topic@{2} reset: moving to two
27 + topic@{3} reset: moving to one
28 topic@{4} branch: Created from HEAD
29 EOF
30 git log -g --format="%gd %gs" topic >actual &&