1. 17 5月, 2013 8 次提交
    • K
      revision.c: make default history consider bottom commits · 141efdba
      Kevin Bracey 提交于
      Previously, the default history treated bottom commits the same as any
      other UNINTERESTING commit, which could force it down side branches.
      
      Consider the following history:
      
         *A--*B---D--*F         * marks !TREESAME parent paths
           \     /*
            `-C-'
      
      When requesting "B..F", B is UNINTERESTING but TREESAME to D. C is
      !UNINTERESTING.
      
      So default following would go from D into the irrelevant side branch C
      to A, rather than to B.  Note also that if there had been an extra
      !UNINTERESTING commit B1 between B and D, it wouldn't have gone down C.
      
      Change the default following to test relevant_commit() instead of
      !UNINTERESTING, so it can proceed straight from D to B, thus finishing
      the traversal of that path.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      141efdba
    • K
      revision.c: don't show all merges for --parents · bf3418b0
      Kevin Bracey 提交于
      When using --parents or --children, get_commit_action() previously showed
      all merges, even if TREESAME to both parents.
      
      This was intended to tie together the topology of the rewritten parents,
      but it was excessive - in fact we only need to show merges that have two
      or more relevant parents. Merges at the boundary do not necessarily need
      to be shown.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      bf3418b0
    • K
      revision.c: discount side branches when computing TREESAME · 4d826608
      Kevin Bracey 提交于
      Use the BOTTOM flag to define relevance for pruning. Relevant commits
      are those that are !UNINTERESTING or BOTTOM, and this allows us to
      identify irrelevant side branches (UNINTERESTING && !BOTTOM).
      
      If a merge has relevant parents, and it is TREESAME to them, then do not
      let irrelevant parents cause the merge to be treated as !TREESAME.
      
      When considering simplification, don't always include all merges -
      merges with exactly one relevant parent can be simplified, if TREESAME
      according to the above rule.
      
      These two changes greatly increase simplification in limited, pruned
      revision lists.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4d826608
    • K
      revision.c: add BOTTOM flag for commits · 7f34a46f
      Kevin Bracey 提交于
      When performing edge-based operations on the revision graph, it can be
      useful to be able to identify the INTERESTING graph's connection(s) to
      the bottom commit(s) specified by the user.
      
      Conceptually when the user specifies "A..B" (== B ^A), they are asking
      for the history from A to B. The first connection from A onto the
      INTERESTING graph is part of that history, and should be considered. If
      we consider only INTERESTING nodes and their connections, then we're
      really only considering the history from A's immediate descendants to B.
      
      This patch does not change behaviour, but adds a new BOTTOM flag to
      indicate the bottom commits specified by the user, ready to be used by
      following patches.
      
      We immediately use the BOTTOM flag to return collect_bottom_commits() to
      its original approach of examining the pending commit list rather than
      the command line. This will ensure alignment of the definition of
      "bottom" with future patches.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      7f34a46f
    • K
      simplify-merges: drop merge from irrelevant side branch · 143f1eaf
      Kevin Bracey 提交于
      Reimplement commit 4b7f53da on top of the new simplify-merges
      infrastructure, tightening the condition to only consider root parents;
      the original version incorrectly dropped parents that were TREESAME to
      anything.
      
      Original log message follows.
      
      The merge simplification rule stated in 6546b593 (revision traversal:
      show full history with merge simplification, 2008-07-31) still
      treated merge commits too specially.  Namely, in a history with this
      shape:
      
      	---o---o---M
      	          /
               x---x---x
      
      where three 'x' were on a history completely unrelated to the main
      history 'o' and do not touch any of the paths we are following, we
      still said that after simplifying all of the parents of M, 'x'
      (which is the leftmost 'x' that rightmost 'x simplifies down to) and
      'o' (which would be the last commit on the main history that touches
      the paths we are following) are independent from each other, and
      both need to be kept.
      
      That is incorrect; when the side branch 'x' never touches the paths,
      it should be removed to allow M to simplify down to the last commit
      on the main history that touches the paths.
      Suggested-by: NJunio C Hamano <gitster@pobox.com>
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      143f1eaf
    • K
      simplify-merges: never remove all TREESAME parents · 9c129eab
      Kevin Bracey 提交于
      When simplifying an odd merge, such as one that used "-s ours", we may
      find ourselves TREESAME to apparently redundant parents. Prevent
      simplify_merges() from removing every TREESAME parent; if this would
      happen reinstate the first TREESAME parent - the one that the default
      log would have followed.
      
      This avoids producing a totally disjoint history from the default log
      when the default log is a better explanation of the end result, and aids
      visualisation of odd merges.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      9c129eab
    • K
      revision.c: Make --full-history consider more merges · d0af663e
      Kevin Bracey 提交于
      History simplification previously always treated merges as TREESAME
      if they were TREESAME to any parent.
      
      While this was consistent with the default behaviour, this could be
      extremely unhelpful when searching detailed history, and could not be
      overridden. For example, if a merge had ignored a change, as if by "-s
      ours", then:
      
        git log -m -p --full-history -Schange file
      
      would successfully locate "change"'s addition but would not locate the
      merge that resolved against it.
      
      Futher, simplify_merges could drop the actual parent that a commit
      was TREESAME to, leaving it as a normal commit marked TREESAME that
      isn't actually TREESAME to its remaining parent.
      
      Now redefine a commit's TREESAME flag to be true only if a commit is
      TREESAME to _all_ of its parents. This doesn't affect either the default
      simplify_history behaviour (because partially TREESAME merges are turned
      into normal commits), or full-history with parent rewriting (because all
      merges are output). But it does affect other modes. The clearest
      difference is that --full-history will show more merges - sufficient to
      ensure that -m -p --full-history log searches can really explain every
      change to the file, including those changes' ultimate fate in merges.
      
      Also modify simplify_merges to recalculate TREESAME after removing
      a parent. This is achieved by storing per-parent TREESAME flags on the
      initial scan, so the combined flag can be easily recomputed.
      
      This fixes some t6111 failures, but creates a couple of new ones -
      we are now showing some merges that don't need to be shown.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      d0af663e
    • K
      revision.c: treat A...B merge bases as if manually specified · a765499a
      Kevin Bracey 提交于
      The documentation assures users that "A...B" is defined as "A B --not
      $(git merge-base --all A B)". This wasn't in fact quite true, because
      the calculated merge bases were not sent to add_rev_cmdline().
      
      The main effect of this was that although
      
        git rev-list --ancestry-path A B --not $(git merge-base --all A B)
      
      worked, the simpler form
      
        git rev-list --ancestry-path A...B
      
      failed with a "no bottom commits" error.
      
      Other potential users of bottom commits could also be affected by this
      problem, if they examine revs->cmdline_info; I came across the issue in
      my proposed history traversal refinements series.
      
      So ensure that the calculated merge bases are sent to add_rev_cmdline(),
      flagged with new 'whence' enum value REV_CMD_MERGE_BASE.
      Signed-off-by: NKevin Bracey <kevin@bracey.fi>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      a765499a
  2. 19 4月, 2013 1 次提交
  3. 17 4月, 2013 1 次提交
    • T
      read_revisions_from_stdin: make copies for handle_revision_arg · 70d26c6e
      Thomas Rast 提交于
      read_revisions_from_stdin() has passed pointers to its read buffer
      down to handle_revision_arg() since its inception way back in 42cabc34
      (Teach rev-list an option to read revs from the standard input.,
      2006-09-05).  Even back then, this was a bug: through
      add_pending_object, the argument was recorded in the object_array's
      'name' field.
      
      Fix it by making a copy whenever read_revisions_from_stdin() passes an
      argument down the callchain.  The other caller runs handle_revision_arg()
      on argv[], where it would be redundant to make a copy.
      Signed-off-by: NThomas Rast <trast@inf.ethz.ch>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      70d26c6e
  4. 09 4月, 2013 1 次提交
  5. 23 3月, 2013 1 次提交
    • K
      Fix revision walk for commits with the same dates · c19d1b4e
      Kacper Kornet 提交于
      Logic in still_interesting function allows to stop the commits
      traversing if the oldest processed commit is not older then the
      youngest commit on the list to process and the list contains only
      commits marked as not interesting ones. It can be premature when dealing
      with a set of coequal commits. For example git rev-list A^! --not B
      provides wrong answer if all commits in the range A..B had the same
      commit time and there are more then 7 of them.
      
      To fix this problem the relevant part of the logic in still_interesting
      is changed to: the walk can be stopped if the oldest processed commit is
      younger then the youngest commit on the list to processed.
      Signed-off-by: NKacper Kornet <draenog@pld-linux.org>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      c19d1b4e
  6. 12 2月, 2013 1 次提交
    • J
      log: re-encode commit messages before grepping · 04deccda
      Jeff King 提交于
      If you run "git log --grep=foo", we will run your regex on
      the literal bytes of the commit message. This can provide
      confusing results if the commit message is not in the same
      encoding as your grep expression (or worse, you have commits
      in multiple encodings, in which case your regex would need
      to be written to match either encoding). On top of this, we
      might also be grepping in the commit's notes, which are
      already re-encoded, potentially leading to grepping in a
      buffer with mixed encodings concatenated. This is insanity,
      but most people never noticed, because their terminal and
      their commit encodings all match.
      
      Instead, let's massage the to-be-grepped commit into a
      standardized encoding. There is not much point in adding a
      flag for "this is the encoding I expect my grep pattern to
      match"; the only sane choice is for it to use the log output
      encoding. That is presumably what the user's terminal is
      using, and it means that the patterns found by the grep will
      match the output produced by git.
      
      As a bonus, this fixes a potential segfault in commit_match
      when commit->buffer is NULL, as we now build on logmsg_reencode,
      which handles reading the commit buffer from disk if
      necessary. The segfault can be triggered with:
      
              git commit -m 'text1' --allow-empty
              git commit -m 'text2' --allow-empty
              git log --graph --no-walk --grep 'text2'
      
      which arguably does not make any sense (--graph inherently
      wants a connected history, and by --no-walk the command line
      is telling us to show discrete points in history without
      connectivity), and we probably should forbid the
      combination, but that is a separate issue.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      04deccda
  7. 18 1月, 2013 1 次提交
    • J
      simplify-merges: drop merge from irrelevant side branch · 4b7f53da
      Junio C Hamano 提交于
      The merge simplification rule stated in 6546b593 (revision traversal:
      show full history with merge simplification, 2008-07-31) still
      treated merge commits too specially.  Namely, in a history with this
      shape:
      
      	---o---o---M
      	          /
               x---x---x
      
      where three 'x' were on a history completely unrelated to the main
      history 'o' and do not touch any of the paths we are following, we
      still said that after simplifying all of the parents of M, 'x'
      (which is the leftmost 'x' that rightmost 'x simplifies down to) and
      'o' (which would be the last commit on the main history that touches
      the paths we are following) are independent from each other, and
      both need to be kept.
      
      That is incorrect; when the side branch 'x' never touches the paths,
      it should be removed to allow M to simplify down to the last commit
      on the main history that touches the paths.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4b7f53da
  8. 11 1月, 2013 2 次提交
    • J
      log --use-mailmap: optimize for cases without --author/--committer search · df874fa8
      Junio C Hamano 提交于
      When we taught the commit_match() mechanism to pay attention to the
      new --use-mailmap option, we started to unconditionally copy the
      commit object to a temporary buffer, just in case we need the author
      and committer lines updated via the mailmap mechanism, and rewrite
      author and committer using the mailmap.
      
      It turns out that this has a rather unpleasant performance
      implications.  In the linux kernel repository, running
      
        $ git log --author='Junio C Hamano' --pretty=short >/dev/null
      
      under /usr/bin/time, with and without --use-mailmap (the .mailmap
      file is 118 entries long, the particular author does not appear in
      it), cost (with warm cache):
      
        [without --use-mailmap]
        5.42user 0.26system 0:05.70elapsed 99%CPU (0avgtext+0avgdata 2005936maxresident)k
        0inputs+0outputs (0major+137669minor)pagefaults 0swaps
      
        [with --use-mailmap]
        6.47user 0.30system 0:06.78elapsed 99%CPU (0avgtext+0avgdata 2006288maxresident)k
        0inputs+0outputs (0major+137692minor)pagefaults 0swaps
      
      which incurs about 20% overhead.  The command is doing extra work,
      so the extra cost may be justified.
      
      But it is inexcusable to pay the cost when we do not need
      author/committer match.  In the same repository,
      
        $ git log --grep='fix menuconfig on debian lenny' --pretty=short >/dev/null
      
      shows very similar numbers as the above:
      
        [without --use-mailmap]
        5.32user 0.30system 0:05.63elapsed 99%CPU (0avgtext+0avgdata 2005984maxresident)k
        0inputs+0outputs (0major+137672minor)pagefaults 0swaps
      
        [with --use-mailmap]
        6.64user 0.24system 0:06.89elapsed 99%CPU (0avgtext+0avgdata 2006320maxresident)k
        0inputs+0outputs (0major+137694minor)pagefaults 0swaps
      
      The latter case is an unnecessary performance regression.  We may
      want to _show_ the result with mailmap applied, but we do not have
      to copy and rewrite the author/committer of all commits we try to
      match if we do not query for these fields.
      
      Trivially optimize this performace regression by limiting the
      rewrites for only when we are matching with author/committer fields.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      df874fa8
    • A
      log: grep author/committer using mailmap · d72fbe81
      Antoine Pelisse 提交于
      Currently you can use mailmap to display log authors and committers
      but you can't use the mailmap to find commits with mapped values.
      
      This commit allows you to run:
      
          git log --use-mailmap --author mapped_name_or_email
          git log --use-mailmap --committer mapped_name_or_email
      
      Of course it only works if the --use-mailmap option is used.
      
      The new name and email are copied only when necessary.
      Signed-off-by: NAntoine Pelisse <apelisse@gmail.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      d72fbe81
  9. 18 10月, 2012 1 次提交
  10. 10 10月, 2012 3 次提交
  11. 30 9月, 2012 3 次提交
  12. 15 9月, 2012 1 次提交
    • J
      grep: teach --debug option to dump the parse tree · 17bf35a3
      Junio C Hamano 提交于
      Our "grep" allows complex boolean expressions to be formed to match
      each individual line with operators like --and, '(', ')' and --not.
      Introduce the "--debug" option to show the parse tree to help people
      who want to debug and enhance it.
      
      Also "log" learns "--grep-debug" option to do the same.  The command
      line parser to the log family is a lot more limited than the general
      "git grep" parser, but it has special handling for header matching
      (e.g. "--author"), and a parse tree is valuable when working on it.
      
      Note that "--all-match" is *not* any individual node in the parse
      tree.  It is an instruction to the evaluator to check all the nodes
      in the top-level backbone have matched and reject a document as
      non-matching otherwise.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      17bf35a3
  13. 31 8月, 2012 1 次提交
    • M
      teach log --no-walk=unsorted, which avoids sorting · ca92e59e
      Martin von Zweigbergk 提交于
      When 'git log' is passed the --no-walk option, no revision walk takes
      place, naturally. Perhaps somewhat surprisingly, however, the provided
      revisions still get sorted by commit date. So e.g 'git log --no-walk
      HEAD HEAD~1' and 'git log --no-walk HEAD~1 HEAD' give the same result
      (unless the two revisions share the commit date, in which case they
      will retain the order given on the command line). As the commit that
      introduced --no-walk (8e64006e (Teach revision machinery about
      --no-walk, 2007-07-24)) points out, the sorting is intentional, to
      allow things like
      
       git log --abbrev-commit --pretty=oneline --decorate --all --no-walk
      
      to show all refs in order by commit date.
      
      But there are also other cases where the sorting is not wanted, such
      as
      
       <command producing revisions in order> |
             git log --oneline --no-walk --stdin
      
      To accomodate both cases, leave the decision of whether or not to sort
      up to the caller, by allowing --no-walk={sorted,unsorted}, defaulting
      to 'sorted' for backward-compatibility reasons.
      Signed-off-by: NMartin von Zweigbergk <martinvonz@gmail.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      ca92e59e
  14. 24 8月, 2012 1 次提交
    • J
      specifying ranges: we did not mean to make ".." an empty set · 003c84f6
      Junio C Hamano 提交于
      Either end of revision range operator can be omitted to default to HEAD,
      as in "origin.." (what did I do since I forked) or "..origin" (what did
      they do since I forked).  But the current parser interprets ".."  as an
      empty range "HEAD..HEAD", and worse yet, because ".." does exist on the
      filesystem, we get this annoying output:
      
        $ cd Documentation/howto
        $ git log .. ;# give me recent commits that touch Documentation/ area.
        fatal: ambiguous argument '..': both revision and filename
        Use '--' to separate filenames from revisions
      
      Surely we could say "git log ../" or even "git log -- .." to disambiguate,
      but we shouldn't have to.
      Helped-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      003c84f6
  15. 04 8月, 2012 1 次提交
    • T
      diff_setup_done(): return void · 28452655
      Thomas Rast 提交于
      diff_setup_done() has historically returned an error code, but lost
      the last nonzero return in 943d5b73 (allow diff.renamelimit to be set
      regardless of -M/-C, 2006-08-09).  The callers were in a pretty
      confused state: some actually checked for the return code, and some
      did not.
      
      Let it return void, and patch all callers to take this into account.
      This conveniently also gets rid of a handful of different(!) error
      messages that could never be triggered anyway.
      
      Note that the function can still die().
      Signed-off-by: NThomas Rast <trast@student.ethz.ch>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      28452655
  16. 30 7月, 2012 1 次提交
    • J
      diff: do not use null sha1 as a sentinel value · e5450100
      Jeff King 提交于
      The diff code represents paths using the diff_filespec
      struct. This struct has a sha1 to represent the sha1 of the
      content at that path, as well as a sha1_valid member which
      indicates whether its sha1 field is actually useful. If
      sha1_valid is not true, then the filespec represents a
      working tree file (e.g., for the no-index case, or for when
      the index is not up-to-date).
      
      The diff_filespec is only used internally, though. At the
      interfaces to the diff subsystem, callers feed the sha1
      directly, and we create a diff_filespec from it. It's at
      that point that we look at the sha1 and decide whether it is
      valid or not; callers may pass the null sha1 as a sentinel
      value to indicate that it is not.
      
      We should not typically see the null sha1 coming from any
      other source (e.g., in the index itself, or from a tree).
      However, a corrupt tree might have a null sha1, which would
      cause "diff --patch" to accidentally diff the working tree
      version of a file instead of treating it as a blob.
      
      This patch extends the edges of the diff interface to accept
      a "sha1_valid" flag whenever we accept a sha1, and to use
      that flag when creating a filespec. In some cases, this
      means passing the flag through several layers, making the
      code change larger than would be desirable.
      
      One alternative would be to simply die() upon seeing
      corrupted trees with null sha1s. However, this fix more
      directly addresses the problem (while bogus sha1s in a tree
      are probably a bad thing, it is really the sentinel
      confusion sending us down the wrong code path that is what
      makes it devastating). And it means that git is more capable
      of examining and debugging these corrupted trees. For
      example, you can still "diff --raw" such a tree to find out
      when the bogus entry was introduced; you just cannot do a
      "--patch" diff (just as you could not with any other
      corrupted tree, as we do not have any content to diff).
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      e5450100
  17. 14 7月, 2012 1 次提交
    • J
      revision: avoid work after --max-count is reached · b72a1904
      Jeff King 提交于
      During a revision traversal in which --max-count has been
      specified, we decrement a counter for each revision returned
      by get_revision. When it hits 0, we typically return NULL
      (the exception being if we still have boundary commits to
      show).
      
      However, before we check the counter, we call get_revision_1
      to get the next commit. This might involve looking at a
      large number of commits if we have restricted the traversal
      (e.g., we might traverse until we find the next commit whose
      diff actually matches a pathspec).
      
      There's no need to make this get_revision_1 call when our
      counter runs out. If we are not in --boundary mode, we will
      just throw away the result and immediately return NULL. If
      we are in --boundary mode, then we will still throw away the
      result, and then start showing the boundary commits.
      However, as git_revision_1 does not impact the boundary
      list, it should not have an impact.
      
      In most cases, avoiding this work will not be especially
      noticeable. However, in some cases, it can make a big
      difference:
      
        [before]
        $ time git rev-list -1 origin Documentation/RelNotes/1.7.11.2.txt
        8d141a1d
      
        real    0m0.301s
        user    0m0.280s
        sys     0m0.016s
      
        [after]
        $ time git rev-list -1 origin Documentation/RelNotes/1.7.11.2.txt
        8d141a1d
      
        real    0m0.010s
        user    0m0.008s
        sys     0m0.000s
      
      Note that the output is produced almost instantaneously in
      the first case, and then git uselessly spends a long time
      looking for the next commit to touch that file (but there
      isn't one, and we traverse all the way down to the roots).
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      b72a1904
  18. 10 7月, 2012 4 次提交
  19. 04 7月, 2012 1 次提交
  20. 19 6月, 2012 1 次提交
    • M
      verify_filename(): ask the caller to chose the kind of diagnosis · 023e37c3
      Matthieu Moy 提交于
      verify_filename() can be called in two different contexts. Either we
      just tried to interpret a string as an object name, and it fails, so
      we try looking for a working tree file (i.e. we finished looking at
      revs that come earlier on the command line, and the next argument
      must be a pathname), or we _know_ that we are looking for a
      pathname, and shouldn't even try interpreting the string as an
      object name.
      
      For example, with this change, we get:
      
        $ git log COPYING HEAD:inexistant
        fatal: HEAD:inexistant: no such path in the working tree.
        Use '-- <path>...' to specify paths that do not exist locally.
        $ git log HEAD:inexistant
        fatal: Path 'inexistant' does not exist in 'HEAD'
      Signed-off-by: NMatthieu Moy <Matthieu.Moy@imag.fr>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      023e37c3
  21. 14 6月, 2012 1 次提交
    • J
      revision: ignore side parents while running simplify-merges · 6e513ba3
      Junio C Hamano 提交于
      The simplify_merges() function needs to look at all history chain to
      find the closest ancestor that is relevant after the simplification,
      but after --first-parent traversal, side parents haven't been marked
      for relevance (they are irrelevant by definition due to the nature
      of first-parent-only traversal) nor culled from the parents list of
      resulting commits.
      
      We cannot simply remove these side parents from the parents list, as
      the output phase still wants to see the parents.  Instead, teach
      simplify_one() and its callees to ignore the later parents.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      6e513ba3
  22. 09 6月, 2012 2 次提交
  23. 26 4月, 2012 1 次提交
  24. 16 4月, 2012 1 次提交