{"thread":{"id":"4458","subject":"gitweb.cgi history not shown","startedAt":"2006-06-11T05:31:17Z","lastAt":"2006-06-11T17:57:35Z","messageCount":8,"participants":["Marco Costalba","Linus Torvalds","Jakub Narebski"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"21573","messageId":"e5bfff550606102231o756f6d11lc46fecdad29568c0@mail.gmail.com","threadId":"4458","inReplyTo":null,"subject":"gitweb.cgi history not shown","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2006-06-11T05:31:17Z","receivedAt":"2006-06-11T05:31:17Z","isPatch":false,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":"What I do wrong?\n\n$ git-rev-list --all -- gitweb/gitweb.cgi\n0a8f4f0020cb35095005852c0797f0b90e9ebb74\n$ git-rev-list --all -- gitweb.cgi\n$\n\nAlso the installed gitweb at kernel.org gives an empty history for\nfile gitweb.cgi under git repository, while the history is correctly\nshown for the same file under the gitweb project.\n\n    Marco\n"},{"id":"21574","messageId":"Pine.LNX.4.64.0606102248360.5498@g5.osdl.org","threadId":"4458","inReplyTo":"e5bfff550606102231o756f6d11lc46fecdad29568c0@mail.gmail.com","subject":"Re: gitweb.cgi history not shown","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-11T06:02:10Z","receivedAt":"2006-06-11T06:02:10Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 11 Jun 2006, Marco Costalba wrote:\n>\n> What I do wrong?\n> \n> $ git-rev-list --all -- gitweb/gitweb.cgi\n> 0a8f4f0020cb35095005852c0797f0b90e9ebb74\n> $ git-rev-list --all -- gitweb.cgi\n> $\n\n[ no output ]\n\nThis is getting to be a FAQ, and I think we should add the \n\"--no-prune-history\" flag (or whatever I called it - I even sent out a \npatch for it) so that you can avoid it.\n\nThe thing that happens in\n\n\tgit-rev-list --all -- gitweb.cgi\n\nis that since your _current_ HEAD does not have that file at all, it \nstarts going back in history, and at each merge it finds it will \n_simplify_ the history, and only look at that part of history that is \nidentical _with_respect_to_the_name_you_gave_!\n\nNow, in the main git history, that name has NEVER existed, so the \nsimplified history for that particular name (as seen from the current \nbranch) is simply empty. It's empty all the way back to the root. No \ncommits at all add that name along the main history branch.\n\nNow, that name obviously existed in the _side_ histories, but we don't \nshow those, because they obviously didn't matter (as far as that \nparticular name happened) within the particular history starting point you \nchose. See?\n\nNow, look what happens if you instead of starting the history search from \nall the _current_ heads, you start it from a location that actually _had_ \nthat file:\n\n\tgit log 1130ef362fc8d9c3422c23f5d5 -- gitweb.cgi\n\nand suddenly there the history is - in all its glory.\n\nSo what this boils down to is really: when you limit revision history by a \nset of filenames, GIT REALLY REWRITES AND SIMPLIFIES THE HISTORY AS PER \n_THAT_ PARTICULAR SET OF FILENAMES. In particular, it will generate the \n_simplest_ history that is consistent with the state of those filenames at \nthe point you asked it to start.\n\nIf you want to get the non-simplified history (ie you object to the fact \nthat we give the simplest history, you want _all_ the possible history for \nthat particular filename, whether it was the same along one branch or \nnot), you need to apply something like the appended..\n\n(And you obviously need to add that \"no_simplify_merge\" flag to the \nrevision data structure, and you need to add some command line flag to \nenable it. Alternatively, try to find the patch I sent out a couple of \nmonths ago, I'm pretty sure I called it \"--no-simplify-merge\" or \n\"--no-prune-history\" or something like that).\n\n\t\tLinus\n---\ndiff --git a/revision.c b/revision.c\nindex 6a6952c..5640cef 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -303,7 +303,7 @@ static void try_to_simplify_commit(struc\n \t\tparse_commit(p);\n \t\tswitch (rev_compare_tree(revs, p->tree, commit->tree)) {\n \t\tcase REV_TREE_SAME:\n-\t\t\tif (p->object.flags & UNINTERESTING) {\n+\t\t\tif (revs->no_simplify_merge || (p->object.flags & UNINTERESTING)) {\n \t\t\t\t/* Even if a merge with an uninteresting\n \t\t\t\t * side branch brought the entire change\n \t\t\t\t * we are interested in, we do not want\n"},{"id":"21575","messageId":"e5bfff550606102332v6afb7d51m43ad5d74ba226cf0@mail.gmail.com","threadId":"4458","inReplyTo":"Pine.LNX.4.64.0606102248360.5498@g5.osdl.org","subject":"Re: gitweb.cgi history not shown","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2006-06-11T06:32:43Z","receivedAt":"2006-06-11T06:32:43Z","isPatch":false,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":">\n> Now, look what happens if you instead of starting the history search from\n> all the _current_ heads, you start it from a location that actually _had_\n> that file:\n>\n>         git log 1130ef362fc8d9c3422c23f5d5 -- gitweb.cgi\n>\n> and suddenly there the history is - in all its glory.\n>\n\nWhy I still get empty results if I run git-rev-list from gitweb merge point?\n\n$ git-rev-list 0a8f4f0020cb35095005852c0797f0b90e9ebb74 -- gitweb.cgi\n$\n$ git-rev-list 0a8f4f0020cb35095005852c0797f0b90e9ebb74 -- gitweb/gitweb.cgi\n0a8f4f0020cb35095005852c0797f0b90e9ebb74\n\nIs this because path changed: gitweb.cgi -> gitweb/gitweb.cgi\n\nI would like to think the problem is the path change because in case\nof gitk, merge of a parallel branch but with _no_ path change,\neverything worked as expected.\n\nSo the question is the path change was \"fixed up\" by hand or done as\npart of gitweb branch merge process, in the latter case probably\ngit-rev-list should already take in account this without special flags\n_and_ without removing history traversal optimizations that are good\nand useful in the remaining 99% of cases (for a GUI tool is difficult\nto know when to use a flag like --no-simplify-merge or not on a per\nrequest basis).\n\n        Marco\n"},{"id":"21600","messageId":"Pine.LNX.4.64.0606110902090.5498@g5.osdl.org","threadId":"4458","inReplyTo":"e5bfff550606102332v6afb7d51m43ad5d74ba226cf0@mail.gmail.com","subject":"Re: gitweb.cgi history not shown","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-11T16:19:06Z","receivedAt":"2006-06-11T16:19:06Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 11 Jun 2006, Marco Costalba wrote:\n> \n> Why I still get empty results if I run git-rev-list from gitweb merge point?\n\nBecause the rename happened _inside_ the merge. \n\nSo when you give the revision 0a8f4f00, that really means the state \n_after_ the merge. At that point, the filename doesn't actually exist.\n\ngit-rev-list then looks at the parents, one by one, and sees that the \nfirst parent _matches_ the state as far as your path spec is concerned (in \nthis case, it matches \"it was empty before, it was empty after\"), so it \nwill literally _always_ pick the parent that you're not interested in \n(regardless of whether it would have been merged into, or was the one that \ngot merged), because that's the one with the minimal history difference.\n\nGoing the other way (the way you actually wish it went) would have \nintroduced more history changes that aren't needed to explain the final \nstate, so git-rev-list - by virtue of trying to generate a _minimal_ \nhistory - will actively avoid it.\n\n> Is this because path changed: gitweb.cgi -> gitweb/gitweb.cgi\n\nWell, in one sense yes, but in a much more fundamental sense that rename \nreally has nothing to do with the real issue.\n\nThe real issue is that you asked how the state of a non-existent file came \nto be, and git-rev-list told you the simplest answer: it never existed at \nall.\n\nAnd that answer is actually _true_. Along one history, that filename never \nexisted.\n\nAnd this really has nothing to do with renames. You can see the exact same \nthing with files that are there. Let's take an example:\n\n\t   A\t<-- top of tree\n\t  / \\\n\t B   C\n\t |   |\n\t D   E\n\t  \\ /\n\t   F\n\t   |\n\t   .\t<-- old history\n\t   .\n\nLet's say that you have had a file called \"file\" for all of history, and \nit got changed sligtly differently in _all_ commits B, C, D _and_ E.\n\nNow, despite all the different changes, let's say that the end result was \nidentical in B and C - even though the diffs of those two commits were not \nnecessarily the same (because they started out from different points: D \nand E respectively). \n\nIn other words, there was a branch, but both branches ended up fixing the \nsame bug the same way (and this is less unusual than you'd think, even if \nthey are independent, but even more so if the branches \"knew of each \nother\" some other way, ie the developers talked about the problem and \nperhaps sent patches back-and-forth that both people applied).\n\nWhat do you think git-rev-list will do when you give it that \"file\" as a \npath limiter?\n\nWhat it will do is to notice that merge A has the same state (wrt that \nfile) as commit B (it's first parent), SO IT WILL TOTALLY IGNORE THE WHOLE \nHISTORY THAT IS REACHABLE FROM C.\n\nSo git-rev-list will first simplify the tree to just A -> B -> D -> F .., \nand then, since A and B were identical in the path (and let's say F was \nidentical to it's parents too), it will actually decide that as far as \nthose commits were concerned, nothing changed, so the actual end result is \njust \"B -> D -> ...\", and none of A, C, E and F show up at all, even \nthough both C and E really did change something (they just didn't \n_matter_, because all the changes could be explained by just picking B and \nD).\n\nSee? No renames. The renames is not what is fundamental here. What is \nfundamental is the _STATE_ of the tree. Remember: that's what git tracks, \nand that is what \"git log\" shows you.\n\nSo when you do\n\n\tgit log -- gitweb.cgi\n\nyou're really asking for: \"Please explain the state of the current tree \nwith regards to gitweb.cgi that doesn't exist at this point in time\". And \nthat's _exactly_ what \"git log\" will do. It will say \"hey, I can explain \nit by the file not existing in one of the previous parents either: maybe \nit got removed there\", and walk back as far as it possibly can to explain \nthat the file doesn't exist.\n\nAnd it turns out that it can walk all the way back to the root, and the \nfile didn't exist there, so the end result is what? The empty set. \n\n\t\t\tLinus\n"},{"id":"21601","messageId":"Pine.LNX.4.64.0606110933040.5498@g5.osdl.org","threadId":"4458","inReplyTo":"Pine.LNX.4.64.0606110902090.5498@g5.osdl.org","subject":"Re: gitweb.cgi history not shown","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-11T16:40:36Z","receivedAt":"2006-06-11T16:40:36Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 11 Jun 2006, Linus Torvalds wrote:\n> \n> See? No renames. The renames is not what is fundamental here. What is \n> fundamental is the _STATE_ of the tree. Remember: that's what git tracks, \n> and that is what \"git log\" shows you.\n\nBtw, this is also why I suggested adding a \"--no-simplify-history\" flag, \nbecause in this case, that's exactly what _you_ want. The reason git is \ndoing something unexpected - and in your case inferior - is exactly that \nwhat you want in this case is really not \"explain the STATE of this file\", \nbut you want \"give me ALL THE HISTORY concerning this filename\".\n\nBoth are very valid things to ask for, it just happens that \"git log\" by \ndefault answers the _other_ question. It does NOT answer the \"what is all \nthe history\" question that you're asking, it answers the \"how did this \nstate come to be\" question.\n\nBtw, the original \"git whatchanged -p\" answered exactly the question you \nhad, and the semantics changed when we rewrite \"git whatchanged\" to act \nlike \"git log -p\". But you can still get the old semantics by hand, if you \nreally want it, by doing\n\n\tgit-rev-list --all | git-diff-tree -p -- <filename>\n\nbecause (and this actually makes total sense when you look at it), you now \nactually say \"first give me all the history\" and then \"show the actual \nchanges in that history as it pertains to <filename>\".\n\nSee? \n\nI hope this explains the not-so-subtle (but still easy to overlook) \ndifference between the two.\n\nAnd I do agree that we should teach \"git log\" and friends to be able to \nanswer both questions, and that's what my suggested patch (fleshed out \nproperly, of course) should do.\n\nNot that I ever _tested_ it, of course. Me? Testing? You make me laugh. Ho \nHo Ho.\n\n\t\t\tLinus\n"},{"id":"21604","messageId":"Pine.LNX.4.64.0606110948090.5498@g5.osdl.org","threadId":"4458","inReplyTo":"Pine.LNX.4.64.0606110933040.5498@g5.osdl.org","subject":"Re: gitweb.cgi history not shown","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-11T16:54:19Z","receivedAt":"2006-06-11T16:54:19Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nI just like talking to myself.\n\nOn Sun, 11 Jun 2006, Linus Torvalds wrote:\n> \n> \tgit-rev-list --all | git-diff-tree -p -- <filename>\n\nThat obviously wants a \"--stdin\" argument to git-diff-tree, and I might as \nwell point out that it has a few other differences to doing this with the \n\"--no-simplify-history\" flag:\n\n - git-diff-tree obviously doesn't show merges normally, and when it does, \n   it would show only merges that change the file. In contrast, the \"git \n   log\" approach would show all merges that are part of the resulting \n   history (which, since you don't simplify merges, is _all_ of them).\n\n - the extra flag to \"git log\" approach allows \"--parents\" to work, ie the \n   stretches of commits in between merges would have their parents \n   rewritten, so that the history would be a unified whole, and you can \n   use qgit/gitk to show the result. The above pipeline obviously cannot \n   do that, since doing the filename limiter in git-diff-tree means that \n   it doesn't ever even _see_ the \"history\" part, it's just doing it one \n   commit at a time.\n\nThat concludes my monologue on the matter, I hope. If somebody wants to \ncondense the issue of \"show all history\" vs \"show how we got to this \nstate\" and add it to the Wiki FAQ thing, that would probably be good.\n\n\t\tLinus\n"},{"id":"21605","messageId":"e6hi4g$k4a$1@sea.gmane.org","threadId":"4458","inReplyTo":"Pine.LNX.4.64.0606110933040.5498@g5.osdl.org","subject":"Re: gitweb.cgi history not shown","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-06-11T16:59:15Z","receivedAt":"2006-06-11T16:59:15Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Linus Torvalds wrote:\n\n\n> Btw, this is also why I suggested adding a \"--no-simplify-history\" flag, \n> because in this case, that's exactly what _you_ want. The reason git is \n> doing something unexpected - and in your case inferior - is exactly that \n> what you want in this case is really not \"explain the STATE of this file\", \n> but you want \"give me ALL THE HISTORY concerning this filename\".\n[...]\n> Btw, the original \"git whatchanged -p\" answered exactly the question you \n> had, and the semantics changed when we rewrite \"git whatchanged\" to act \n> like \"git log -p\". \n[...]\n> And I do agree that we should teach \"git log\" and friends to be able to \n> answer both questions, and that's what my suggested patch (fleshed out \n> properly, of course) should do.\n\nCould we please 'git whatchanged -p' default to the original (before\nrewrite) behavior, i.e. ALL THE HISTORY?\n\n-- \nJakub Narebski\nWarsaw, Poland\n"},{"id":"21607","messageId":"Pine.LNX.4.64.0606111044160.5498@g5.osdl.org","threadId":"4458","inReplyTo":"e6hi4g$k4a$1@sea.gmane.org","subject":"Re: gitweb.cgi history not shown","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-11T17:57:35Z","receivedAt":"2006-06-11T17:57:35Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 11 Jun 2006, Jakub Narebski wrote:\n> \n> Could we please 'git whatchanged -p' default to the original (before\n> rewrite) behavior, i.e. ALL THE HISTORY?\n\nOk, here's the full patch to do that.\n\nIt does:\n\n - add a \"rev.simplify_history\" flag which defaults to on\n - it turns it off for \"git whatchanged\" (which thus now has real\n   semantics outside of \"git log\")\n - it adds a command line flag (\"--full-history\") to turn it off for \n   others (ie you can make \"git log\" and \"gitk\" etc get the semantics if \n   you want to.\n\nNow, just as an example of _why_ you really really really want to simplify \nhistory by default, apply this patch, install it, and try these two \ncommand lines:\n\n\tgitk --full-history -- git.c\n\tgitk -- git.c\n\nand compare the output. \n\nSo with this, you can also now do\n\n\tgit whatchanged -p -- gitweb.cgi\n\tgit log -p --full-history -- gitweb.cgi\n\nand it will show the old history of gitweb.cgi, even though it's not \nrelevant to the _current_ state of the name \"gitweb.cgi\"\n\nNOTE NOTE NOTE! It will still actually simplify away merges that didn't \nchange anything at all into either child. That creates these bogus strange \ndiscontinuities if you look at it with \"gitk\" (look at the --full-history \ngitk output for git.c, and you'll see a few strange cases).\n\nSo the whole \"--parent\" thing ends up somewhat bogus with --full-history \nbecause of this, but I'm not sure it's worth even worrying about. I don't \nthink you'd ever want to really use \"--full-history\" with the graphical \nrepresentation, I just give it as an example exactly to show _why_ doing \nso would be insane.\n\nI think this is trivial enough and useful enough to be worth merging into \nthe stable branch.\n\n\t\t\tLinus\n\n---\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 29a8851..4407f06 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -51,6 +51,7 @@ int cmd_whatchanged(int argc, const char\n \tinit_revisions(&rev);\n \trev.diff = 1;\n \trev.diffopt.recursive = 1;\n+\trev.simplify_history = 0;\n \treturn cmd_log_wc(argc, argv, envp, &rev);\n }\n \ndiff --git a/revision.c b/revision.c\nindex 6a6952c..75c648c 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -303,7 +303,7 @@ static void try_to_simplify_commit(struc\n \t\tparse_commit(p);\n \t\tswitch (rev_compare_tree(revs, p->tree, commit->tree)) {\n \t\tcase REV_TREE_SAME:\n-\t\t\tif (p->object.flags & UNINTERESTING) {\n+\t\t\tif (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {\n \t\t\t\t/* Even if a merge with an uninteresting\n \t\t\t\t * side branch brought the entire change\n \t\t\t\t * we are interested in, we do not want\n@@ -519,6 +519,7 @@ void init_revisions(struct rev_info *rev\n \n \trevs->abbrev = DEFAULT_ABBREV;\n \trevs->ignore_merges = 1;\n+\trevs->simplify_history = 1;\n \trevs->pruning.recursive = 1;\n \trevs->pruning.add_remove = file_add_remove;\n \trevs->pruning.change = file_change;\n@@ -756,6 +757,10 @@ int setup_revisions(int argc, const char\n \t\t\t\trevs->full_diff = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--full-history\")) {\n+\t\t\t\trevs->simplify_history = 0;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\topts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);\n \t\t\tif (opts > 0) {\n \t\t\t\trevs->diff = 1;\ndiff --git a/revision.h b/revision.h\nindex 7d85b0f..4020e25 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -30,6 +30,7 @@ struct rev_info {\n \t\t\tno_merges:1,\n \t\t\tno_walk:1,\n \t\t\tremove_empty_trees:1,\n+\t\t\tsimplify_history:1,\n \t\t\tlifo:1,\n \t\t\ttopo_order:1,\n \t\t\ttag_objects:1,\n"}]}