{"thread":{"id":"9700","subject":"[PATCH] simplify history by default","startedAt":"2007-08-30T06:25:12Z","lastAt":"2007-08-30T07:25:49Z","messageCount":2,"participants":["Michael S. Tsirkin","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"51874","messageId":"20070830062512.GB16312@mellanox.co.il","threadId":"9700","inReplyTo":null,"subject":"[PATCH] simplify history by default","fromName":"Michael S. Tsirkin","fromEmail":"mst@dev.mellanox.co.il","sentAt":"2007-08-30T06:25:12Z","receivedAt":"2007-08-30T06:25:12Z","isPatch":true,"sender":{"key":"mst@kernel.org","avatar":null},"body":"Simplify history if --no-merges is set, even if no pathspec\nis given.\n\nSigned-off-by: Michael S. Tsirkin <mst@dev.mellanox.co.il>\n\n---\n\nHi!\nIf I merge in a branch with -s ours, plain git log will still\nshow commits from this branch:\n\n$git checkout b\n$git merge -s ours a\n$ git log --pretty=oneline\n185166cad796945c52769033f16a4c1c9cd02f08 Merge branch 'a' into b\n4ee339d9c905dcc39e208fd476a5ca1163d2f8b3 commit for branch b\na2c872723eb585665c5e092059cc97115e63e80f commit for branch a\n0b4a099bd90c2ffcd21273afd59a0ee7d182a084 initial commit\n\nIf I limit the log to a path (any path), git log\nsimplifies the commit history:\n\n$git log --pretty=oneline -- .\n4ee339d9c905dcc39e208fd476a5ca1163d2f8b3 commit for branch b\n0b4a099bd90c2ffcd21273afd59a0ee7d182a084 initial commit\n\nWhich is better IMO, because the a branch is actually ignored.\nBut, is this behaviour documented? I actually discovered\nthis trick looking at the source:\n\tsetup_revisions does\n\t\t/* First, search for \"--\" */\n\t\tseen_dashdash = 0;\n\t\tfor (i = 1; i < argc; i++) {\n\t\t\tconst char *arg = argv[i];\n\t\t\tif (strcmp(arg, \"--\"))\n\t\t\t\tcontinue;\n\t\t\targv[i] = NULL;\n\t\t\targc = i;\n\t\t\trevs->prune_data = get_pathspec(revs->prefix, argv + i + 1);\n\t\t\tseen_dashdash = 1;\n\t\t\tbreak;\n\t\t}\n\n\tso prune_data seems to be set if there's a path spec; and then\n\n\t\tif (revs->prune_data) {\n\t\t\tdiff_tree_setup_paths(revs->prune_data, &revs->pruning);\n\t\t\t/* Can't prune commits with rename following: the paths change.. */\n\t\t\tif (!revs->diffopt.follow_renames)\n\t\t\t\trevs->prune_fn = try_to_simplify_commit;\n\t\t\tif (!revs->full_diff)\n\t\t\t\tdiff_tree_setup_paths(revs->prune_data, &revs->diffopt);\n\t\t}\n\n\tso try_to_simplify_commit is only called if there is prune_data,\n\n\nFurther, man git-rev-list says\n--full-history::\n\n\tShow also parts of history irrelevant to current state of a given path.\n\t\tThis turns off history simplification, which removed merges\n\t\twhich didn't change anything at all at some child. It will still\n\t\tactually simplify away merges that didn't change anything at all\n\t\tinto either child.\n\nwhich makes it seem like the default should be to do history simplification, but\nwhat actually happens is that the default is not to do simplification\nunless you give a path, in which case the default is to do simplification,\nand --full-history changes this:\n\n$git-rev-list HEAD\n185166cad796945c52769033f16a4c1c9cd02f08\n4ee339d9c905dcc39e208fd476a5ca1163d2f8b3\na2c872723eb585665c5e092059cc97115e63e80f\n0b4a099bd90c2ffcd21273afd59a0ee7d182a084\n\nSo it didn't hide branch a.\n\nWouldn't it make sense to make the simplified form a default, or enable it if\n--no-merges is set, or add a flag to enable history simplification, or at\nleast document this better?\n\nThe following patch implements the second option.\nComments?\n\nI would also really like to see, by default:\n$ git log --pretty=oneline\n185166cad796945c52769033f16a4c1c9cd02f08 Merge branch 'a' into b\n4ee339d9c905dcc39e208fd476a5ca1163d2f8b3 commit for branch b\n0b4a099bd90c2ffcd21273afd59a0ee7d182a084 initial commit\nOpinions?\n\ndiff --git a/revision.c b/revision.c\nindex 51fff0e..746eb9f 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1262,7 +1262,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \t\t\trevs->prune_fn = try_to_simplify_commit;\n \t\tif (!revs->full_diff)\n \t\t\tdiff_tree_setup_paths(revs->prune_data, &revs->diffopt);\n-\t}\n+\t} else if (revs->no_merges) /* Simplification can hide merge commits */\n+\t\trevs->prune_fn = try_to_simplify_commit;\n+\n \tif (revs->combine_merges) {\n \t\trevs->ignore_merges = 0;\n \t\tif (revs->dense_combined_merges && !revs->diffopt.output_format)\n\n-- \nMST\n"},{"id":"51879","messageId":"7vir6x8ow2.fsf@gitster.siamese.dyndns.org","threadId":"9700","inReplyTo":"20070830062512.GB16312@mellanox.co.il","subject":"Re: [PATCH] simplify history by default","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-30T07:25:49Z","receivedAt":"2007-08-30T07:25:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Michael S. Tsirkin\" <mst@dev.mellanox.co.il> writes:\n\n> Which is better IMO, because the a branch is actually ignored.\n> But, is this behaviour documented?\n\nFormal documentation is probably lacking.  Both Linus and I have\nexplained this \"history simplification\" countless times here and\non #git.  As a matter of fact, I think I did my latest round of\nexplanation on #git just a few days ago.\n\nThe thing is, neither of us is very good at documention --- we\ntend to offer explanation on demand _in context_.\n\n> Further, man git-rev-list says\n> --full-history::\n>\n> \tShow also parts of history irrelevant to current state of a given path.\n> \t\tThis turns off history simplification, which removed merges\n> \t\twhich didn't change anything at all at some child. It will still\n> \t\tactually simplify away merges that didn't change anything at all\n> \t\tinto either child.\n>\n> which makes it seem like the default should be to do history simplification, but\n> what actually happens is that the default is not to do simplification\n> unless you give a path, in which case the default is to do simplification,\n\nI would agree around the part you quoted is a good place to add\ndescriptions we gave in the past, and it is a good idea to do so\nat the very technical level.\n\nAt the same time, I think section #2 of the user manual\n\"Exploring git history\" should talk about path limited,\nsimplified history, in its \"Browsing revisions\" subsection, when\nit gives the example\n\n\t$ git log v2.5.. Makefile fs/\n\nAs the previous section has already introduced the history\ndiagram, it would help to draw a merge graph and how the history\nis simplified.\n\nSlides #116, #117 and #118 from\n\n\thttp://members.cox.net/junkio/200607-ols.pdf\n\ntalk about history simplification, which may be a good starting\npoint to steal from.\n\nAs to your patch, I am a bit reluctant to make the history\nsimplification for the \"whole tree\" history traversal default,\neven with --no-merges.  One thing we often use --no-merges is\nfor shortlog and I do want to see commits from both branches,\nwhen I have something like this:\n\n ... maint ...----o----A----B---C'\n                             \\   \\\n                              \\   \\\n ... master ... -----o----C----M---N\n\nwhere I first made a fix C on the 'master' branch, later\nbackported it to 'maint' as C' to fix the same issue (but\napplicable for the context of 'maint').  The merge made at N\nwill most likely result as if 'maint' was merged using 'ours'\nstrategy to 'master' because at point M, the master branch is\nsupposed to be in sync with and contain everything from 'maint',\nincluding the effect C' would bring to 'maint'.  I feel somewhat\nuneasy to drop C' when I am preparing to write release notes for\nN (or later).  Maybe this is just superstition, but when not\nusing path-limiting, I am really interested in who contributed\nin the whole system, whether the fruits of their efforts\nsurvived at the end or not.  The use case is quite different\nwhen looking at history with path limiters.\n"}]}