summaryrefslogtreecommitdiff
path: root/Documentation/rev-list-options.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/rev-list-options.txt')
-rw-r--r--Documentation/rev-list-options.txt134
1 files changed, 133 insertions, 1 deletions
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index bfd02ad..04ad7dd 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -342,6 +342,12 @@ Default mode::
branches if the end result is the same (i.e. merging branches
with the same content)
+--show-pulls::
+ Include all commits from the default mode, but also any merge
+ commits that are not TREESAME to the first parent but are
+ TREESAME to a later parent. This mode is helpful for showing
+ the merge commits that "first introduced" a change to a branch.
+
--full-history::
Same as the default mode, but does not prune some history.
@@ -534,7 +540,7 @@ Note the major differences in `N`, `P`, and `Q` over `--full-history`:
parent and is TREESAME.
--
-Finally, there is a fifth simplification mode available:
+There is another simplification mode available:
--ancestry-path::
Limit the displayed commits to those directly on the ancestry
@@ -573,6 +579,132 @@ option does. Applied to the 'D..M' range, it results in:
L--M
-----------------------------------------------------------------------
+Before discussing another option, `--show-pulls`, we need to
+create a new example history.
++
+A common problem users face when looking at simplified history is that a
+commit they know changed a file somehow does not appear in the file's
+simplified history. Let's demonstrate a new example and show how options
+such as `--full-history` and `--simplify-merges` works in that case:
++
+-----------------------------------------------------------------------
+ .-A---M-----C--N---O---P
+ / / \ \ \/ / /
+ I B \ R-'`-Z' /
+ \ / \/ /
+ \ / /\ /
+ `---X--' `---Y--'
+-----------------------------------------------------------------------
++
+For this example, suppose `I` created `file.txt` which was modified by
+`A`, `B`, and `X` in different ways. The single-parent commits `C`, `Z`,
+and `Y` do not change `file.txt`. The merge commit `M` was created by
+resolving the merge conflict to include both changes from `A` and `B`
+and hence is not TREESAME to either. The merge commit `R`, however, was
+created by ignoring the contents of `file.txt` at `M` and taking only
+the contents of `file.txt` at `X`. Hence, `R` is TREESAME to `X` but not
+`M`. Finally, the natural merge resolution to create `N` is to take the
+contents of `file.txt` at `R`, so `N` is TREESAME to `R` but not `C`.
+The merge commits `O` and `P` are TREESAME to their first parents, but
+not to their second parents, `Z` and `Y` respectively.
++
+When using the default mode, `N` and `R` both have a TREESAME parent, so
+those edges are walked and the others are ignored. The resulting history
+graph is:
++
+-----------------------------------------------------------------------
+ I---X
+-----------------------------------------------------------------------
++
+When using `--full-history`, Git walks every edge. This will discover
+the commits `A` and `B` and the merge `M`, but also will reveal the
+merge commits `O` and `P`. With parent rewriting, the resulting graph is:
++
+-----------------------------------------------------------------------
+ .-A---M--------N---O---P
+ / / \ \ \/ / /
+ I B \ R-'`--' /
+ \ / \/ /
+ \ / /\ /
+ `---X--' `------'
+-----------------------------------------------------------------------
++
+Here, the merge commits `O` and `P` contribute extra noise, as they did
+not actually contribute a change to `file.txt`. They only merged a topic
+that was based on an older version of `file.txt`. This is a common
+issue in repositories using a workflow where many contributors work in
+parallel and merge their topic branches along a single trunk: manu
+unrelated merges appear in the `--full-history` results.
++
+When using the `--simplify-merges` option, the commits `O` and `P`
+disappear from the results. This is because the rewritten second parents
+of `O` and `P` are reachable from their first parents. Those edges are
+removed and then the commits look like single-parent commits that are
+TREESAME to their parent. This also happens to the commit `N`, resulting
+in a history view as follows:
++
+-----------------------------------------------------------------------
+ .-A---M--.
+ / / \
+ I B R
+ \ / /
+ \ / /
+ `---X--'
+-----------------------------------------------------------------------
++
+In this view, we see all of the important single-parent changes from
+`A`, `B`, and `X`. We also see the carefully-resolved merge `M` and the
+not-so-carefully-resolved merge `R`. This is usually enough information
+to determine why the commits `A` and `B` "disappeared" from history in
+the default view. However, there are a few issues with this approach.
++
+The first issue is performance. Unlike any previous option, the
+`--simplify-merges` option requires walking the entire commit history
+before returning a single result. This can make the option difficult to
+use for very large repositories.
++
+The second issue is one of auditing. When many contributors are working
+on the same repository, it is important which merge commits introduced
+a change into an important branch. The problematic merge `R` above is
+not likely to be the merge commit that was used to merge into an
+important branch. Instead, the merge `N` was used to merge `R` and `X`
+into the important branch. This commit may have information about why
+the change `X` came to override the changes from `A` and `B` in its
+commit message.
++
+The `--show-pulls` option helps with both of these issues by adding more
+merge commits to the history results. If a merge is not TREESAME to its
+first parent but is TREESAME to a later parent, then that merge is
+treated as if it "pulled" the change from another branch. When using
+`--show-pulls` on this example (and no other options) the resulting
+graph is:
++
+-----------------------------------------------------------------------
+ I---X---R---N
+-----------------------------------------------------------------------
++
+Here, the merge commits `R` and `N` are included because they pulled
+the commits `X` and `R` into the base branch, respectively. These
+merges are the reason the commits `A` and `B` do not appear in the
+default history.
++
+When `--show-pulls` is paired with `--simplify-merges`, the
+graph includes all of the necessary information:
++
+-----------------------------------------------------------------------
+ .-A---M--. N
+ / / \ /
+ I B R
+ \ / /
+ \ / /
+ `---X--'
+-----------------------------------------------------------------------
++
+Notice that since `M` is reachable from `R`, the edge from `N` to `M`
+was simplified away. However, `N` still appears in the history as an
+important commit because it "pulled" the change `R` into the main
+branch.
+
The `--simplify-by-decoration` option allows you to view only the
big picture of the topology of the history, by omitting commits
that are not referenced by tags. Commits are marked as !TREESAME