]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jk/log-fp-implies-m'
authorJunio C Hamano <gitster@pobox.com>
Tue, 18 Aug 2020 00:02:49 +0000 (17:02 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 18 Aug 2020 00:02:49 +0000 (17:02 -0700)
"git log --first-parent -p" showed patches only for single-parent
commits on the first-parent chain; the "--first-parent" option has
been made to imply "-m".  Use "--no-diff-merges" to restore the
previous behaviour to omit patches for merge commits.

* jk/log-fp-implies-m:
  doc/git-log: clarify handling of merge commit diffs
  doc/git-log: move "-t" into diff-options list
  doc/git-log: drop "-r" diff option
  doc/git-log: move "Diff Formatting" from rev-list-options
  log: enable "-m" automatically with "--first-parent"
  revision: add "--no-diff-merges" option to counteract "-m"
  log: drop "--cc implies -m" logic

1  2 
Documentation/git-log.txt
Documentation/rev-list-options.txt
builtin/log.c
revision.c
revision.h
t/t4013-diff-various.sh
t/t4013/diff.log_--no-diff-merges_-p_--first-parent_master
t/t4013/diff.log_-p_--first-parent_master

index 3fd26d52122b5a1b694fb33de9e34a37233d72f4,9ccba65469d7c6bc42fc8fb2de6fef36b1969061..27fa0ea26deed036981108d1bf1bb8a02b6a9f97
@@@ -15,12 -15,9 +15,12 @@@ DESCRIPTIO
  -----------
  Shows the commit logs.
  
 -The command takes options applicable to the `git rev-list`
 +:git-log: 1
 +include::rev-list-description.txt[]
 +
 +The command takes options applicable to the linkgit:git-rev-list[1]
  command to control what is shown and how, and options applicable to
 -the `git diff-*` commands to control how the changes
 +the linkgit:git-diff[1] command to control how the changes
  each commit introduces are shown.
  
  
@@@ -114,8 -111,47 +114,47 @@@ include::rev-list-options.txt[
  
  include::pretty-formats.txt[]
  
- COMMON DIFF OPTIONS
- -------------------
+ DIFF FORMATTING
+ ---------------
+ By default, `git log` does not generate any diff output. The options
+ below can be used to show the changes made by each commit.
+ Note that unless one of `-c`, `--cc`, or `-m` is given, merge commits
+ will never show a diff, even if a diff format like `--patch` is
+ selected, nor will they match search options like `-S`. The exception is
+ when `--first-parent` is in use, in which merges are treated like normal
+ single-parent commits (this can be overridden by providing a
+ combined-diff option or with `--no-diff-merges`).
+ -c::
+       With this option, diff output for a merge commit
+       shows the differences from each of the parents to the merge result
+       simultaneously instead of showing pairwise diff between a parent
+       and the result one at a time. Furthermore, it lists only files
+       which were modified from all parents.
+ --cc::
+       This flag implies the `-c` option and further compresses the
+       patch output by omitting uninteresting hunks whose contents in
+       the parents have only two variants and the merge result picks
+       one of them without modification.
+ --combined-all-paths::
+       This flag causes combined diffs (used for merge commits) to
+       list the name of the file from all parents.  It thus only has
+       effect when -c or --cc are specified, and is likely only
+       useful if filename changes are detected (i.e. when either
+       rename or copy detection have been requested).
+ -m::
+ --diff-merges::
+       This flag makes the merge commits show the full diff like
+       regular commits; for each merge parent, a separate log entry
+       and diff is generated. An exception is that only diff against
+       the first parent is shown when `--first-parent` option is given;
+       in that case, the output represents the changes the merge
+       brought _into_ the then-current branch.
  
  :git-log: 1
  include::diff-options.txt[]
index d3117ce51bfe2ca223f4e51927a6d7ec4e9bf374,398178d72a0b551e30fcf7f88b701907af124ccb..002379056a072cb87f7c65bbcaedaa4ebed7387a
@@@ -128,7 -128,8 +128,7 @@@ parents) and `--max-parents=-1` (negati
        because merges into a topic branch tend to be only about
        adjusting to updated upstream from time to time, and
        this option allows you to ignore the individual commits
 -      brought in to your history by such a merge. Cannot be
 -      combined with --bisect.
 +      brought in to your history by such a merge.
  
  --not::
        Reverses the meaning of the '{caret}' prefix (or lack thereof)
@@@ -206,7 -207,7 +206,7 @@@ ifndef::git-rev-list[
        Pretend as if the bad bisection ref `refs/bisect/bad`
        was listed and as if it was followed by `--not` and the good
        bisection refs `refs/bisect/good-*` on the command
 -      line. Cannot be combined with --first-parent.
 +      line.
  endif::git-rev-list[]
  
  --stdin::
@@@ -742,7 -743,7 +742,7 @@@ outputs 'midpoint', the output of the t
  would be of roughly the same length.  Finding the change which
  introduces a regression is thus reduced to a binary search: repeatedly
  generate and test new 'midpoint's until the commit chain is of length
 -one. Cannot be combined with --first-parent.
 +one.
  
  --bisect-vars::
        This calculates the same as `--bisect`, except that refs in
@@@ -1116,48 -1117,3 +1116,3 @@@ ifdef::git-rev-list[
        by a tab.
  endif::git-rev-list[]
  endif::git-shortlog[]
- ifndef::git-shortlog[]
- ifndef::git-rev-list[]
- Diff Formatting
- ~~~~~~~~~~~~~~~
- Listed below are options that control the formatting of diff output.
- Some of them are specific to linkgit:git-rev-list[1], however other diff
- options may be given. See linkgit:git-diff-files[1] for more options.
- -c::
-       With this option, diff output for a merge commit
-       shows the differences from each of the parents to the merge result
-       simultaneously instead of showing pairwise diff between a parent
-       and the result one at a time. Furthermore, it lists only files
-       which were modified from all parents.
- --cc::
-       This flag implies the `-c` option and further compresses the
-       patch output by omitting uninteresting hunks whose contents in
-       the parents have only two variants and the merge result picks
-       one of them without modification.
- --combined-all-paths::
-       This flag causes combined diffs (used for merge commits) to
-       list the name of the file from all parents.  It thus only has
-       effect when -c or --cc are specified, and is likely only
-       useful if filename changes are detected (i.e. when either
-       rename or copy detection have been requested).
- -m::
-       This flag makes the merge commits show the full diff like
-       regular commits; for each merge parent, a separate log entry
-       and diff is generated. An exception is that only diff against
-       the first parent is shown when `--first-parent` option is given;
-       in that case, the output represents the changes the merge
-       brought _into_ the then-current branch.
- -r::
-       Show recursive diffs.
- -t::
-       Show the tree objects in the diff output. This implies `-r`.
- endif::git-rev-list[]
- endif::git-shortlog[]
diff --combined builtin/log.c
index 33528fefa9de4754fce37c9f660241a10fdd22e3,83b147c23ad157d8d4718b3a73dc7419e1d4ea54..b58f8da09ef7a16a1df0a99aba36003dc8732a24
@@@ -599,8 -599,8 +599,8 @@@ static int show_tree_object(const struc
  static void show_setup_revisions_tweak(struct rev_info *rev,
                                       struct setup_revision_opt *opt)
  {
-       if (rev->ignore_merges) {
-               /* There was no "-m" on the command line */
+       if (rev->ignore_merges < 0) {
+               /* There was no "-m" variant on the command line */
                rev->ignore_merges = 0;
                if (!rev->first_parent_only && !rev->combine_merges) {
                        /* No "--first-parent", "-c", or "--cc" */
@@@ -732,8 -732,7 +732,7 @@@ static void log_setup_revisions_tweak(s
        if (!rev->diffopt.output_format && rev->combine_merges)
                rev->diffopt.output_format = DIFF_FORMAT_PATCH;
  
-       /* Turn -m on when --cc/-c was given */
-       if (rev->combine_merges)
+       if (rev->first_parent_only && rev->ignore_merges < 0)
                rev->ignore_merges = 0;
  }
  
@@@ -1128,18 -1127,18 +1127,18 @@@ do_pp
  
  static int get_notes_refs(struct string_list_item *item, void *arg)
  {
 -      argv_array_pushf(arg, "--notes=%s", item->string);
 +      strvec_pushf(arg, "--notes=%s", item->string);
        return 0;
  }
  
 -static void get_notes_args(struct argv_array *arg, struct rev_info *rev)
 +static void get_notes_args(struct strvec *arg, struct rev_info *rev)
  {
        if (!rev->show_notes) {
 -              argv_array_push(arg, "--no-notes");
 +              strvec_push(arg, "--no-notes");
        } else if (rev->notes_opt.use_default_notes > 0 ||
                   (rev->notes_opt.use_default_notes == -1 &&
                    !rev->notes_opt.extra_notes_refs.nr)) {
 -              argv_array_push(arg, "--notes");
 +              strvec_push(arg, "--notes");
        } else {
                for_each_string_list(&rev->notes_opt.extra_notes_refs, get_notes_refs, arg);
        }
@@@ -1217,7 -1216,7 +1216,7 @@@ static void make_cover_letter(struct re
                 * can be added later if deemed desirable.
                 */
                struct diff_options opts;
 -              struct argv_array other_arg = ARGV_ARRAY_INIT;
 +              struct strvec other_arg = STRVEC_INIT;
                diff_setup(&opts);
                opts.file = rev->diffopt.file;
                opts.use_color = rev->diffopt.use_color;
                get_notes_args(&other_arg, rev);
                show_range_diff(rev->rdiff1, rev->rdiff2,
                                rev->creation_factor, 1, &opts, &other_arg);
 -              argv_array_clear(&other_arg);
 +              strvec_clear(&other_arg);
        }
  }
  
diff --combined revision.c
index dc86ec8732cd0fb37089c6dbd3a95f559de580d0,669bc856694f9853b4067eb2027da4522fd6112e..97ae8f16a8865642868a9c8346223c30d7811cb9
@@@ -23,7 -23,7 +23,7 @@@
  #include "bisect.h"
  #include "packfile.h"
  #include "worktree.h"
 -#include "argv-array.h"
 +#include "strvec.h"
  #include "commit-reach.h"
  #include "commit-graph.h"
  #include "prio-queue.h"
@@@ -633,6 -633,7 +633,6 @@@ static unsigned int count_bloom_filter_
  static unsigned int count_bloom_filter_definitely_not;
  static unsigned int count_bloom_filter_false_positive;
  static unsigned int count_bloom_filter_not_present;
 -static unsigned int count_bloom_filter_length_zero;
  
  static void trace2_bloom_filter_statistics_atexit(void)
  {
  
        jw_object_begin(&jw, 0);
        jw_object_intmax(&jw, "filter_not_present", count_bloom_filter_not_present);
 -      jw_object_intmax(&jw, "zero_length_filter", count_bloom_filter_length_zero);
        jw_object_intmax(&jw, "maybe", count_bloom_filter_maybe);
        jw_object_intmax(&jw, "definitely_not", count_bloom_filter_definitely_not);
        jw_object_intmax(&jw, "false_positive", count_bloom_filter_false_positive);
@@@ -668,9 -670,9 +668,9 @@@ static void prepare_to_use_bloom_filter
  {
        struct pathspec_item *pi;
        char *path_alloc = NULL;
 -      const char *path;
 -      int last_index;
 -      int len;
 +      const char *path, *p;
 +      size_t len;
 +      int path_component_nr = 1;
  
        if (!revs->commits)
                return;
                return;
  
        pi = &revs->pruning.pathspec.items[0];
 -      last_index = pi->len - 1;
  
        /* remove single trailing slash from path, if needed */
 -      if (pi->match[last_index] == '/') {
 -          path_alloc = xstrdup(pi->match);
 -          path_alloc[last_index] = '\0';
 -          path = path_alloc;
 +      if (pi->len > 0 && pi->match[pi->len - 1] == '/') {
 +              path_alloc = xmemdupz(pi->match, pi->len - 1);
 +              path = path_alloc;
        } else
 -          path = pi->match;
 +              path = pi->match;
  
        len = strlen(path);
 +      if (!len) {
 +              revs->bloom_filter_settings = NULL;
 +              free(path_alloc);
 +              return;
 +      }
 +
 +      p = path;
 +      while (*p) {
 +              /*
 +               * At this point, the path is normalized to use Unix-style
 +               * path separators. This is required due to how the
 +               * changed-path Bloom filters store the paths.
 +               */
 +              if (*p == '/')
 +                      path_component_nr++;
 +              p++;
 +      }
 +
 +      revs->bloom_keys_nr = path_component_nr;
 +      ALLOC_ARRAY(revs->bloom_keys, revs->bloom_keys_nr);
  
 -      revs->bloom_key = xmalloc(sizeof(struct bloom_key));
 -      fill_bloom_key(path, len, revs->bloom_key, revs->bloom_filter_settings);
 +      fill_bloom_key(path, len, &revs->bloom_keys[0],
 +                     revs->bloom_filter_settings);
 +      path_component_nr = 1;
 +
 +      p = path + len - 1;
 +      while (p > path) {
 +              if (*p == '/')
 +                      fill_bloom_key(path, p - path,
 +                                     &revs->bloom_keys[path_component_nr++],
 +                                     revs->bloom_filter_settings);
 +              p--;
 +      }
  
        if (trace2_is_enabled() && !bloom_filter_atexit_registered) {
                atexit(trace2_bloom_filter_statistics_atexit);
@@@ -746,7 -720,7 +746,7 @@@ static int check_maybe_different_in_blo
                                                 struct commit *commit)
  {
        struct bloom_filter *filter;
 -      int result;
 +      int result = 1, j;
  
        if (!revs->repo->objects->commit_graph)
                return -1;
                return -1;
        }
  
 -      if (!filter->len) {
 -              count_bloom_filter_length_zero++;
 -              return -1;
 +      for (j = 0; result && j < revs->bloom_keys_nr; j++) {
 +              result = bloom_filter_contains(filter,
 +                                             &revs->bloom_keys[j],
 +                                             revs->bloom_filter_settings);
        }
  
 -      result = bloom_filter_contains(filter,
 -                                     revs->bloom_key,
 -                                     revs->bloom_filter_settings);
 -
        if (result)
                count_bloom_filter_maybe++;
        else
@@@ -805,7 -782,7 +805,7 @@@ static int rev_compare_tree(struct rev_
                        return REV_TREE_SAME;
        }
  
 -      if (revs->bloom_key && !nth_parent) {
 +      if (revs->bloom_keys_nr && !nth_parent) {
                bloom_ret = check_maybe_different_in_bloom_filter(revs, commit);
  
                if (bloom_ret == 0)
  
        tree_difference = REV_TREE_SAME;
        revs->pruning.flags.has_changes = 0;
 -      if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "",
 -                         &revs->pruning) < 0)
 -              return REV_TREE_DIFFERENT;
 +      diff_tree_oid(&t1->object.oid, &t2->object.oid, "", &revs->pruning);
  
        if (!nth_parent)
                if (bloom_ret == 1 && tree_difference == REV_TREE_SAME)
  
  static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
  {
 -      int retval;
        struct tree *t1 = get_commit_tree(commit);
  
        if (!t1)
  
        tree_difference = REV_TREE_SAME;
        revs->pruning.flags.has_changes = 0;
 -      retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
 +      diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
  
 -      return retval >= 0 && (tree_difference == REV_TREE_SAME);
 +      return tree_difference == REV_TREE_SAME;
  }
  
  struct treesame_state {
@@@ -1815,7 -1795,7 +1815,7 @@@ void repo_init_revisions(struct reposit
  
        revs->repo = r;
        revs->abbrev = DEFAULT_ABBREV;
-       revs->ignore_merges = 1;
+       revs->ignore_merges = -1;
        revs->simplify_history = 1;
        revs->pruning.repo = r;
        revs->pruning.flags.recursive = 1;
@@@ -2093,14 -2073,14 +2093,14 @@@ int handle_revision_arg(const char *arg
  }
  
  static void read_pathspec_from_stdin(struct strbuf *sb,
 -                                   struct argv_array *prune)
 +                                   struct strvec *prune)
  {
        while (strbuf_getline(sb, stdin) != EOF)
 -              argv_array_push(prune, sb->buf);
 +              strvec_push(prune, sb->buf);
  }
  
  static void read_revisions_from_stdin(struct rev_info *revs,
 -                                    struct argv_array *prune)
 +                                    struct strvec *prune)
  {
        struct strbuf sb;
        int seen_dashdash = 0;
@@@ -2335,7 -2315,7 +2335,7 @@@ static int handle_revision_opt(struct r
        } else if (!strcmp(arg, "--unpacked")) {
                revs->unpacked = 1;
        } else if (starts_with(arg, "--unpacked=")) {
 -              die("--unpacked=<packfile> no longer supported.");
 +              die(_("--unpacked=<packfile> no longer supported"));
        } else if (!strcmp(arg, "-r")) {
                revs->diff = 1;
                revs->diffopt.flags.recursive = 1;
                revs->diff = 1;
                revs->diffopt.flags.recursive = 1;
                revs->diffopt.flags.tree_in_recursive = 1;
-       } else if (!strcmp(arg, "-m")) {
+       } else if (!strcmp(arg, "-m") || !strcmp(arg, "--diff-merges")) {
                revs->ignore_merges = 0;
+       } else if (!strcmp(arg, "--no-diff-merges")) {
+               revs->ignore_merges = 1;
        } else if (!strcmp(arg, "-c")) {
                revs->diff = 1;
                revs->dense_combined_merges = 0;
@@@ -2695,7 -2677,7 +2697,7 @@@ static void NORETURN diagnose_missing_d
  int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt)
  {
        int i, flags, left, seen_dashdash, got_rev_arg = 0, revarg_opt;
 -      struct argv_array prune_data = ARGV_ARRAY_INIT;
 +      struct strvec prune_data = STRVEC_INIT;
        const char *submodule = NULL;
        int seen_end_of_options = 0;
  
                        argv[i] = NULL;
                        argc = i;
                        if (argv[i + 1])
 -                              argv_array_pushv(&prune_data, argv + i + 1);
 +                              strvec_pushv(&prune_data, argv + i + 1);
                        seen_dashdash = 1;
                        break;
                }
                        for (j = i; j < argc; j++)
                                verify_filename(revs->prefix, argv[j], j == i);
  
 -                      argv_array_pushv(&prune_data, argv + i);
 +                      strvec_pushv(&prune_data, argv + i);
                        break;
                }
                else
                        got_rev_arg = 1;
        }
  
 -      if (prune_data.argc) {
 +      if (prune_data.nr) {
                /*
                 * If we need to introduce the magic "a lone ':' means no
                 * pathspec whatsoever", here is the place to do so.
                 * }
                 */
                parse_pathspec(&revs->prune_data, 0, 0,
 -                             revs->prefix, prune_data.argv);
 +                             revs->prefix, prune_data.v);
        }
 -      argv_array_clear(&prune_data);
 +      strvec_clear(&prune_data);
  
        if (revs->def == NULL)
                revs->def = opt ? opt->def : NULL;
                        copy_pathspec(&revs->diffopt.pathspec,
                                      &revs->prune_data);
        }
-       if (revs->combine_merges)
+       if (revs->combine_merges && revs->ignore_merges < 0)
                revs->ignore_merges = 0;
+       if (revs->ignore_merges < 0)
+               revs->ignore_merges = 1;
        if (revs->combined_all_paths && !revs->combine_merges)
                die("--combined-all-paths makes no sense without -c or --cc");
  
        if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
                die("cannot use --grep-reflog without --walk-reflogs");
  
 -      if (revs->first_parent_only && revs->bisect)
 -              die(_("--first-parent is incompatible with --bisect"));
 -
        if (revs->line_level_traverse &&
            (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
                die(_("-L does not yet support diff formats besides -p and -s"));
diff --combined revision.h
index 889216c2d8bd0c330e05ccb439e446b5e0543542,5258024743c11b28a6ea958bbca557f4df7dbedc..c1e5bcf139d7a31d9bf851ada3bc8373f5ab932e
@@@ -190,11 -190,11 +190,11 @@@ struct rev_info 
                        show_root_diff:1,
                        no_commit_id:1,
                        verbose_header:1,
-                       ignore_merges:1,
                        combine_merges:1,
                        combined_all_paths:1,
                        dense_combined_merges:1,
                        always_show_header:1;
+       int             ignore_merges:2;
  
        /* Format info */
        int             show_notes;
        struct topo_walk_info *topo_walk_info;
  
        /* Commit graph bloom filter fields */
 -      /* The bloom filter key for the pathspec */
 -      struct bloom_key *bloom_key;
 +      /* The bloom filter key(s) for the pathspec */
 +      struct bloom_key *bloom_keys;
 +      int bloom_keys_nr;
 +
        /*
         * The bloom filter settings used to generate the key.
         * This is loaded from the commit-graph being used.
diff --combined t/t4013-diff-various.sh
index 3f60f7d96ce1998cd977751158c09cadfd926d15,40e222c94520fd661cb66a5f8aaa4cf4499ed997..2a57f9033e8c8a50e5a29ad09b677b9dfa468019
@@@ -117,12 -117,12 +117,12 @@@ test_expect_success setup 
  
  : <<\EOF
  ! [initial] Initial
 - * [master] Merge branch 'side' into master
 + * [master] Merge branch 'side'
    ! [rearrange] Rearranged lines in dir/sub
     ! [side] Side
  ----
    +  [rearrange] Rearranged lines in dir/sub
 - -   [master] Merge branch 'side' into master
 + -   [master] Merge branch 'side'
   * + [side] Side
   *   [master^] Third
   *   [master~2] Second
@@@ -297,6 -297,7 +297,7 @@@ log --root --patch-with-stat --summary 
  log --root -c --patch-with-stat --summary master
  # improved by Timo's patch
  log --root --cc --patch-with-stat --summary master
+ log --no-diff-merges -p --first-parent master
  log -p --first-parent master
  log -m -p --first-parent master
  log -m -p master
index 0000000000000000000000000000000000000000,94bf1850b29bbfb8f1f1917c8d35c98633733521..597002232e5209bcc3723baecacc0339258487c7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,78 +1,78 @@@
 -    Merge branch 'side' into master
+ $ git log --no-diff-merges -p --first-parent master
+ commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+ Merge: 9a6d494 c7a2ab9
+ Author: A U Thor <author@example.com>
+ Date:   Mon Jun 26 00:04:00 2006 +0000
++    Merge branch 'side'
+ commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+ Author: A U Thor <author@example.com>
+ Date:   Mon Jun 26 00:02:00 2006 +0000
+     Third
+ diff --git a/dir/sub b/dir/sub
+ index 8422d40..cead32e 100644
+ --- a/dir/sub
+ +++ b/dir/sub
+ @@ -2,3 +2,5 @@ A
+  B
+  C
+  D
+ +E
+ +F
+ diff --git a/file1 b/file1
+ new file mode 100644
+ index 0000000..b1e6722
+ --- /dev/null
+ +++ b/file1
+ @@ -0,0 +1,3 @@
+ +A
+ +B
+ +C
+ commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+ Author: A U Thor <author@example.com>
+ Date:   Mon Jun 26 00:01:00 2006 +0000
+     Second
+     
+     This is the second commit.
+ diff --git a/dir/sub b/dir/sub
+ index 35d242b..8422d40 100644
+ --- a/dir/sub
+ +++ b/dir/sub
+ @@ -1,2 +1,4 @@
+  A
+  B
+ +C
+ +D
+ diff --git a/file0 b/file0
+ index 01e79c3..b414108 100644
+ --- a/file0
+ +++ b/file0
+ @@ -1,3 +1,6 @@
+  1
+  2
+  3
+ +4
+ +5
+ +6
+ diff --git a/file2 b/file2
+ deleted file mode 100644
+ index 01e79c3..0000000
+ --- a/file2
+ +++ /dev/null
+ @@ -1,3 +0,0 @@
+ -1
+ -2
+ -3
+ commit 444ac553ac7612cc88969031b02b3767fb8a353a
+ Author: A U Thor <author@example.com>
+ Date:   Mon Jun 26 00:00:00 2006 +0000
+     Initial
+ $
index 3fc896d424f9471aa793cd6e9e0dda41264acb9b,fe044399f04ecc672340b405ae807a976b1c8fb6..28840ebea1e33a41402b392833093df2e92f8035
@@@ -4,8 -4,30 +4,30 @@@ Merge: 9a6d494 c7a2ab
  Author: A U Thor <author@example.com>
  Date:   Mon Jun 26 00:04:00 2006 +0000
  
 -    Merge branch 'side' into master
 +    Merge branch 'side'
  
+ diff --git a/dir/sub b/dir/sub
+ index cead32e..992913c 100644
+ --- a/dir/sub
+ +++ b/dir/sub
+ @@ -4,3 +4,5 @@ C
+  D
+  E
+  F
+ +1
+ +2
+ diff --git a/file0 b/file0
+ index b414108..10a8a9f 100644
+ --- a/file0
+ +++ b/file0
+ @@ -4,3 +4,6 @@
+  4
+  5
+  6
+ +A
+ +B
+ +C
  commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
  Author: A U Thor <author@example.com>
  Date:   Mon Jun 26 00:02:00 2006 +0000