Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: git/git
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 82fa169d55
Choose a base ref
...
head repository: git/git
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8d049e182e
Choose a head ref
  • 1 commit
  • 5 files changed
  • 1 contributor

Commits on Apr 10, 2020

  1. revision: --show-pulls adds helpful merges

    The default file history simplification of "git log -- <path>" or
    "git rev-list -- <path>" focuses on providing the smallest set of
    commits that first contributed a change. The revision walk greatly
    restricts the set of walked commits by visiting only the first
    TREESAME parent of a merge commit, when one exists. This means
    that portions of the commit-graph are not walked, which can be a
    performance benefit, but can also "hide" commits that added changes
    but were ignored by a merge resolution.
    
    The --full-history option modifies this by walking all commits and
    reporting a merge commit as "interesting" if it has _any_ parent
    that is not TREESAME. This tends to be an over-representation of
    important commits, especially in an environment where most merge
    commits are created by pull request completion.
    
    Suppose we have a commit A and we create a commit B on top that
    changes our file. When we merge the pull request, we create a merge
    commit M. If no one else changed the file in the first-parent
    history between M and A, then M will not be TREESAME to its first
    parent, but will be TREESAME to B. Thus, the simplified history
    will be "B". However, M will appear in the --full-history mode.
    
    However, suppose that a number of topics T1, T2, ..., Tn were
    created based on commits C1, C2, ..., Cn between A and M as
    follows:
    
      A----C1----C2--- ... ---Cn----M------P1---P2--- ... ---Pn
       \     \     \            \  /      /    /            /
        \     \__.. \            \/ ..__T1    /           Tn
         \           \__..       /\     ..__T2           /
          \_____________________B  \____________________/
    
    If the commits T1, T2, ... Tn did not change the file, then all of
    P1 through Pn will be TREESAME to their first parent, but not
    TREESAME to their second. This means that all of those merge commits
    appear in the --full-history view, with edges that immediately
    collapse into the lower history without introducing interesting
    single-parent commits.
    
    The --simplify-merges option was introduced to remove these extra
    merge commits. By noticing that the rewritten parents are reachable
    from their first parents, those edges can be simplified away. Finally,
    the commits now look like single-parent commits that are TREESAME to
    their "only" parent. Thus, they are removed and this issue does not
    cause issues anymore. However, this also ends up removing the commit
    M from the history view! Even worse, the --simplify-merges option
    requires walking the entire history before returning a single result.
    
    Many Git users are using Git alongside a Git service that provides
    code storage alongside a code review tool commonly called "Pull
    Requests" or "Merge Requests" against a target branch.  When these
    requests are accepted and merged, they typically create a merge
    commit whose first parent is the previous branch tip and the second
    parent is the tip of the topic branch used for the request. This
    presents a valuable order to the parents, but also makes that merge
    commit slightly special. Users may want to see not only which
    commits changed a file, but which pull requests merged those commits
    into their branch. In the previous example, this would mean the
    users want to see the merge commit "M" in addition to the single-
    parent commit "C".
    
    Users are even more likely to want these merge commits when they
    use pull requests to merge into a feature branch before merging that
    feature branch into their trunk.
    
    In some sense, users are asking for the "first" merge commit to
    bring in the change to their branch. As long as the parent order is
    consistent, this can be handled with the following rule:
    
      Include a merge commit if it is not TREESAME to its first
      parent, but is TREESAME to a later parent.
    
    These merges look like the merge commits that would result from
    running "git pull <topic>" on a main branch. Thus, the option to
    show these commits is called "--show-pulls". This has the added
    benefit of showing the commits created by closing a pull request or
    merge request on any of the Git hosting and code review platforms.
    
    To test these options, extend the standard test example to include
    a merge commit that is not TREESAME to its first parent. It is
    surprising that that option was not already in the example, as it
    is instructive.
    
    In particular, this extension demonstrates a common issue with file
    history simplification. When a user resolves a merge conflict using
    "-Xours" or otherwise ignoring one side of the conflict, they create
    a TREESAME edge that probably should not be TREESAME. This leads
    users to become frustrated and complain that "my change disappeared!"
    In my experience, showing them history with --full-history and
    --simplify-merges quickly reveals the problematic merge. As mentioned,
    this option is expensive to compute. The --show-pulls option
    _might_ show the merge commit (usually titled "resolving conflicts")
    more quickly. Of course, this depends on the user having the correct
    parent order, which is backwards when using "git pull master" from a
    topic branch.
    
    There are some special considerations when combining the --show-pulls
    option with --simplify-merges. This requires adding a new PULL_MERGE
    object flag to store the information from the initial TREESAME
    comparisons. This helps avoid dropping those commits in later filters.
    This is covered by a test, including how the parents can be simplified.
    Since "struct object" has already ruined its 32-bit alignment by using
    33 bits across parsed, type, and flags member, let's not make it worse.
    PULL_MERGE is used in revision.c with the same value (1u<<15) as
    REACHABLE in commit-graph.c. The REACHABLE flag is only used when
    writing a commit-graph file, and a revision walk using --show-pulls
    does not happen in the same process. Care must be taken in the future
    to ensure this remains the case.
    
    Update Documentation/rev-list-options.txt with significant details
    around this option. This requires updating the example in the
    History Simplification section to demonstrate some of the problems
    with TREESAME second parents.
    
    Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
    Signed-off-by: Junio C Hamano <gitster@pobox.com>
    derrickstolee authored and gitster committed Apr 10, 2020
    Configuration menu
    Copy the full SHA
    8d049e1 View commit details
    Browse the repository at this point in the history
Loading