{"thread":{"id":"9520","subject":"bisect / history preserving on rename + update","startedAt":"2007-08-14T08:38:01Z","lastAt":"2007-08-25T17:23:05Z","messageCount":15,"participants":["Thomas Gleixner","Karl Hasselström","David Kastrup","Linus Torvalds","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"50685","messageId":"1187080681.12828.174.camel@chaos","threadId":"9520","inReplyTo":null,"subject":"bisect / history preserving on rename + update","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2007-08-14T08:38:01Z","receivedAt":"2007-08-14T08:38:01Z","isPatch":false,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"Hi,\n\nis there a built in way to handle the following situation:\n\nfile A is renamed to B\nfile A is created again and new content is added.\n\nI found only two ways to do that, which both suck:\n\n1)\n\tgit-mv A B\n\tgit-add A\n\tgit commit\n\n\tresults in a copy A to B and lost history of B\n\n2)\n\tgit-mv A B\n\tgit commit\n\tgit-add A\n\tgit commit\n\n\tpreserves the history of B, but breaks bisection because\n\tA is needed to compile\n\nI have no real good idea how to solve this. After staring at the git\nsource for a while, I think that 1) is quite hard to solve. A sane\nsolution for 2) might be to add a flag to the second commit, which\nbundles the two commits for bisection.\n\nAny other solutions ?\n\n\ttglx\n"},{"id":"50692","messageId":"20070814093357.GA14010@diana.vm.bytemark.co.uk","threadId":"9520","inReplyTo":"1187080681.12828.174.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-08-14T09:33:57Z","receivedAt":"2007-08-14T09:33:57Z","isPatch":false,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2007-08-14 10:38:01 +0200, Thomas Gleixner wrote:\n\n> is there a built in way to handle the following situation:\n>\n> file A is renamed to B\n> file A is created again and new content is added.\n>\n> I found only two ways to do that, which both suck:\n>\n> 1)\n>       git-mv A B\n>       git-add A\n>       git commit\n>\n>       results in a copy A to B and lost history of B\n\nWhat exactly do you mean by \"lost history of B\"? You do know that git\ndoesn't record renames? So you could just as well do\n\n  $ mv A B\n  $ create a new A\n  $ git add A B\n  $ git commit\n\n> 2)\n>       git-mv A B\n>       git commit\n>       git-add A\n>       git commit\n>\n>       preserves the history of B, but breaks bisection because A is\n>       needed to compile\n\nYes. I wouldn't recommend this option for that reason.\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"50693","messageId":"86d4xqh1r5.fsf@lola.quinscape.zz","threadId":"9520","inReplyTo":"1187080681.12828.174.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2007-08-14T10:03:10Z","receivedAt":"2007-08-14T10:03:10Z","isPatch":false,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Thomas Gleixner <tglx@linutronix.de> writes:\n\n> is there a built in way to handle the following situation:\n>\n> file A is renamed to B\n> file A is created again and new content is added.\n>\n> I found only two ways to do that, which both suck:\n>\n> 1)\n> \tgit-mv A B\n> \tgit-add A\n> \tgit commit\n>\n> \tresults in a copy A to B and lost history of B\n>\n> 2)\n> \tgit-mv A B\n> \tgit commit\n> \tgit-add A\n> \tgit commit\n>\n> \tpreserves the history of B, but breaks bisection because\n> \tA is needed to compile\n>\n> I have no real good idea how to solve this. After staring at the git\n> source for a while, I think that 1) is quite hard to solve. A sane\n> solution for 2) might be to add a flag to the second commit, which\n> bundles the two commits for bisection.\n>\n> Any other solutions ?\n\nYou are confused, probably because something like \"git-mv\" exists (it\nis just syntactic sugar, and it might be less confusing to users to\nactually remove it).  git does _not_ track file histories.  Not the\ntiniest bit.\n\nIt _constructs_ them when you ask it nicely.  All commands that\ndisplay \"tracking\" information have options like -M -C -R and so on\nthat tell git just how much effort it should spend on keeping abreast\nof copying/renaming/modification.\n\n-- \nDavid Kastrup\n"},{"id":"50694","messageId":"1187086600.12828.177.camel@chaos","threadId":"9520","inReplyTo":"20070814093357.GA14010@diana.vm.bytemark.co.uk","subject":"Re: bisect / history preserving on rename + update","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2007-08-14T10:16:40Z","receivedAt":"2007-08-14T10:16:40Z","isPatch":false,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Tue, 2007-08-14 at 11:33 +0200, Karl Hasselström wrote:\n> On 2007-08-14 10:38:01 +0200, Thomas Gleixner wrote:\n> \n> > is there a built in way to handle the following situation:\n> >\n> > file A is renamed to B\n> > file A is created again and new content is added.\n> >\n> > I found only two ways to do that, which both suck:\n> >\n> > 1)\n> >       git-mv A B\n> >       git-add A\n> >       git commit\n> >\n> >       results in a copy A to B and lost history of B\n> \n> What exactly do you mean by \"lost history of B\"? You do know that git\n> doesn't record renames? So you could just as well do\n\nErr.\n\ngit-mv A B\ngit commit\nedit B\ngit commit\ngit blame B <- shows the full history of A & B\n\nIMHO that's why we have git-mv\n\n\ttglx\n"},{"id":"50695","messageId":"20070814105056.GA14536@diana.vm.bytemark.co.uk","threadId":"9520","inReplyTo":"1187086600.12828.177.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-08-14T10:50:56Z","receivedAt":"2007-08-14T10:50:56Z","isPatch":false,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2007-08-14 12:16:40 +0200, Thomas Gleixner wrote:\n\n> On Tue, 2007-08-14 at 11:33 +0200, Karl Hasselström wrote:\n>\n> > What exactly do you mean by \"lost history of B\"? You do know that\n> > git doesn't record renames? So you could just as well do\n>\n> Err.\n>\n> git-mv A B\n> git commit\n> edit B\n> git commit\n> git blame B <- shows the full history of A & B\n>\n> IMHO that's why we have git-mv\n\nTry replacing\n\n  $ git-mv A B\n\nwith\n\n  $ mv A B\n  $ git rm A\n  $ git add B\n\nThe result is exactly the same. git-mv is just a convenience.\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"50696","messageId":"1187089619.12828.183.camel@chaos","threadId":"9520","inReplyTo":"20070814105056.GA14536@diana.vm.bytemark.co.uk","subject":"Re: bisect / history preserving on rename + update","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2007-08-14T11:06:59Z","receivedAt":"2007-08-14T11:06:59Z","isPatch":false,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Tue, 2007-08-14 at 12:50 +0200, Karl Hasselström wrote:\n> > Err.\n> >\n> > git-mv A B\n> > git commit\n> > edit B\n> > git commit\n> > git blame B <- shows the full history of A & B\n> >\n> > IMHO that's why we have git-mv\n> \n> Try replacing\n> \n>   $ git-mv A B\n> \n> with\n> \n>   $ mv A B\n>   $ git rm A\n>   $ git add B\n> \n> The result is exactly the same. git-mv is just a convenience.\n\nFair enough, but it still does not solve my initial problem of keeping\nthe history of B (former A) intact, while creating a new A which is\nnecessary to compile the tree, simply because I can not change #include\n<A> to #include <B> for various reasons.\n\n\ttglx\n"},{"id":"50697","messageId":"86wsvyfjyg.fsf@lola.quinscape.zz","threadId":"9520","inReplyTo":"1187089619.12828.183.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2007-08-14T11:12:55Z","receivedAt":"2007-08-14T11:12:55Z","isPatch":false,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Thomas Gleixner <tglx@linutronix.de> writes:\n\n> On Tue, 2007-08-14 at 12:50 +0200, Karl Hasselström wrote:\n>> > Err.\n>> >\n>> > git-mv A B\n>> > git commit\n>> > edit B\n>> > git commit\n>> > git blame B <- shows the full history of A & B\n>> >\n>> > IMHO that's why we have git-mv\n>> \n>> Try replacing\n>> \n>>   $ git-mv A B\n>> \n>> with\n>> \n>>   $ mv A B\n>>   $ git rm A\n>>   $ git add B\n>> \n>> The result is exactly the same. git-mv is just a convenience.\n>\n> Fair enough, but it still does not solve my initial problem of keeping\n> the history of B (former A) intact, while creating a new A which is\n> necessary to compile the tree, simply because I can not change #include\n> <A> to #include <B> for various reasons.\n\nSigh.  Please use the right options for calling your history viewing\ncommands.  It is not like I haven't told you that already.  For\nexample, take git-blame.  Its manual page clearly states:\n\n\t-M|<num>|\n\t   Detect moving lines in the file as well. When a commit\n\t   moves a block of lines in a file (e.g. the original file\n\t   has A and then B, and the commit changes it to B and then\n\t   A), traditional blame algorithm typically blames the\n\t   lines that were moved up (i.e. B) to the parent and\n\t   assigns blame to the lines that were moved down (i.e. A)\n\t   to the child commit. With this option, both groups of\n\t   lines are blamed on the parent.\n\n\t   <num> is optional but it is the lower bound on the number\n\t   of alphanumeric characters that git must detect as moving\n\t   within a file for it to associate those lines with the\n\t   parent commit.\n\n\t-C|<num>|\n\t   In addition to -M, detect lines copied from other files\n\t   that were modified in the same commit. This is useful\n\t   when you reorganize your program and move code around\n\t   across files. When this option is given twice, the\n\t   command looks for copies from all other files in the\n\t   parent for the commit that creates the file in addition.\n\n\t   <num> is optional but it is the lower bound on the number\n\t   of alphanumeric characters that git must detect as moving\n\t   between files for it to associate those lines with the\n\t   parent commit.\n\n\n-- \nDavid Kastrup\n"},{"id":"50698","messageId":"20070814111828.GA15399@diana.vm.bytemark.co.uk","threadId":"9520","inReplyTo":"1187089619.12828.183.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-08-14T11:18:28Z","receivedAt":"2007-08-14T11:18:28Z","isPatch":false,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2007-08-14 13:06:59 +0200, Thomas Gleixner wrote:\n\n> On Tue, 2007-08-14 at 12:50 +0200, Karl Hasselström wrote:\n>\n> > The result is exactly the same. git-mv is just a convenience.\n>\n> Fair enough, but it still does not solve my initial problem of\n> keeping the history of B (former A) intact, while creating a new A\n> which is necessary to compile the tree, simply because I can not\n> change #include <A> to #include <B> for various reasons.\n\nHave you tried running blame with -C, or -C -C? That will make it try\nharder to identify lines originating from other files.\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"50705","messageId":"1187101183.12828.191.camel@chaos","threadId":"9520","inReplyTo":"20070814111828.GA15399@diana.vm.bytemark.co.uk","subject":"Re: bisect / history preserving on rename + update","fromName":"Thomas Gleixner","fromEmail":"tglx@linutronix.de","sentAt":"2007-08-14T14:19:43Z","receivedAt":"2007-08-14T14:19:43Z","isPatch":false,"sender":{"key":"tglx@linutronix.de","avatar":null},"body":"On Tue, 2007-08-14 at 13:18 +0200, Karl Hasselström wrote:\n> On 2007-08-14 13:06:59 +0200, Thomas Gleixner wrote:\n> \n> > On Tue, 2007-08-14 at 12:50 +0200, Karl Hasselström wrote:\n> >\n> > > The result is exactly the same. git-mv is just a convenience.\n> >\n> > Fair enough, but it still does not solve my initial problem of\n> > keeping the history of B (former A) intact, while creating a new A\n> > which is necessary to compile the tree, simply because I can not\n> > change #include <A> to #include <B> for various reasons.\n> \n> Have you tried running blame with -C, or -C -C? That will make it try\n> harder to identify lines originating from other files.\n\nDoes not help. Strange enough it results in\n\n# git blame include/B\n\nb4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  1) #ifndef _A_H_\nb4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  2) #define _A_H_\nb4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  3) \nb4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  4) #define TEST_1 1\nf098c4ad include/B (Thomas Gleixner 2007-08-14 16:01:05 +0200  5) #define TEST_2 2\nf098c4ad include/B (Thomas Gleixner 2007-08-14 16:01:05 +0200  6) \nf098c4ad include/B (Thomas Gleixner 2007-08-14 16:01:05 +0200  7) #endif\n\n\ttglx\n"},{"id":"50707","messageId":"86lkcefa3c.fsf@lola.quinscape.zz","threadId":"9520","inReplyTo":"1187101183.12828.191.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2007-08-14T14:45:59Z","receivedAt":"2007-08-14T14:45:59Z","isPatch":false,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Thomas Gleixner <tglx@linutronix.de> writes:\n\n> On Tue, 2007-08-14 at 13:18 +0200, Karl Hasselström wrote:\n>> On 2007-08-14 13:06:59 +0200, Thomas Gleixner wrote:\n>> \n>> > On Tue, 2007-08-14 at 12:50 +0200, Karl Hasselström wrote:\n>> >\n>> > > The result is exactly the same. git-mv is just a convenience.\n>> >\n>> > Fair enough, but it still does not solve my initial problem of\n>> > keeping the history of B (former A) intact, while creating a new A\n>> > which is necessary to compile the tree, simply because I can not\n>> > change #include <A> to #include <B> for various reasons.\n>> \n>> Have you tried running blame with -C, or -C -C? That will make it try\n>> harder to identify lines originating from other files.\n>\n> Does not help. Strange enough it results in\n>\n> # git blame include/B\n>\n> b4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  1) #ifndef _A_H_\n> b4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  2) #define _A_H_\n> b4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  3) \n> b4062b16 include/A (Joe Hacker      2007-08-14 10:52:28 +0200  4) #define TEST_1 1\n> f098c4ad include/B (Thomas Gleixner 2007-08-14 16:01:05 +0200  5) #define TEST_2 2\n> f098c4ad include/B (Thomas Gleixner 2007-08-14 16:01:05 +0200  6) \n> f098c4ad include/B (Thomas Gleixner 2007-08-14 16:01:05 +0200  7) #endif\n\nSo it tells you commit and corresponding file that are responsible for\nthe lines in question.\n\nHow does this not help?\n\n-- \nDavid Kastrup\n"},{"id":"50710","messageId":"alpine.LFD.0.999.0708140853500.30176@woody.linux-foundation.org","threadId":"9520","inReplyTo":"1187080681.12828.174.camel@chaos","subject":"Re: bisect / history preserving on rename + update","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-08-14T16:14:30Z","receivedAt":"2007-08-14T16:14:30Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 14 Aug 2007, Thomas Gleixner wrote:\n>\n> is there a built in way to handle the following situation:\n> \n> file A is renamed to B\n> file A is created again and new content is added.\n\nThat \"should just work\".\n\n[ However, there does seem to be a bug in the \"-B\" logic, so it doesn't \n  actually work as well as it should! See below ]\n\nBUT! By default, rename detection isn't on at all, mostly because it \nresults in patches that non-git \"patch\" cannot apply, but partly also \nbecause it can slow certain things down.\n\nSo to get nice diffs, use\n\n\tgit show -B -C\n\nwhere the magic is:\n\n - \"-B\" means \"break file associations when a file is *too* dissimilar\" \n\n   Normally, git will assume that if a filename stays around, it's the \n   same file. However, with \"-B\", it does similarity analysis even for \n   files that are the same, and if they are very different, git will \n   decide that maybe they weren't the same file after all!\n\n - \"-C\" is \"find code movement and copying\".\n\nHowever, nobody ever actually uses \"-B\" (it's so rare as to effectively \nnot exist, and it does slow things down a bit), so it seems to have \nbit-rotted (or maybe it had this bug even originally: as I said, I don't \nthink anybody has ever really _used_ this functionality).\n\nJunio, look at this:\n\n\t# create a repo in \"testing\"\n\tcd\n\tmkdir testing\n\tcd testing/\n\tgit init\n\n\t# copy a file from the git repo\n\tcp ~/git/revision.c .\n\tgit add revision.c\n\tgit commit -a -m \"Add file 'A'\"\n\n\t# move it around, copy another file in its stead\n\tgit mv revision.c old-revision.c\n\tcp ~/git/Makefile revision.c\n\tgit add revision.c\n\tgit commit -a -m \"Move file 'A' to 'B', create new 'A'\"\n\tgit show -B -C\n\nand notice how \"-B\" *did* actually work, and we get a nice:\n\n\tdiff --git a/revision.c b/old-revision.c\n\tsimilarity index 100%\n\trename from revision.c\n\trename to old-revision.c\n\nbut then it breaks: instead of creating the new \"revision.c\", we get:\n\n\tdiff --git a/revision.c b/revision.c\n\tdissimilarity index 98%\n\tindex 038693c..4eb4637 100644\n\t--- a/revision.c\n\t+++ b/revision.c\n\t@@ -1,1572 +1,1117 @@\n\t-#include \"cache.h\"\n\t...\n\nwhich uses \"reivision.c\" as the base, even though it was already broken \nup! I think it *should* have looked like\n\n\tdiff --git a/old-revision.c b/old-revision.c\n\tnew file mode 100644\n\tindex 0000000..4eb4637\n\t--- /dev/null\n\t+++ b/revision.c\n\t+# The default target of this Makefile is...\n\t...\n\nso I think there is a bug there where the \"-B\" thing doesn't really \n\"stick\", and some part still uses the old file content even though it was \ndis-associated with the new content!\n\nHmm?\n\n\t\t\tLinus\n"},{"id":"51490","messageId":"7vmywgb45c.fsf@gitster.siamese.dyndns.org","threadId":"9520","inReplyTo":"alpine.LFD.0.999.0708140853500.30176@woody.linux-foundation.org","subject":"Re: bisect / history preserving on rename + update","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-25T04:59:43Z","receivedAt":"2007-08-25T04:59:43Z","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> [ However, there does seem to be a bug in the \"-B\" logic, so it doesn't \n>   actually work as well as it should! See below ]\n\nI finally had a bit of time to follow this through.  After\nrunning your set-up using revision.c and Makefile to emulate the\nsituation, you can try running:\n\n\t$ git diff-tree -B -C --numstat --summary HEAD\n\nor\n\n\t$ git diff-tree -B -M --numstat --summary HEAD\n\nwhich would say:\n\n        90028d007986de4db8c3af30a2d5e5c00e5a2c8b\n        0       0       revision.c => old-revision.c\n        1117    1579    revision.c\n         rename revision.c => old-revision.c (100%)\n         rewrite revision.c (98%)\n\nThe code is working as intended (it is a different discussion if\n\"as intended\" is actually the desired behaviour).\n\nWe take the preimage tree as a whole, and express postimage in\nterms of series of patches, _however_ we do not interpret the\nseries of patches as _incremental_.  IOW, when we talk about the\neffect of the second patch that describes the postimage of\nrevision.c, we pretend as if nothing happened with the first\npatch (which renamed away revision.c).  So \"rewrite revision.c\"\nis what we say, not \"create revision.c anew, because the first\none renamed it away\".\n\nThis behaviour actually was a bit counterintuitive to me.  I did\nnot implement the very original rename/copy the way we currently\noperate.  It was corrected into the current behaviour, following\nthe guiding principle described in this message:\n\n\thttp://thread.gmane.org/gmane.comp.version-control.git/3807\n\nwhich is reproduced below.\n\nFrom: Linus Torvalds <torvalds@osdl.org>\nDate: Mon, 23 May 2005 07:49:01 -0700 (PDT)\nSubject: Re: [PATCH] Make sure diff-helper can tell rename/copy in the new\n diff-raw format.\nMessage-ID: <Pine.LNX.4.58.0505230736180.2307@ppc970.osdl.org>\n\n    On Mon, 23 May 2005, Junio C Hamano wrote:\n    >\n    > This adds tests to make sure that diff-helper can tell renames\n    > from copies using the same \"everything but the last one are\n    > copies and the last one is either rename or stay\" logic.\n\n    Btw, I still disagree...\n    ...\n    For example, let's say that you have modified \"fileA\" _and_ you have \n    created a \"fileB\" that is a copy of the original \"fileA\" with some _other_ \n    slight modifications. We'll call the SHA1's involved \"sha_A\", \"sha_A'\" and \n    \"sha_B\"\n\n    I think it's perfectly valid to say\n\n            :100644 100644 <sha_A> <sha_A'> M\tfileA\tfileA\n            :100644 100644 <sha_A> <sha_B> C89\tfileA\tfileB\n\n    which says \"fileA\" was modified from orig-A to new-A, and \"fileB\" is a \n    copy based on orig-A.\n\n    Now, when the above is turned into a \"diff\", that diff is no longer\n    something you can apply \"incrementally\" - you have to apply it as if\n    you're applying all differences to the \"original tree\". But the thing is,\n    that's actually what I _want_, because I was planning on writing a tool\n    that applies patches that applies them all-or-nothing.\n\n    Also, it turns out that this kind of \"non-incremental\" diff is the kind\n    that I personally want to see as a _human_, because quite frankly, my\n    brain-capacity is that of a demented ocelot, and I can't _remember_ what\n    happened in other parts of the diff. I much prefer the stateless \"oh, this\n    file X is in that relation Y to the previous version of file Z\".\n\n    I do that partly because I actually routinely edit patches. If you have \n    the incremental format, that's practically impossible, while the stateless \n    version is fine.\n\n    See?\n\n    So I think all the clever \"don't re-use files we have modified\" etc is \n    actually wrong. If you want to make a traditional diff that can be applied \n    with normal \"patch\", you just don't use the -M or -C flags.\n\n                    Linus\n"},{"id":"51497","messageId":"85r6lsdq23.fsf@lola.goethe.zz","threadId":"9520","inReplyTo":"7vmywgb45c.fsf@gitster.siamese.dyndns.org","subject":"Re: bisect / history preserving on rename + update","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2007-08-25T07:35:48Z","receivedAt":"2007-08-25T07:35:48Z","isPatch":false,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Linus Torvalds <torvalds@linux-foundation.org> writes:\n>\n>> [ However, there does seem to be a bug in the \"-B\" logic, so it doesn't \n>>   actually work as well as it should! See below ]\n>\n> I finally had a bit of time to follow this through.  After\n> running your set-up using revision.c and Makefile to emulate the\n> situation, you can try running:\n>\n> \t$ git diff-tree -B -C --numstat --summary HEAD\n>\n> or\n>\n> \t$ git diff-tree -B -M --numstat --summary HEAD\n>\n> which would say:\n>\n>         90028d007986de4db8c3af30a2d5e5c00e5a2c8b\n>         0       0       revision.c => old-revision.c\n>         1117    1579    revision.c\n>          rename revision.c => old-revision.c (100%)\n>          rewrite revision.c (98%)\n>\n> The code is working as intended (it is a different discussion if\n> \"as intended\" is actually the desired behaviour).\n\n>From reading the argument of Linus, I would say that this \"stateless,\nnot applicable by patch\" behavior is desirable in some application.\nAnd the \"sequential, applicable by patch\" behavior also is desirable\nin a number of applications.\n\nSo there should be an option to select those behaviors.  This has the\nadded advantage that the manual page will explain that option, and so\nthe user gets to actively pick what he wants, and gets to _think_\nabout this choice.\n\nThis would be strictly better than \"at some point of time, we figured\nthat this particular way suited Linus' personal workflow best, so we\nobliterated all traces of other applications from code, documentation,\ndiscussion and thought\".\n\n> This behaviour actually was a bit counterintuitive to me.  I did\n> not implement the very original rename/copy the way we currently\n> operate.  It was corrected into the current behaviour, following\n> the guiding principle described in this message:\n>\n> \thttp://thread.gmane.org/gmane.comp.version-control.git/3807\n>\n> which is reproduced below.\n\nI think this is a case where restricting git's operation to a single\nway of doing it is limiting the range of its applications.  And having\n_neither_ an option _nor_ an explanation but rather pretending that\nthis is the only valid way one could want this feature to work is not\ngoing to help even those users who would, in the end, decide to choose\nthat behavior after all.\n\n-- \nDavid Kastrup, Kriemhildstr. 15, 44793 Bochum\n"},{"id":"51513","messageId":"alpine.LFD.0.999.0708250819360.25853@woody.linux-foundation.org","threadId":"9520","inReplyTo":"7vmywgb45c.fsf@gitster.siamese.dyndns.org","subject":"Re: bisect / history preserving on rename + update","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-08-25T15:38:32Z","receivedAt":"2007-08-25T15:38:32Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 24 Aug 2007, Junio C Hamano wrote:\n> \n> I finally had a bit of time to follow this through.  After\n> running your set-up using revision.c and Makefile to emulate the\n> situation, you can try running:\n> \n> \t$ git diff-tree -B -C --numstat --summary HEAD\n> \n> or\n> \n> \t$ git diff-tree -B -M --numstat --summary HEAD\n> \n> which would say:\n> \n>         90028d007986de4db8c3af30a2d5e5c00e5a2c8b\n>         0       0       revision.c => old-revision.c\n>         1117    1579    revision.c\n>          rename revision.c => old-revision.c (100%)\n>          rewrite revision.c (98%)\n\nYeah, in that format, git behaviour actually looks really nice.\n\n> The code is working as intended (it is a different discussion if\n> \"as intended\" is actually the desired behaviour).\n\nI think it may be at times.\n\n> We take the preimage tree as a whole, and express postimage in\n> terms of series of patches, _however_ we do not interpret the\n> series of patches as _incremental_.\n\nIIRC, that's not strictly true. We do have logic to make sure that the \ndifference between \"copy\" and \"rename\" is that the rename happens only \nonce, ie I just tested this sequence:\n\n\tmkdir test-rename\n\tcd test-rename/\n\tcp /home/torvalds/git/revision.c .\n\tgit init\n\tgit add .\n\tgit commit -m \"add revision.c\"\n\tcp revision.c rev1.c\n\tcp revision.c rev2.c\n\trm revision.c\n\tem rev1.c\n\tem rev2.c\n\tgit add .\n\tgit commit -a -m \"rename revision.c twice\"\n\n(the two \"em\" calls are just me in an editor, adding a line to the top \nof the file saying \"This is rev[12].c\")\n\nAfter that, doing a \"git show -C\" shows:\n\n\tdiff --git a/revision.c b/rev1.c\n\tsimilarity index 99%\n\tcopy from revision.c\n\tcopy to rev1.c\n\t...\n\tdiff --git a/revision.c b/rev2.c\n\tsimilarity index 99%\n\trename from revision.c\n\trename to rev2.c\n\t...\n\nso we do have a notion of \"incremental\" in that the first is a copy, the \nsecond is a rename, and that the rename is expected to remove the file.\n\n(Doing a \"--stat\" doesn't show the difference between copy and rename, so \nwe'll just see it as\n\n\t revision.c => rev1.c |    1 +\n\t revision.c => rev2.c |    1 +\n\nwhich looks pretty).\n\n> IOW, when we talk about the effect of the second patch that describes \n> the postimage of revision.c, we pretend as if nothing happened with the \n> first patch (which renamed away revision.c).  So \"rewrite revision.c\" is \n> what we say, not \"create revision.c anew, because the first one renamed \n> it away\".\n\nIf that was consistent, then we'd have used \"rename\" in both cases above..\n\n> It was corrected into the current behaviour, following the guiding \n> principle described in this message:\n> \n> \thttp://thread.gmane.org/gmane.comp.version-control.git/3807\n\nAhh, you're a wily one. Using my own words against me.\n\nBut that earlier Linus was obviously a fake impostor, since he was wrong \n(and could thus by definition not _possibly_ be the true Linus!). So your \njudo mindtrick fails.\n\nThat said, I actually think that the earlier Linus might actually be me, \nand he's right in the case he mentions: we should *not* break the \nassociation if it results in a good diff!\n\nIe, the true \"guiding principle\" should be the principle of minizing the \nfinal diff - that's how diff is supposed to act within a single file, and \nI think it's how the rename/copy detection is supposed to act too.\n\nSo:\n\n>     I think it's perfectly valid to say\n> \n>             :100644 100644 <sha_A> <sha_A'> M\tfileA\tfileA\n>             :100644 100644 <sha_A> <sha_B> C89\tfileA\tfileB\n> \n>     which says \"fileA\" was modified from orig-A to new-A, and \"fileB\" is a \n>     copy based on orig-A.\n\nThis is 100% consistent with \"how do I minimally show the differences \nbetween the original and the result\": we decide that we can show it as a \n\"copy\" and a \"modification\" of the original file.\n\nBut it makes sense to \"copy and modify the original\", but it does *not* \nmake sense to \"rename and modify the original\". That is, after all, the \n*only* difference between copying and renaming. A copy will leave the \noriginal around (so that it can be modified), while a rename will not.\n\nSo, by the very definition of \"rename\", doing a \"rename and modify the \noriginal\" would appear to be somewhat senseless, no?\n\n\t\t\tLinus\n"},{"id":"51516","messageId":"7vd4xb5y12.fsf@gitster.siamese.dyndns.org","threadId":"9520","inReplyTo":"alpine.LFD.0.999.0708250819360.25853@woody.linux-foundation.org","subject":"Re: bisect / history preserving on rename + update","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-08-25T17:23:05Z","receivedAt":"2007-08-25T17:23:05Z","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>> It was corrected into the current behaviour, following the guiding \n>> principle described in this message:\n>> \n>> \thttp://thread.gmane.org/gmane.comp.version-control.git/3807\n>\n> Ahh, you're a wily one. Using my own words against me.\n\nI am not being wily.  I usually do not remember nor quote too\nold histories, but June 2005 was somewhat special to me.  Those\ntwo weeks of 18-hour-straight-doing-git-and-nothing-else,\nworking with git and with you in particular, were what taught me\nhow fun open source development and working with brilliant\nothers is.\n\n> Ie, the true \"guiding principle\" should be the principle of minizing the \n> final diff - that's how diff is supposed to act within a single file, and \n> I think it's how the rename/copy detection is supposed to act too.\n\nOk, I would agree with that in principle, but that would be\nrather intrusive change that I am sure would have fallout to\ngit-apply side (and anybody who interprets \"git diff\" output,\nespecially gitweb), too.  I am not rejecting the idea, but I\nwon't be able to look into it myself for some time.\n"}]}