Re: [PATCH] reset cached ident date before creating objects
From: Junio C Hamano <hidden>
Date: 2016-07-29 18:16:02
Jeff King [off-list ref] writes:
Linus suggested resetting the timestamp after making the commit, to clear the way for the next commit. But if we reset any cached value _before_ making the commit, this has a few advantages:
I guess our mails crossed ;-).
It does feel a little backwards to cache by default, and then try to catch all the places that want to reset. Another way of thinking about it would be to almost _never_ cache, but let a few callsites like (the commit object creation) explicitly ask for a stable timestamp between the author and committer.
... and the reflog? I would say that the approach taken by this version is perfectly sensible, if we don't look at it as a "cache" and instead look at it as a "snapshot" of the clock for the duration of the operation. "reset" is like "now we are starting another operation, so grab a snapshot please". The changes to both tagging and committing look sensible. Thanks.
quoted hunk
-- >8 -- Subject: reset cached ident date before creating objects When we compute the date to put in author/committer lines of commits, or tagger lines of tags, we get the current date once and then cache it for the rest of the program. This is a good thing in some cases, like "git commit", because it means we do not racily assign different times to the author/committer fields of a single commit object. But as more programs start to make many commits in a single process (e.g., the recently builtin "git am"), it means that you'll get long strings of commits with identical committer timestamps (whereas before, we invoked "git commit" many times and got true timestamps). This patch addresses it by letting callers reset the cached time, which means they'll get a fresh time on their next call to git_committer_info() or git_author_info(). We do so automatically before filling in the ident fields of commit and tag objects. That retains the property that committers and authors in a single object will match, but means that separate objects we create should always get their own fresh timestamps. There's no automated test, because it would be inherently racy (it depends on whether the program takes multiple seconds to run). But you can see the effect with something like: # make a fake 100-patch series; use --first-parent # so that we pretend merges are just more patches top=$(git rev-parse HEAD) bottom=$(git rev-list --first-parent -100 HEAD | tail -n 1) git log --format=email --reverse --first-parent \ --binary -m -p $bottom..$top >patch # now apply it; this presumably takes multiple seconds git checkout --detach $bottom git am <patch # now count the number of distinct committer times; # prior to this patch, there would only be one, but # now we'd typically see several. git log --format=%ct $bottom.. | sort -u Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Jeff King <redacted> --- builtin/tag.c | 1 + cache.h | 1 + commit.c | 1 + ident.c | 5 +++++ 4 files changed, 8 insertions(+)diff --git a/builtin/tag.c b/builtin/tag.c index 50e4ae5..3025e7f 100644 --- a/builtin/tag.c +++ b/builtin/tag.c@@ -225,6 +225,7 @@ static void create_tag(const unsigned char *object, const char *tag, if (type <= OBJ_NONE) die(_("bad object type.")); + reset_ident_date(); header_len = snprintf(header_buf, sizeof(header_buf), "object %s\n" "type %s\n"diff --git a/cache.h b/cache.h index b5f76a4..31e65f9 100644 --- a/cache.h +++ b/cache.h@@ -1269,6 +1269,7 @@ extern const char *ident_default_email(void); extern const char *git_editor(void); extern const char *git_pager(int stdout_is_tty); extern int git_ident_config(const char *, const char *, void *); +extern void reset_ident_date(void); struct ident_split { const char *name_begin;diff --git a/commit.c b/commit.c index 71a360d..7ddbffe 100644 --- a/commit.c +++ b/commit.c@@ -1548,6 +1548,7 @@ int commit_tree_extended(const char *msg, size_t msg_len, } /* Person/date information */ + reset_ident_date(); if (!author) author = git_author_info(IDENT_STRICT); strbuf_addf(&buffer, "author %s\n", author);diff --git a/ident.c b/ident.c index 139c528..e20a772 100644 --- a/ident.c +++ b/ident.c@@ -184,6 +184,11 @@ static const char *ident_default_date(void) return git_default_date.buf; } +void reset_ident_date(void) +{ + strbuf_reset(&git_default_date); +} + static int crud(unsigned char c) { return c <= 32 ||