{"thread":{"id":"8656","subject":"Finally implement \"git log --follow\"","startedAt":"2007-06-19T21:22:46Z","lastAt":"2007-07-04T13:21:39Z","messageCount":11,"participants":["Linus Torvalds","Marco Costalba","Junio C Hamano","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"45384","messageId":"alpine.LFD.0.98.0706191358180.3593@woody.linux-foundation.org","threadId":"8656","inReplyTo":null,"subject":"Finally implement \"git log --follow\"","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-19T21:22:46Z","receivedAt":"2007-06-19T21:22:46Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nOk, I've really held off doing this too damn long, because I'm lazy, and I \nwas always hoping that somebody else would do it.\n\nBut no, people keep asking for it, but nobody actually did anything, so I \ndecided I might as well bite the bullet, and instead of telling people \nthey could add a \"--follow\" flag to \"git log\" to do what they want to do, \nI decided that it looks like I just have to do it for them..\n\nThe code wasn't actually that complicated, in that the diffstat for this \npatch literally says \"70 insertions(+), 1 deletions(-)\", but I will have \nto admit that in order to get to this fairly simple patch, you did have to \nknow and understand the internal git diff generation machinery pretty \nwell, and had to really be able to follow how commit generation interacts \nwith generating patches and generating the log.\n\nSo I suspect that while I was right that it wasn't that hard, I might have \nbeen expecting too much of random people - this patch does seem to be \nfirmly in the core \"Linus or Junio\" territory.\n\nTo make a long story short: I'm sorry for it taking so long until I just \ndid it.\n\nI'm not going to guarantee that this works for everybody, but you really \ncan just look at the patch, and after the appropriate appreciative noises \n(\"Ooh, aah\") over how clever I am, you can then just notice that the code \nitself isn't really that complicated.\n\nAll the real new code is in the new \"try_to_follow_renames()\" function. It \nreally isn't rocket science: we notice that the pathname we were looking \nat went away, so we start a full tree diff and try to see if we can \ninstead make that pathname be a rename or a copy from some other previous \npathname. And if we can, we just continue, except we show *that* \nparticular diff, and ever after we use the _previous_ pathname.\n\nOne thing to look out for: the \"rename detection\" is considered to be a \nsingular event in the _linear_ \"git log\" output! That's what people want \nto do, but I just wanted to point out that this patch is *not* carrying \naround a \"commit,pathname\" kind of pair and it's *not* going to be able to \nnotice the file coming from multiple *different* files in earlier history.\n\nIOW, if you use \"git log --follow\", then you get the stupid CVS/SVN kind \nof \"files have single identities\" kind of semantics, and git log will just \npick the identity based on the normal move/copy heuristics _as_if_ the \nhistory could be linearized.\n\nPut another way: I think the model is broken, but given the broken model, \nI think this patch does just about as well as you can do. If you have \nmerges with the same \"file\" having different filenames over the two \nbranches, git will just end up picking _one_ of the pathnames at the point \nwhere the newer one goes away. It never looks at multiple pathnames in \nparallel.\n\nAnd if you understood all that, you probably didn't need it explained, and \nif you didn't understand the above blathering, it doesn't really mtter to \nyou. What matters to you is that you can now do\n\n\tgit log -p --follow builtin-rev-list.c\n\nand it will find the point where the old \"rev-list.c\" got renamed to \n\"builtin-rev-list.c\" and show it as such.\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n----\n\nNOTE! For obvious enough reasons, I limited the rename following to just \n*one* pathname. If somebody wants to extend it to any more, be my guest.\n\nAlso, I really might have some silly bug somewhere.\n\n\"It Works For Me(tm)\", and I tested it with both the git archive and the \nkernel (block/ll_rw_block.c) and it worked beautifully, but I'll also \nadmit that the patch is a bit _too_ clever for my taste normally. The \npatch actually looks more straightforward than it really is: that \"hook \ndirectly into diff_tree_sha1()\" thing is just too damn clever for words.\n\nPeople who want to improve on it should get rid of the memory leak I \nintroduced - I decided to not bother cleaning up the whole rename diff \nqueue, I just reset it. I'm lazy, and I'm a *man*. I do the rough manly \nstuff, others can clean up after me.\n\n*Burp*. That hit the spot. *Scratch*\n\n\t\tLinus\n\n---\n builtin-log.c |    5 ++++\n diff.c        |    2 +\n diff.h        |    1 +\n revision.c    |    4 ++-\n tree-diff.c   |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 70 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 0aede76..a26a010 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -58,6 +58,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,\n \targc = setup_revisions(argc, argv, rev, \"HEAD\");\n \tif (rev->diffopt.pickaxe || rev->diffopt.filter)\n \t\trev->always_show_header = 0;\n+\tif (rev->diffopt.follow_renames) {\n+\t\trev->always_show_header = 0;\n+\t\tif (rev->diffopt.nr_paths != 1)\n+\t\t\tusage(\"git logs can only follow renames on one pathname at a time\");\n+\t}\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \t\tif (!strcmp(arg, \"--decorate\")) {\ndiff --git a/diff.c b/diff.c\nindex 4aa9bbc..9938969 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2210,6 +2210,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)\n \t}\n \telse if (!strcmp(arg, \"--find-copies-harder\"))\n \t\toptions->find_copies_harder = 1;\n+\telse if (!strcmp(arg, \"--follow\"))\n+\t\toptions->follow_renames = 1;\n \telse if (!strcmp(arg, \"--abbrev\"))\n \t\toptions->abbrev = DEFAULT_ABBREV;\n \telse if (!prefixcmp(arg, \"--abbrev=\")) {\ndiff --git a/diff.h b/diff.h\nindex a7ee6d8..9fd6d44 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -55,6 +55,7 @@ struct diff_options {\n \t\t full_index:1,\n \t\t silent_on_remove:1,\n \t\t find_copies_harder:1,\n+\t\t follow_renames:1,\n \t\t color_diff:1,\n \t\t color_diff_words:1,\n \t\t has_changes:1,\ndiff --git a/revision.c b/revision.c\nindex 1f4590b..7834bb1 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1230,7 +1230,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \n \tif (revs->prune_data) {\n \t\tdiff_tree_setup_paths(revs->prune_data, &revs->pruning);\n-\t\trevs->prune_fn = try_to_simplify_commit;\n+\t\t/* Can't prune commits with rename following: the paths change.. */\n+\t\tif (!revs->diffopt.follow_renames)\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}\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 852498e..42924e9 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -3,6 +3,7 @@\n  */\n #include \"cache.h\"\n #include \"diff.h\"\n+#include \"diffcore.h\"\n #include \"tree.h\"\n \n static char *malloc_base(const char *base, int baselen, const char *path, int pathlen)\n@@ -290,6 +291,59 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru\n \treturn 0;\n }\n \n+/*\n+ * Does it look like the resulting diff might be due to a rename?\n+ *  - single entry\n+ *  - not a valid previous file\n+ */\n+static inline int diff_might_be_rename(void)\n+{\n+\treturn diff_queued_diff.nr == 1 &&\n+\t\t!DIFF_FILE_VALID(diff_queued_diff.queue[0]->one);\n+}\n+\n+static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)\n+{\n+\tstruct diff_options diff_opts;\n+\tconst char *paths[2];\n+\tint i;\n+\n+\tdiff_setup(&diff_opts);\n+\tdiff_opts.recursive = 1;\n+\tdiff_opts.detect_rename = DIFF_DETECT_RENAME;\n+\tdiff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;\n+\tdiff_opts.single_follow = opt->paths[0];\n+\tpaths[0] = NULL;\n+\tdiff_tree_setup_paths(paths, &diff_opts);\n+\tif (diff_setup_done(&diff_opts) < 0)\n+\t\tdie(\"unable to set up diff options to follow renames\");\n+\tdiff_tree(t1, t2, base, &diff_opts);\n+\tdiffcore_std(&diff_opts);\n+\n+\t/* NOTE! Ignore the first diff! That was the old one! */\n+\tfor (i = 1; i < diff_queued_diff.nr; i++) {\n+\t\tstruct diff_filepair *p = diff_queued_diff.queue[i];\n+\n+\t\t/*\n+\t\t * Found a source? Not only do we use that for the new\n+\t\t * diff_queued_diff, we also use that as the path in\n+\t\t * the future!\n+\t\t */\n+\t\tif ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, opt->paths[0])) {\n+\t\t\tdiff_queued_diff.queue[0] = p;\n+\t\t\topt->paths[0] = xstrdup(p->one->path);\n+\t\t\tdiff_tree_setup_paths(opt->paths, opt);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Then, ignore any but the first entry! It might be the old one,\n+\t * or it might be the rename/copy we found\n+\t */\n+\tdiff_queued_diff.nr = 1;\n+}\n+\n int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt)\n {\n \tvoid *tree1, *tree2;\n@@ -306,6 +360,11 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha\n \tinit_tree_desc(&t1, tree1, size1);\n \tinit_tree_desc(&t2, tree2, size2);\n \tretval = diff_tree(&t1, &t2, base, opt);\n+\tif (opt->follow_renames && diff_might_be_rename()) {\n+\t\tinit_tree_desc(&t1, tree1, size1);\n+\t\tinit_tree_desc(&t2, tree2, size2);\n+\t\ttry_to_follow_renames(&t1, &t2, base, opt);\n+\t}\n \tfree(tree1);\n \tfree(tree2);\n \treturn retval;\n"},{"id":"45385","messageId":"alpine.LFD.0.98.0706191425240.3593@woody.linux-foundation.org","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706191358180.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-19T21:35:30Z","receivedAt":"2007-06-19T21:35:30Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 19 Jun 2007, Linus Torvalds wrote:\n> \n> People who want to improve on it should get rid of the memory leak I \n> introduced - I decided to not bother cleaning up the whole rename diff \n> queue, I just reset it. I'm lazy, and I'm a *man*. I do the rough manly \n> stuff, others can clean up after me.\n> \n> *Burp*. That hit the spot. *Scratch*\n\nOn that note, if people want to decide that \"git log\" should *default* to \nfollow when one filename is given, that's ok by me. A few warnings:\n\n - You should only do it for the \"single file\" case, and that's very\n   *different* from the \"single pattern\" case. I often do \"git log\" on a \n   single directory, and that had better not start doing any \"filename \n   following\" by default.\n\n   So before turning on \"follow\" automatically, it should be checked that \n   that exact file exists right now (might be as simplistic as just doing \n   a \"lstat()\" and verifying that it's a file or symlink in the current \n   working tree)\n\n - the commit simplification isn't done. So you cannot do \"--follow\" \n   together with somethign that wants a contiguous history (like gitk) and \n   uses \"--parents\".\n\n   This is pretty fundamental. The commit simplification is a separate \n   phase over the (non-linear!) commit space, and the \"git log --follow\" \n   logic is really a *different* logic over the _linear_ space (namely the \n   streaming \"log output\" space). \n\n   Two totally different things, in other words. And not compatible.\n\nSo if we want to turn on \"follow\" by default, then I'm certainly ok with \nit, but it needs to be done with care. so I'd almost suggest just adding \nan alias instead, aka\n\n\tgit config alias.follow 'log --follow'\n\nand then doing\n\n\tgit follow filename\n\nrather than changing the behaviour of \"git log\" itself.\n\n\t\t\tLinus\n"},{"id":"45410","messageId":"e5bfff550706192327l187b30eblb5bd5e4e76b3eab6@mail.gmail.com","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706191358180.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2007-06-20T06:27:49Z","receivedAt":"2007-06-20T06:27:49Z","isPatch":false,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":"On 6/19/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:\n>\n> Ok, I've really held off doing this too damn long, because I'm lazy, and I\n> was always hoping that somebody else would do it.\n>\n> But no, people keep asking for it, but nobody actually did anything, so I\n> decided I might as well bite the bullet, and instead of telling people\n> they could add a \"--follow\" flag to \"git log\" to do what they want to do,\n> I decided that it looks like I just have to do it for them..\n>\n\nThanks,\n\n  now I have one more reason to switch from using git-rev-list to\ngit-log in qgit, file history annotation, that is currently based on\ngit-rev-list, will automatically gain a powerful feature.\n\nMarco\n\nP.S: The only thing that is still missing in git-log against\ngit-rev-list is a --stdin option. This is needed because with 40 chars\nSHA the command line could became very long in case of repos with many\ntags/branches or when loading StGIT unapplied patches (one sha per\npatch) and one git-rev-list call to loading them all.\n\nWithout --stdin we break easily on _some_ OS and in the worst cases (a\nlot of unapplied patches) *even* under Linux.\n"},{"id":"45432","messageId":"alpine.LFD.0.98.0706200940000.3593@woody.linux-foundation.org","threadId":"8656","inReplyTo":"e5bfff550706192327l187b30eblb5bd5e4e76b3eab6@mail.gmail.com","subject":"Re: Finally implement \"git log --follow\"","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-20T16:47:28Z","receivedAt":"2007-06-20T16:47:28Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 20 Jun 2007, Marco Costalba wrote:\n> \n>  now I have one more reason to switch from using git-rev-list to\n> git-log in qgit, file history annotation, that is currently based on\n> git-rev-list, will automatically gain a powerful feature.\n\nWell, note my other email about how \"--follow\" does *not* play together \nwith \"--parents\", because the two do totally different kinds of filtering \nof the commits. So yes, you can use it for file history annotation, but \nnot for the \"graphical history\" part that depends on parenthood etc.\n\nThat said, you really would be better off using\n\n\tgit blame -M --incremental\n\nfor the history annotation. It does the rename following *and* so much \nmore.\n\n\t\tLinus\n"},{"id":"45452","messageId":"alpine.LFD.0.98.0706201811440.3593@woody.linux-foundation.org","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706191358180.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-21T01:15:11Z","receivedAt":"2007-06-21T01:15:11Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nJunio, I note that you merged this into 'next', and also:\n\nOn Tue, 19 Jun 2007, Linus Torvalds wrote:\n>\n> [ long and boring explanation ]\n> \n> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n> ----\n\nNote the *four* dashes instead of three, so:\n\n> NOTE! For obvious enough reasons, I limited the rename following to just \n> *one* pathname. If somebody wants to extend it to any more, be my guest.\n> \n> Also, I really might have some silly bug somewhere.\n> \n> \"It Works For Me(tm)\", and I tested it with both the git archive and the \n> kernel (block/ll_rw_block.c) and it worked beautifully, but I'll also \n> admit that the patch is a bit _too_ clever for my taste normally. The \n> patch actually looks more straightforward than it really is: that \"hook \n> directly into diff_tree_sha1()\" thing is just too damn clever for words.\n> \n> People who want to improve on it should get rid of the memory leak I \n> introduced - I decided to not bother cleaning up the whole rename diff \n> queue, I just reset it. I'm lazy, and I'm a *man*. I do the rough manly \n> stuff, others can clean up after me.\n> \n> *Burp*. That hit the spot. *Scratch*\n\nThis also hit the git archives. \n\nMy burping and scratching wasn't really *meant* to be part of the official \nrecord, but hey, there you have it.\n\nNo problem, and maybe you noticed and thought it amusing, but in case it \nwent unnoticed, you may want to clean that up when/if moving it to \n\"master\".\n\nOr not. Your choice.\n\n\t\tLinus\n"},{"id":"45453","messageId":"7v4pl25bpk.fsf@assigned-by-dhcp.pobox.com","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706201811440.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-06-21T01:37:59Z","receivedAt":"2007-06-21T01:37:59Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> My burping and scratching wasn't really *meant* to be part of the official \n> record, but hey, there you have it.\n\nWell, burping and scratching is already part of the public\nrecord ;-)  gmane hopefully remembers it forever.\n\nBut you are right.  I should re-do that one when moving it to master.\n"},{"id":"45471","messageId":"e5bfff550706202321t354ec0e3xb218f382f1c983ae@mail.gmail.com","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706200940000.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2007-06-21T06:21:30Z","receivedAt":"2007-06-21T06:21:30Z","isPatch":false,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":"On 6/20/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:\n\n>\n> That said, you really would be better off using\n>\n>         git blame -M --incremental\n>\n\nThat's how it is currently inplemented in qgit:\n\n- Main view revision list + graph: git-rev-list\n- File history and annotation: git-rev-list\n\nThe possible options are:\n\nALL GIT LOG\n-------------------\n\n- Main view revision list + graph: git-log\n- File history and annotation: git-log\n\nGood: easy implementation and a lot of common code to share among\nmodules, all the current features (see \"range fltering\" below) are\npreserved\n\nBad: Currently git-log does not support --stdin option, required IMHO\nwhen git-log is runned by a tool, not a user, due to the possibility\nof a very long command line.\n\nMIXED\n---------\n\n- Main view revision list + graph: git-rev-list\n- File history and annotation: git-blame\n\nGood: Gain additional features of git-blame against git-log\n\nBad: FWIK \"git blame -M --incremental\" does not support annotating all\nthe files in history in one go, as it is possible both with\ngit-rev-list and git-log. You have to re-annotate the new file when\nbrowsing file history with the mouse.\n\nImpementation cannot reuse big chunks of code, so a lot of new code is\nneeded and probably old one will not disappear.\n\nFWIK \"git blame -M --incremental\" does not support \"code lines range\nfiltering\", when with the mouse you select some lines of code and\nafter filtering you see the subset of file's history that modified\nthat range of code. This feature is currently supported by qgit\nannotating code.\n\nAlso jump to the same currently selected code line when switching to a\ndifferent version in file history it is currently supported by\nannotate code.\n\n\nINTERESTING\n--------------------\n\n- Main view revision list + graph: git-log\n- File history and annotation: git-blame\n\nA curious mix.\n\n\n\nSome advice?\n\n\nThanks\nMarco\n"},{"id":"45507","messageId":"alpine.LFD.0.98.0706210842340.3593@woody.linux-foundation.org","threadId":"8656","inReplyTo":"e5bfff550706202321t354ec0e3xb218f382f1c983ae@mail.gmail.com","subject":"Re: Finally implement \"git log --follow\"","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-21T15:44:17Z","receivedAt":"2007-06-21T15:44:17Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 21 Jun 2007, Marco Costalba wrote:\n> \n> Bad: Currently git-log does not support --stdin option, required IMHO\n> when git-log is runned by a tool, not a user, due to the possibility\n> of a very long command line.\n\nI do think we should just fix this. The patch to do so can't be *that* \nbad.\n\nI'll look at it.\n\n> FWIK \"git blame -M --incremental\" does not support \"code lines range\n> filtering\", when with the mouse you select some lines of code and\n> after filtering you see the subset of file's history that modified\n> that range of code. This feature is currently supported by qgit\n> annotating code.\n\nYeah, that sounds like it would be a good thing to fix.\n\n\t\tLinus\n"},{"id":"45509","messageId":"Pine.LNX.4.64.0706211654100.4059@racer.site","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706210842340.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-06-21T15:55:05Z","receivedAt":"2007-06-21T15:55:05Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 21 Jun 2007, Linus Torvalds wrote:\n\n> On Thu, 21 Jun 2007, Marco Costalba wrote:\n> > \n> > Bad: Currently git-log does not support --stdin option, required IMHO\n> > when git-log is runned by a tool, not a user, due to the possibility\n> > of a very long command line.\n> \n> I do think we should just fix this. The patch to do so can't be *that* \n> bad.\n\nThe only quirk here is that \"--stdin\" makes no sense with a pager. \nTherefore, you'd have to move the automatic pager invocation to _after_ \noption parsing.\n\nCiao,\nDscho\n"},{"id":"45511","messageId":"alpine.LFD.0.98.0706210907190.3593@woody.linux-foundation.org","threadId":"8656","inReplyTo":"Pine.LNX.4.64.0706211654100.4059@racer.site","subject":"Re: Finally implement \"git log --follow\"","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-21T16:09:32Z","receivedAt":"2007-06-21T16:09:32Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 21 Jun 2007, Johannes Schindelin wrote:\n> \n> The only quirk here is that \"--stdin\" makes no sense with a pager. \n> Therefore, you'd have to move the automatic pager invocation to _after_ \n> option parsing.\n\nI don't know.. The pager invocation already checks whether the output is a \ntty. Quite frankly, I think that is sufficient for all cases we're \ndiscussing right now (ie anybody who uses \"--stdin\" would *also* redirect \nthe output!), and we could certainly make it check that both the input \n*and* the output is a tty.\n\n\t\t\tLinus\n"},{"id":"46480","messageId":"e5bfff550707040621o1339de98o62f10fdfe4ff0650@mail.gmail.com","threadId":"8656","inReplyTo":"alpine.LFD.0.98.0706191425240.3593@woody.linux-foundation.org","subject":"Re: Finally implement \"git log --follow\"","fromName":"Marco Costalba","fromEmail":"mcostalba@gmail.com","sentAt":"2007-07-04T13:21:39Z","receivedAt":"2007-07-04T13:21:39Z","isPatch":false,"sender":{"key":"mcostalba@gmail.com","avatar":null},"body":"On 6/19/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:\n>\n>  - the commit simplification isn't done. So you cannot do \"--follow\"\n>    together with somethign that wants a contiguous history (like gitk) and\n>    uses \"--parents\".\n>\n>    This is pretty fundamental. The commit simplification is a separate\n>    phase over the (non-linear!) commit space, and the \"git log --follow\"\n>    logic is really a *different* logic over the _linear_ space (namely the\n>    streaming \"log output\" space).\n>\n>    Two totally different things, in other words. And not compatible.\n>\n\nOf course I need exactly that!\n\nReally don't want to thrash away the nice qgit graph, also in file\nhistories, and at the same time I really like that '--follow' feature,\nso....\n\nI've just started to hit the wall against the scary revision.c and\nfriends, my goal is to find a solution (trick/hack) to get the renames\nalso with --parents.\n\nFirst of all I have commented out:\n\n\t\t/* Can't prune commits with rename following: the paths change.. */\n// \t\tif (!revs->diffopt.follow_renames)\n\t\t\trevs->prune_fn = try_to_simplify_commit;\n\nSo I've see that with --parents set try_to_simplify_commit() does his\njob and when the processing arrives in diff_tree_sha1() it is already\npruned, so also if the check\n\nif (opt->follow_renames && diff_might_be_rename())\n\nis true and the following try_to_follow_renames() is called, no\nalternative tree is found.\n\nMy idea, after have understood a little bit better how it works, is to\n'resurrect' the pruned info  before calling try_to_follow_renames().\nTo do this I was thinking of saving a pointer to some pruned tree\ninformation in try_to_simplify_commit() and in case use that pointer\nafter in diff_tree_sha1() when needed.\n\nNightmares??? Perhaps, I'm just starting with this difficult piece of\ncode and probably (90%) I will give up before the end and very\nprobably (99%) all said before is just brain dead, but...anyway I have\nto start from somewhere.\n\nMarco\n"}]}