• J
    am: reset cached ident date for each patch · 4d9c7e6f
    Jeff King 提交于
    When we compute the date to go 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(). The first
    caller to do so is "git am", which resets the time for each
    patch it applies.
    
    It would be nice if we could just do this automatically
    before filling in the ident fields of commit and tag
    objects. Unfortunately, it's hard to know where a particular
    logical operation begins and ends.
    
    For instance, if commit_tree_extended() were to call
    reset_ident_date() before getting the committer/author
    ident, that doesn't quite work; sometimes the author info is
    passed in to us as a parameter, and it may or may not have
    come from a previous call to ident_default_date(). So in
    those cases, we lose the property that the committer and the
    author timestamp always match.
    
    You could similarly put a date-reset at the end of
    commit_tree_extended(). That actually works in the current
    code base, but it's fragile. It makes the assumption that
    after commit_tree_extended() finishes, the caller has no
    other operations that would logically want to fall into the
    same timestamp.
    
    So instead we provide the tool to easily do the reset, and
    let the high-level callers use it to annotate their own
    logical operations.
    
    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
      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: NLinus Torvalds <torvalds@linux-foundation.org>
    Helped-by: NPaul Tan <pyokagan@gmail.com>
    Signed-off-by: NJeff King <peff@peff.net>
    Signed-off-by: NJunio C Hamano <gitster@pobox.com>
    4d9c7e6f
cache.h 65.2 KB