@@ -342,6 +342,12 @@ Default mode::
342
342
branches if the end result is the same (i.e. merging branches
343
343
with the same content)
344
344
345
+ --show-pulls::
346
+ Include all commits from the default mode, but also any merge
347
+ commits that are not TREESAME to the first parent but are
348
+ TREESAME to a later parent. This mode is helpful for showing
349
+ the merge commits that "first introduced" a change to a branch.
350
+
345
351
--full-history::
346
352
Same as the default mode, but does not prune some history.
347
353
@@ -534,7 +540,7 @@ Note the major differences in `N`, `P`, and `Q` over `--full-history`:
534
540
parent and is TREESAME.
535
541
--
536
542
537
- Finally, there is a fifth simplification mode available:
543
+ There is another simplification mode available:
538
544
539
545
--ancestry-path::
540
546
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:
573
579
L--M
574
580
-----------------------------------------------------------------------
575
581
582
+ Before discussing another option, `--show-pulls`, we need to
583
+ create a new example history.
584
+ +
585
+ A common problem users face when looking at simplified history is that a
586
+ commit they know changed a file somehow does not appear in the file's
587
+ simplified history. Let's demonstrate a new example and show how options
588
+ such as `--full-history` and `--simplify-merges` works in that case:
589
+ +
590
+ -----------------------------------------------------------------------
591
+ .-A---M-----C--N---O---P
592
+ / / \ \ \/ / /
593
+ I B \ R-'`-Z' /
594
+ \ / \/ /
595
+ \ / /\ /
596
+ `---X--' `---Y--'
597
+ -----------------------------------------------------------------------
598
+ +
599
+ For this example, suppose `I` created `file.txt` which was modified by
600
+ `A`, `B`, and `X` in different ways. The single-parent commits `C`, `Z`,
601
+ and `Y` do not change `file.txt`. The merge commit `M` was created by
602
+ resolving the merge conflict to include both changes from `A` and `B`
603
+ and hence is not TREESAME to either. The merge commit `R`, however, was
604
+ created by ignoring the contents of `file.txt` at `M` and taking only
605
+ the contents of `file.txt` at `X`. Hence, `R` is TREESAME to `X` but not
606
+ `M`. Finally, the natural merge resolution to create `N` is to take the
607
+ contents of `file.txt` at `R`, so `N` is TREESAME to `R` but not `C`.
608
+ The merge commits `O` and `P` are TREESAME to their first parents, but
609
+ not to their second parents, `Z` and `Y` respectively.
610
+ +
611
+ When using the default mode, `N` and `R` both have a TREESAME parent, so
612
+ those edges are walked and the others are ignored. The resulting history
613
+ graph is:
614
+ +
615
+ -----------------------------------------------------------------------
616
+ I---X
617
+ -----------------------------------------------------------------------
618
+ +
619
+ When using `--full-history`, Git walks every edge. This will discover
620
+ the commits `A` and `B` and the merge `M`, but also will reveal the
621
+ merge commits `O` and `P`. With parent rewriting, the resulting graph is:
622
+ +
623
+ -----------------------------------------------------------------------
624
+ .-A---M--------N---O---P
625
+ / / \ \ \/ / /
626
+ I B \ R-'`--' /
627
+ \ / \/ /
628
+ \ / /\ /
629
+ `---X--' `------'
630
+ -----------------------------------------------------------------------
631
+ +
632
+ Here, the merge commits `O` and `P` contribute extra noise, as they did
633
+ not actually contribute a change to `file.txt`. They only merged a topic
634
+ that was based on an older version of `file.txt`. This is a common
635
+ issue in repositories using a workflow where many contributors work in
636
+ parallel and merge their topic branches along a single trunk: manu
637
+ unrelated merges appear in the `--full-history` results.
638
+ +
639
+ When using the `--simplify-merges` option, the commits `O` and `P`
640
+ disappear from the results. This is because the rewritten second parents
641
+ of `O` and `P` are reachable from their first parents. Those edges are
642
+ removed and then the commits look like single-parent commits that are
643
+ TREESAME to their parent. This also happens to the commit `N`, resulting
644
+ in a history view as follows:
645
+ +
646
+ -----------------------------------------------------------------------
647
+ .-A---M--.
648
+ / / \
649
+ I B R
650
+ \ / /
651
+ \ / /
652
+ `---X--'
653
+ -----------------------------------------------------------------------
654
+ +
655
+ In this view, we see all of the important single-parent changes from
656
+ `A`, `B`, and `X`. We also see the carefully-resolved merge `M` and the
657
+ not-so-carefully-resolved merge `R`. This is usually enough information
658
+ to determine why the commits `A` and `B` "disappeared" from history in
659
+ the default view. However, there are a few issues with this approach.
660
+ +
661
+ The first issue is performance. Unlike any previous option, the
662
+ `--simplify-merges` option requires walking the entire commit history
663
+ before returning a single result. This can make the option difficult to
664
+ use for very large repositories.
665
+ +
666
+ The second issue is one of auditing. When many contributors are working
667
+ on the same repository, it is important which merge commits introduced
668
+ a change into an important branch. The problematic merge `R` above is
669
+ not likely to be the merge commit that was used to merge into an
670
+ important branch. Instead, the merge `N` was used to merge `R` and `X`
671
+ into the important branch. This commit may have information about why
672
+ the change `X` came to override the changes from `A` and `B` in its
673
+ commit message.
674
+ +
675
+ The `--show-pulls` option helps with both of these issues by adding more
676
+ merge commits to the history results. If a merge is not TREESAME to its
677
+ first parent but is TREESAME to a later parent, then that merge is
678
+ treated as if it "pulled" the change from another branch. When using
679
+ `--show-pulls` on this example (and no other options) the resulting
680
+ graph is:
681
+ +
682
+ -----------------------------------------------------------------------
683
+ I---X---R---N
684
+ -----------------------------------------------------------------------
685
+ +
686
+ Here, the merge commits `R` and `N` are included because they pulled
687
+ the commits `X` and `R` into the base branch, respectively. These
688
+ merges are the reason the commits `A` and `B` do not appear in the
689
+ default history.
690
+ +
691
+ When `--show-pulls` is paired with `--simplify-merges`, the
692
+ graph includes all of the necessary information:
693
+ +
694
+ -----------------------------------------------------------------------
695
+ .-A---M--. N
696
+ / / \ /
697
+ I B R
698
+ \ / /
699
+ \ / /
700
+ `---X--'
701
+ -----------------------------------------------------------------------
702
+ +
703
+ Notice that since `M` is reachable from `R`, the edge from `N` to `M`
704
+ was simplified away. However, `N` still appears in the history as an
705
+ important commit because it "pulled" the change `R` into the main
706
+ branch.
707
+
576
708
The `--simplify-by-decoration` option allows you to view only the
577
709
big picture of the topology of the history, by omitting commits
578
710
that are not referenced by tags. Commits are marked as !TREESAME
0 commit comments