1. 05 6月, 2014 1 次提交
    • J
      shortlog: allow --exclude=<glob> to be passed · eb077745
      Junio C Hamano 提交于
      These two commands are supposed to be equivalent:
      
        $ git log --exclude=refs/notes/\* --all --no-merges --since=2.days |
          git shortlog
        $ git shortlog --exclude=refs/notes/\* --all --no-merges --since=2.days
      
      However, the latter does not understand the ref-exclusion command
      line option, even though other options understood by "log", such as
      "--all" and "--no-merges", are understood.
      
      This was because e7b432c5 (revision: introduce --exclude=<glob> to
      tame wildcards, 2013-08-30) did not wire the new option fully to the
      machinery.  A new option understood by handle_revision_pseudo_opt()
      must be told to handle_revision_opt() as well.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      eb077745
  2. 05 4月, 2014 1 次提交
    • V
      add `ignore_missing_links` mode to revwalk · 2db1a43f
      Vicent Marti 提交于
      When pack-objects is computing the reachability bitmap to
      serve a fetch request, it can erroneously die() if some of
      the UNINTERESTING objects are not present. Upload-pack
      throws away HAVE lines from the client for objects we do not
      have, but we may have a tip object without all of its
      ancestors (e.g., if the tip is no longer reachable and was
      new enough to survive a `git prune`, but some of its
      reachable objects did get pruned).
      
      In the non-bitmap case, we do a revision walk with the HAVE
      objects marked as UNINTERESTING. The revision walker
      explicitly ignores errors in accessing UNINTERESTING commits
      to handle this case (and we do not bother looking at
      UNINTERESTING trees or blobs at all).
      
      When we have bitmaps, however, the process is quite
      different.  The bitmap index for a pack-objects run is
      calculated in two separate steps:
      
      First, we perform an extensive walk from all the HAVEs to
      find the full set of objects reachable from them. This walk
      is usually optimized away because we are expected to hit an
      object with a bitmap during the traversal, which allows us
      to terminate early.
      
      Secondly, we perform an extensive walk from all the WANTs,
      which usually also terminates early because we hit a commit
      with an existing bitmap.
      
      Once we have the resulting bitmaps from the two walks, we
      AND-NOT them together to obtain the resulting set of objects
      we need to pack.
      
      When we are walking the HAVE objects, the revision walker
      does not know that we are walking it only to mark the
      results as uninteresting. We strip out the UNINTERESTING flag,
      because those objects _are_ interesting to us during the
      first walk. We want to keep going to get a complete set of
      reachable objects if we can.
      
      We need some way to tell the revision walker that it's OK to
      silently truncate the HAVE walk, just like it does for the
      UNINTERESTING case. This patch introduces a new
      `ignore_missing_links` flag to the `rev_info` struct, which
      we set only for the HAVE walk.
      
      It also adds tests to cover UNINTERESTING objects missing
      from several positions: a missing blob, a missing tree, and
      a missing parent commit. The missing blob already worked (as
      we do not care about its contents at all), but the other two
      cases caused us to die().
      
      Note that there are a few cases we do not need to test:
      
        1. We do not need to test a missing tree, with the blob
           still present. Without the tree that refers to it, we
           would not know that the blob is relevant to our walk.
      
        2. We do not need to test a tip commit that is missing.
           Upload-pack omits these for us (and in fact, we
           complain even in the non-bitmap case if it fails to do
           so).
      Reported-by: NSiddharth Agarwal <sid0@fb.com>
      Signed-off-by: NVicent Marti <tanoku@gmail.com>
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      2db1a43f
  3. 26 3月, 2014 1 次提交
  4. 14 3月, 2014 1 次提交
  5. 25 2月, 2014 1 次提交
  6. 21 2月, 2014 1 次提交
  7. 06 2月, 2014 1 次提交
  8. 16 1月, 2014 2 次提交
    • J
      revision: propagate flag bits from tags to pointees · a7435286
      Junio C Hamano 提交于
      With the previous fix 895c5ba3 (revision: do not peel tags used in
      range notation, 2013-09-19), handle_revision_arg() that processes
      command line arguments for the "git log" family of commands no
      longer directly places the object pointed by the tag in the pending
      object array when it sees a tag object.  We used to place pointee
      there after copying the flag bits like UNINTERESTING and
      SYMMETRIC_LEFT.
      
      This change meant that any flag that is relevant to later history
      traversal must now be propagated to the pointed objects (most often
      these are commits) while starting the traversal, which is partly
      done by handle_commit() that is called from prepare_revision_walk().
      We did propagate UNINTERESTING, but did not do so for others, most
      notably SYMMETRIC_LEFT.  This caused "git log --left-right v1.0..."
      (where "v1.0" is a tag) to start losing the "leftness" from the
      commit the tag points at.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      a7435286
    • J
      revision: mark contents of an uninteresting tree uninteresting · 2ac5e447
      Junio C Hamano 提交于
      "git rev-list --objects ^A^{tree} B^{tree}" ought to mean "I want a
      list of objects inside B's tree, but please exclude the objects that
      appear inside A's tree".
      
      we see the top-level tree marked as uninteresting (i.e. ^A^{tree} in
      the above example) and call mark_tree_uninteresting() on it; this
      unfortunately prevents us from recursing into the tree and marking
      the objects in the tree as uninteresting.
      
      The reason why "git log ^A A" yields an empty set of commits,
      i.e. we do not have a similar issue for commits, is because we call
      mark_parents_uninteresting() after seeing an uninteresting commit.
      The uninteresting-ness of the commit itself does not prevent its
      parents from being marked as uninteresting.
      
      Introduce mark_tree_contents_uninteresting() and structure the code
      in handle_commit() in such a way that it makes it the responsibility
      of the callchain leading to this function to mark commits, trees and
      blobs as uninteresting, and also make it the responsibility of the
      helpers called from this function to mark objects that are reachable
      from them.
      
      Note that this is a very old bug that probably dates back to the day
      when "rev-list --objects" was introduced.  The line to clear
      tree->object.parsed at the end of mark_tree_contents_uninteresting()
      can be removed when this fix is merged to the codebase after
      6e454b9a (clear parsed flag when we free tree buffers, 2013-06-05).
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      2ac5e447
  9. 06 12月, 2013 1 次提交
    • C
      replace {pre,suf}fixcmp() with {starts,ends}_with() · 59556548
      Christian Couder 提交于
      Leaving only the function definitions and declarations so that any
      new topic in flight can still make use of the old functions, replace
      existing uses of the prefixcmp() and suffixcmp() with new API
      functions.
      
      The change can be recreated by mechanically applying this:
      
          $ git grep -l -e prefixcmp -e suffixcmp -- \*.c |
            grep -v strbuf\\.c |
            xargs perl -pi -e '
              s|!prefixcmp\(|starts_with\(|g;
              s|prefixcmp\(|!starts_with\(|g;
              s|!suffixcmp\(|ends_with\(|g;
              s|suffixcmp\(|!ends_with\(|g;
            '
      
      on the result of preparatory changes in this series.
      Signed-off-by: NChristian Couder <chriscool@tuxfamily.org>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      59556548
  10. 02 11月, 2013 1 次提交
  11. 01 11月, 2013 1 次提交
  12. 29 10月, 2013 1 次提交
    • N
      pathspec: stop --*-pathspecs impact on internal parse_pathspec() uses · 4a2d5ae2
      Nguyễn Thái Ngọc Duy 提交于
      Normally parse_pathspec() is used on command line arguments where it
      can do fancy thing like parsing magic on each argument or adding magic
      for all pathspecs based on --*-pathspecs options.
      
      There's another use of parse_pathspec(), where pathspec is needed, but
      the input is known to be pure paths. In this case we usually don't
      want --*-pathspecs to interfere. And we definitely do not want to
      parse magic in these paths, regardless of --literal-pathspecs.
      
      Add new flag PATHSPEC_LITERAL_PATH for this purpose. When it's set,
      --*-pathspecs are ignored, no magic is parsed. And if the caller
      allows PATHSPEC_LITERAL (i.e. the next calls can take literal magic),
      then PATHSPEC_LITERAL will be set.
      
      This fixes cases where git chokes when GIT_*_PATHSPECS are set because
      parse_pathspec() indicates it won't take any magic. But
      GIT_*_PATHSPECS add them anyway. These are
      
         export GIT_LITERAL_PATHSPECS=1
         git blame -- something
         git log --follow something
         git log --merge
      
      "git ls-files --with-tree=path" (aka parse_pathspec() in
      overlay_tree_on_cache()) is safe because the input is empty, and
      producing one pathspec due to PATHSPEC_PREFER_CWD does not take any
      magic into account.
      Signed-off-by: NNguyễn Thái Ngọc Duy <pclouds@gmail.com>
      Acked-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4a2d5ae2
  13. 25 10月, 2013 1 次提交
  14. 23 10月, 2013 1 次提交
  15. 16 10月, 2013 1 次提交
    • J
      revision: do not peel tags used in range notation · 895c5ba3
      Junio C Hamano 提交于
      A range notation "A..B" means exactly the same thing as what "^A B"
      means, i.e. the set of commits that are reachable from B but not
      from A.  But the internal representation after the revision parser
      parsed these two notations are subtly different.
      
       - "rev-list ^A B" leaves A and B in the revs->pending.objects[]
         array, with the former marked as UNINTERESTING and the revision
         traversal machinery propagates the mark to underlying commit
         objects A^0 and B^0.
      
       - "rev-list A..B" peels tags and leaves A^0 (marked as
         UNINTERESTING) and B^0 in revs->pending.objects[] array before
         the traversal machinery kicks in.
      
      This difference usually does not matter, but starts to matter when
      the --objects option is used.  For example, we see this:
      
          $ git rev-list --objects v1.8.4^1..v1.8.4 | grep $(git rev-parse v1.8.4)
          $ git rev-list --objects v1.8.4 ^v1.8.4^1 | grep $(git rev-parse v1.8.4)
          04f013dc38d7512eadb915eba22efc414f18b869 v1.8.4
      
      With the former invocation, the revision traversal machinery never
      hears about the tag v1.8.4 (it only sees the result of peeling it,
      i.e. the commit v1.8.4^0), and the tag itself does not appear in the
      output.  The latter does send the tag object itself to the output.
      
      Make the range notation keep the unpeeled objects and feed them to
      the traversal machinery to fix this inconsistency.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      895c5ba3
  16. 04 9月, 2013 1 次提交
  17. 31 8月, 2013 1 次提交
    • J
      revision: introduce --exclude=<glob> to tame wildcards · e7b432c5
      Junio C Hamano 提交于
      People often find "git log --branches" etc. that includes _all_
      branches is cumbersome to use when they want to grab most but except
      some.  The same applies to --tags, --all and --glob.
      
      Teach the revision machinery to remember patterns, and then upon the
      next such a globbing option, exclude those that match the pattern.
      
      With this, I can view only my integration branches (e.g. maint,
      master, etc.) without topic branches, which are named after two
      letters from primary authors' names, slash and topic name.
      
          git rev-list --no-walk --exclude=??/* --branches |
          git name-rev --refs refs/heads/* --stdin
      
      This one shows things reachable from local and remote branches that
      have not been merged to the integration branches.
      
          git log --remotes --branches --not --exclude=??/* --branches
      
      It may be a bit rough around the edges, in that the pattern to give
      the exclude option depends on what globbing option follows.  In
      these examples, the pattern "??/*" is used, not "refs/heads/??/*",
      because the globbing option that follows the -"-exclude=<pattern>"
      is "--branches".  As each use of globbing option resets previously
      set "--exclude", this may not be such a bad thing, though.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      e7b432c5
  18. 05 8月, 2013 1 次提交
    • T
      log: use true parents for diff when walking reflogs · 838f9a15
      Thomas Rast 提交于
      The reflog walking logic (git log -g) replaces the true parent list
      with the preceding commit in the reflog.  This results in bogus commit
      diffs when combined with options such as -p; the diff is against the
      reflog predecessor, not the parent of the commit.
      
      Save the true parents on the side, extending the functions from the
      previous commit.  The diff logic picks them up and uses them to show
      the correct diffs.
      
      We do have to be somewhat careful about repeated calling of
      save_parents(), since the reflog may list a commit more than once.  We
      now store (commit_list*)-1 to distinguish the "not saved yet" and
      "root commit" cases.  This lets us preserve an empty parent list even
      if save_parents() is repeatedly called.
      Suggested-by: NJeff King <peff@peff.net>
      Signed-off-by: NThomas Rast <trast@inf.ethz.ch>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      838f9a15
  19. 02 8月, 2013 1 次提交
    • T
      log: use true parents for diff even when rewriting · 53d00b39
      Thomas Rast 提交于
      When using pathspec filtering in combination with diff-based log
      output, parent simplification happens before the diff is computed.
      The diff is therefore against the *simplified* parents.
      
      This works okay, arguably by accident, in the normal case:
      simplification reduces to one parent as long as the commit is TREESAME
      to it.  So the simplified parent of any given commit must have the
      same tree contents on the filtered paths as its true (unfiltered)
      parent.
      
      However, --full-diff breaks this guarantee, and indeed gives pretty
      spectacular results when comparing the output of
      
        git log --graph --stat ...
        git log --graph --full-diff --stat ...
      
      (--graph internally kicks in parent simplification, much like
      --parents).
      
      To fix it, store a copy of the parent list before simplification (in a
      slab) whenever --full-diff is in effect.  Then use the stored parents
      instead of the simplified ones in the commit display code paths.  The
      latter do not actually check for --full-diff to avoid duplicated code;
      they just grab the original parents if save_parents() has not been
      called for this revision walk.
      
      For ordinary commits it should be obvious that this is the right thing
      to do.
      
      Merge commits are a bit subtle.  Observe that with default
      simplification, merge simplification is an all-or-nothing decision:
      either the merge is TREESAME to one parent and disappears, or it is
      different from all parents and the parent list remains intact.
      Redundant parents are not pruned, so the existing code also shows them
      as a merge.
      
      So if we do show a merge commit, the parent list just consists of the
      rewrite result on each parent.  Running, e.g., --cc on this in
      --full-diff mode is not very useful: if any commits were skipped, some
      hunks will disagree with all sides of the merge (with one side,
      because commits were skipped; with the others, because they didn't
      have those changes in the first place).  This triggers --cc showing
      these hunks spuriously.
      
      Therefore I believe that even for merge commits it is better to show
      the diffs wrt. the original parents.
      Reported-by: NUwe Kleine-König <u.kleine-koenig@pengutronix.de>
      Helped-by: NJunio C Hamano <gitster@pobox.com>
      Helped-by: NRamsay Jones <ramsay@ramsay1.demon.co.uk>
      Signed-off-by: NThomas Rast <trast@inf.ethz.ch>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      53d00b39
  20. 16 7月, 2013 3 次提交
  21. 10 7月, 2013 1 次提交
    • N
      Convert "struct cache_entry *" to "const ..." wherever possible · 9c5e6c80
      Nguyễn Thái Ngọc Duy 提交于
      I attempted to make index_state->cache[] a "const struct cache_entry **"
      to find out how existing entries in index are modified and where. The
      question I have is what do we do if we really need to keep track of on-disk
      changes in the index. The result is
      
       - diff-lib.c: setting CE_UPTODATE
      
       - name-hash.c: setting CE_HASHED
      
       - preload-index.c, read-cache.c, unpack-trees.c and
         builtin/update-index: obvious
      
       - entry.c: write_entry() may refresh the checked out entry via
         fill_stat_cache_info(). This causes "non-const struct cache_entry
         *" in builtin/apply.c, builtin/checkout-index.c and
         builtin/checkout.c
      
       - builtin/ls-files.c: --with-tree changes stagemask and may set
         CE_UPDATE
      
      Of these, write_entry() and its call sites are probably most
      interesting because it modifies on-disk info. But this is stat info
      and can be retrieved via refresh, at least for porcelain
      commands. Other just uses ce_flags for local purposes.
      
      So, keeping track of "dirty" entries is just a matter of setting a
      flag in index modification functions exposed by read-cache.c. Except
      unpack-trees, the rest of the code base does not do anything funny
      behind read-cache's back.
      
      The actual patch is less valueable than the summary above. But if
      anyone wants to re-identify the above sites. Applying this patch, then
      this:
      
          diff --git a/cache.h b/cache.h
          index 430d021..1692891 100644
          --- a/cache.h
          +++ b/cache.h
          @@ -267,7 +267,7 @@ static inline unsigned int canon_mode(unsigned int mode)
           #define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1)
      
           struct index_state {
          -	struct cache_entry **cache;
          +	const struct cache_entry **cache;
           	unsigned int version;
           	unsigned int cache_nr, cache_alloc, cache_changed;
           	struct string_list *resolve_undo;
      
      will help quickly identify them without bogus warnings.
      Signed-off-by: NNguyễn Thái Ngọc Duy <pclouds@gmail.com>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      9c5e6c80
  22. 12 6月, 2013 2 次提交
    • J
      log: --author-date-order · 81c6b38b
      Junio C Hamano 提交于
      Sometimes people would want to view the commits in parallel
      histories in the order of author dates, not committer dates.
      
      Teach "topo-order" sort machinery to do so, using a commit-info slab
      to record the author dates of each commit, and prio-queue to sort
      them.
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      81c6b38b
    • J
      toposort: rename "lifo" field · 08f704f2
      Junio C Hamano 提交于
      The primary invariant of sort_in_topological_order() is that a
      parent commit is not emitted until all children of it are.  When
      traversing a forked history like this with "git log C E":
      
          A----B----C
           \
            D----E
      
      we ensure that A is emitted after all of B, C, D, and E are done, B
      has to wait until C is done, and D has to wait until E is done.
      
      In some applications, however, we would further want to control how
      these child commits B, C, D and E on two parallel ancestry chains
      are shown.
      
      Most of the time, we would want to see C and B emitted together, and
      then E and D, and finally A (i.e. the --topo-order output).  The
      "lifo" parameter of the sort_in_topological_order() function is used
      to control this behaviour.  We start the traversal by knowing two
      commits, C and E.  While keeping in mind that we also need to
      inspect E later, we pick C first to inspect, and we notice and
      record that B needs to be inspected.  By structuring the "work to be
      done" set as a LIFO stack, we ensure that B is inspected next,
      before other in-flight commits we had known that we will need to
      inspect, e.g. E.
      
      When showing in --date-order, we would want to see commits ordered
      by timestamps, i.e. show C, E, B and D in this order before showing
      A, possibly mixing commits from two parallel histories together.
      When "lifo" parameter is set to false, the function keeps the "work
      to be done" set sorted in the date order to realize this semantics.
      After inspecting C, we add B to the "work to be done" set, but the
      next commit we inspect from the set is E which is newer than B.
      
      The name "lifo", however, is too strongly tied to the way how the
      function implements its behaviour, and does not describe what the
      behaviour _means_.
      
      Replace this field with an enum rev_sort_order, with two possible
      values: REV_SORT_IN_GRAPH_ORDER and REV_SORT_BY_COMMIT_DATE, and
      update the existing code.  The mechanical replacement rule is:
      
        "lifo == 0" is equivalent to "sort_order == REV_SORT_BY_COMMIT_DATE"
        "lifo == 1" is equivalent to "sort_order == REV_SORT_IN_GRAPH_ORDER"
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      08f704f2
  23. 07 6月, 2013 1 次提交
    • J
      clear parsed flag when we free tree buffers · 6e454b9a
      Jeff King 提交于
      Many code paths will free a tree object's buffer and set it
      to NULL after finishing with it in order to keep memory
      usage down during a traversal. However, out of 8 sites that
      do this, only one actually unsets the "parsed" flag back.
      Those sites that don't are setting a trap for later users of
      the tree object; even after calling parse_tree, the buffer
      will remain NULL, causing potential segfaults.
      
      It is not known whether this is triggerable in the current
      code. Most commands do not do an in-memory traversal
      followed by actually using the objects again. However, it
      does not hurt to be safe for future callers.
      
      In most cases, we can abstract this out to a
      "free_tree_buffer" helper. However, there are two
      exceptions:
      
        1. The fsck code relies on the parsed flag to know that we
           were able to parse the object at one point. We can
           switch this to using a flag in the "flags" field.
      
        2. The index-pack code sets the buffer to NULL but does
           not free it (it is freed by a caller). We should still
           unset the parsed flag here, but we cannot use our
           helper, as we do not want to free the buffer.
      Signed-off-by: NJeff King <peff@peff.net>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      6e454b9a
  24. 03 6月, 2013 1 次提交
    • M
      object_array_entry: fix memory handling of the name field · 31faeb20
      Michael Haggerty 提交于
      Previously, the memory management of the object_array_entry::name
      field was inconsistent and undocumented.  object_array_entries are
      ultimately created by a single function, add_object_array_with_mode(),
      which has an argument "const char *name".  This function used to
      simply set the name field to reference the string pointed to by the
      name parameter, and nobody on the object_array side ever freed the
      memory.  Thus, it assumed that the memory for the name field would be
      managed by the caller, and that the lifetime of that string would be
      at least as long as the lifetime of the object_array_entry.  But
      callers were inconsistent:
      
      * Some passed pointers to constant strings or argv entries, which was
        OK.
      
      * Some passed pointers to newly-allocated memory, but didn't arrange
        for the memory ever to be freed.
      
      * Some passed the return value of sha1_to_hex(), which is a pointer to
        a statically-allocated buffer that can be overwritten at any time.
      
      * Some passed pointers to refnames that they received from a
        for_each_ref()-type iteration, but the lifetimes of such refnames is
        not guaranteed by the refs API.
      
      Bring consistency to this mess by changing object_array to make its
      own copy for the object_array_entry::name field and free this memory
      when an object_array_entry is deleted from the array.
      
      Many callers were passing the empty string as the name parameter, so
      as a performance optimization, treat the empty string specially.
      Instead of making a copy, store a pointer to a statically-allocated
      empty string to object_array_entry::name.  When deleting such an
      entry, skip the free().
      
      Change the callers that were already passing copies to
      add_object_array_with_mode() to either skip the copy, or (if the
      memory needed to be allocated anyway) freeing the memory itself.
      
      A part of this commit effectively reverts
      
          70d26c6e read_revisions_from_stdin: make copies for handle_revision_arg
      
      because the copying introduced by that commit (which is still
      necessary) is now done at a deeper level.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      31faeb20
  25. 29 5月, 2013 3 次提交
  26. 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
  27. 19 4月, 2013 1 次提交