{"thread":{"id":"59636","subject":"Proposal: tell git a file has been renamed","startedAt":"2023-04-22T18:40:17Z","lastAt":"2023-05-11T13:45:34Z","messageCount":24,"participants":["Jeremy Morton","rsbecker@nexbridge.com","Erik Cervin Edin","Kristoffer Haugsbakk","Chris Torek","Junio C Hamano","Felipe Contreras","Jacob Keller"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"475847","messageId":"8fe188a9-c01f-9fb5-5877-8ff508094b22@game-point.net","threadId":"59636","inReplyTo":null,"subject":"Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-22T18:01:45Z","receivedAt":"2023-04-22T18:40:17Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"Yes, I know Linus specifically doesn't store file rename info in Git. \nThe trouble is, every now and then, I'll come across a situation where \nGit doesn't successfully detect that I've renamed a file because I'm \ndoing something like renaming a class at the same time.  So I'll have \na file OldClassNameTests.cs and a NewClassNameTests.cs but a bunch of \nlines in that file have also changed from OldClassName.DoThing() to \nNewClassName.DoThing().  I can clearly see that this is a rename, but \nGit sees enough changed content that it doesn't realize it, and puts \nit in as a delete/add, losing the content history.\n\nThe standard answer for this is to rename the file in one commit, then \nmake the changes.  That's fine if you know ahead of time you'll want \nto do this.  However it's a total PITA if you have a bunch of changes \nand you realize that a rename has caused this problem.  You now have \nto back out your changes to the renamed file, add the rename, commit \nit, then re-apply the changes.\n\nCould a command be added to git that means you tell Git that counts as \na file rename?  Git would add a marker to the staging area that the \nfile has been renamed, and upon commit, would first generate an \nadditional commit for each rename before generating the main commit, \nensuring the rename operation counts as an actual rename, and the \ncontent's history is maintained.\n\n-- \nBest regards,\nJeremy Morton (Jez)\n"},{"id":"475848","messageId":"01cd01d9754b$f12326b0$d3697410$@nexbridge.com","threadId":"59636","inReplyTo":"8fe188a9-c01f-9fb5-5877-8ff508094b22@game-point.net","subject":"RE: Proposal: tell git a file has been renamed","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2023-04-22T18:54:55Z","receivedAt":"2023-04-22T18:55:10Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Saturday, April 22, 2023 2:02 PM, Jeremy Morton wrote:\n>Yes, I know Linus specifically doesn't store file rename info in Git.\n>The trouble is, every now and then, I'll come across a situation where Git doesn't\n>successfully detect that I've renamed a file because I'm doing something like\n>renaming a class at the same time.  So I'll have a file OldClassNameTests.cs and a\n>NewClassNameTests.cs but a bunch of lines in that file have also changed from\n>OldClassName.DoThing() to NewClassName.DoThing().  I can clearly see that this is a\n>rename, but Git sees enough changed content that it doesn't realize it, and puts it in\n>as a delete/add, losing the content history.\n>\n>The standard answer for this is to rename the file in one commit, then make the\n>changes.  That's fine if you know ahead of time you'll want to do this.  However it's a\n>total PITA if you have a bunch of changes and you realize that a rename has caused\n>this problem.  You now have to back out your changes to the renamed file, add the\n>rename, commit it, then re-apply the changes.\n>\n>Could a command be added to git that means you tell Git that counts as a file\n>rename?  Git would add a marker to the staging area that the file has been renamed,\n>and upon commit, would first generate an additional commit for each rename before\n>generating the main commit, ensuring the rename operation counts as an actual\n>rename, and the content's history is maintained.\n\nWould git mv work in your situation? You can stage changes to the original file, then use git mv. Or use git mv first. The rename shows as staged in any event.\n--Randall\n\n"},{"id":"475849","messageId":"01ce01d97553$4361f990$ca25ecb0$@nexbridge.com","threadId":"59636","inReplyTo":"fbe77ad2-ce65-e6a6-254e-01bf6446d582@game-point.net","subject":"RE: Proposal: tell git a file has been renamed","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2023-04-22T19:47:19Z","receivedAt":"2023-04-22T19:48:46Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"No, history is preserved in the rename.\n\n>-----Original Message-----\n>From: Jeremy Morton <admin@game-point.net>\n>Sent: Saturday, April 22, 2023 3:45 PM\n>To: rsbecker@nexbridge.com; git@vger.kernel.org\n>Subject: Re: Proposal: tell git a file has been renamed\n>\n>I read that git mv is basically the equivalent to deleting the old file, creating the new\n>file, and adding the changes.  Isn't it?  If so it's gonna have the same problem as I\n>have now.\n>\n>--\n>Best regards,\n>Jeremy Morton (Jez)\n>\n>On 22/04/2023 19:54, rsbecker@nexbridge.com wrote:\n>> On Saturday, April 22, 2023 2:02 PM, Jeremy Morton wrote:\n>>> Yes, I know Linus specifically doesn't store file rename info in Git.\n>>> The trouble is, every now and then, I'll come across a situation\n>>> where Git doesn't successfully detect that I've renamed a file\n>>> because I'm doing something like renaming a class at the same time.\n>>> So I'll have a file OldClassNameTests.cs and a NewClassNameTests.cs\n>>> but a bunch of lines in that file have also changed from\n>>> OldClassName.DoThing() to NewClassName.DoThing().  I can clearly see\n>>> that this is a rename, but Git sees enough changed content that it\n>>> doesn't realize it, and puts it in as a delete/add, losing the content history.\n>>>\n>>> The standard answer for this is to rename the file in one commit,\n>>> then make the changes.  That's fine if you know ahead of time you'll\n>>> want to do this.  However it's a total PITA if you have a bunch of\n>>> changes and you realize that a rename has caused this problem.  You\n>>> now have to back out your changes to the renamed file, add the rename, commit\n>it, then re-apply the changes.\n>>>\n>>> Could a command be added to git that means you tell Git that counts\n>>> as a file rename?  Git would add a marker to the staging area that\n>>> the file has been renamed, and upon commit, would first generate an\n>>> additional commit for each rename before generating the main commit,\n>>> ensuring the rename operation counts as an actual rename, and the content's\n>history is maintained.\n>>\n>> Would git mv work in your situation? You can stage changes to the original file,\n>then use git mv. Or use git mv first. The rename shows as staged in any event.\n>> --Randall\n>>\n>>\n\n"},{"id":"475850","messageId":"fbe77ad2-ce65-e6a6-254e-01bf6446d582@game-point.net","threadId":"59636","inReplyTo":"01cd01d9754b$f12326b0$d3697410$@nexbridge.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-22T19:44:45Z","receivedAt":"2023-04-22T19:48:46Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"I read that git mv is basically the equivalent to deleting the old \nfile, creating the new file, and adding the changes.  Isn't it?  If so \nit's gonna have the same problem as I have now.\n\n-- \nBest regards,\nJeremy Morton (Jez)\n\nOn 22/04/2023 19:54, rsbecker@nexbridge.com wrote:\n> On Saturday, April 22, 2023 2:02 PM, Jeremy Morton wrote:\n>> Yes, I know Linus specifically doesn't store file rename info in Git.\n>> The trouble is, every now and then, I'll come across a situation where Git doesn't\n>> successfully detect that I've renamed a file because I'm doing something like\n>> renaming a class at the same time.  So I'll have a file OldClassNameTests.cs and a\n>> NewClassNameTests.cs but a bunch of lines in that file have also changed from\n>> OldClassName.DoThing() to NewClassName.DoThing().  I can clearly see that this is a\n>> rename, but Git sees enough changed content that it doesn't realize it, and puts it in\n>> as a delete/add, losing the content history.\n>>\n>> The standard answer for this is to rename the file in one commit, then make the\n>> changes.  That's fine if you know ahead of time you'll want to do this.  However it's a\n>> total PITA if you have a bunch of changes and you realize that a rename has caused\n>> this problem.  You now have to back out your changes to the renamed file, add the\n>> rename, commit it, then re-apply the changes.\n>>\n>> Could a command be added to git that means you tell Git that counts as a file\n>> rename?  Git would add a marker to the staging area that the file has been renamed,\n>> and upon commit, would first generate an additional commit for each rename before\n>> generating the main commit, ensuring the rename operation counts as an actual\n>> rename, and the content's history is maintained.\n> \n> Would git mv work in your situation? You can stage changes to the original file, then use git mv. Or use git mv first. The rename shows as staged in any event.\n> --Randall\n> \n> \n"},{"id":"475851","messageId":"3ac19159-7314-c299-5112-b0f7aa2cc409@game-point.net","threadId":"59636","inReplyTo":"01ce01d97553$4361f990$ca25ecb0$@nexbridge.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-22T19:54:28Z","receivedAt":"2023-04-22T19:54:44Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"https://stackoverflow.com/a/1094392/178757\n\nsays:\n\ngit mv oldname newname\n\nis just shorthand for:\n\nmv oldname newname\ngit add newname\ngit rm oldname\n\n-- \nBest regards,\nJeremy Morton (Jez)\n\nOn 22/04/2023 20:47, rsbecker@nexbridge.com wrote:\n> No, history is preserved in the rename.\n> \n>> -----Original Message-----\n>> From: Jeremy Morton <admin@game-point.net>\n>> Sent: Saturday, April 22, 2023 3:45 PM\n>> To: rsbecker@nexbridge.com; git@vger.kernel.org\n>> Subject: Re: Proposal: tell git a file has been renamed\n>>\n>> I read that git mv is basically the equivalent to deleting the old file, creating the new\n>> file, and adding the changes.  Isn't it?  If so it's gonna have the same problem as I\n>> have now.\n>>\n>> --\n>> Best regards,\n>> Jeremy Morton (Jez)\n>>\n>> On 22/04/2023 19:54, rsbecker@nexbridge.com wrote:\n>>> On Saturday, April 22, 2023 2:02 PM, Jeremy Morton wrote:\n>>>> Yes, I know Linus specifically doesn't store file rename info in Git.\n>>>> The trouble is, every now and then, I'll come across a situation\n>>>> where Git doesn't successfully detect that I've renamed a file\n>>>> because I'm doing something like renaming a class at the same time.\n>>>> So I'll have a file OldClassNameTests.cs and a NewClassNameTests.cs\n>>>> but a bunch of lines in that file have also changed from\n>>>> OldClassName.DoThing() to NewClassName.DoThing().  I can clearly see\n>>>> that this is a rename, but Git sees enough changed content that it\n>>>> doesn't realize it, and puts it in as a delete/add, losing the content history.\n>>>>\n>>>> The standard answer for this is to rename the file in one commit,\n>>>> then make the changes.  That's fine if you know ahead of time you'll\n>>>> want to do this.  However it's a total PITA if you have a bunch of\n>>>> changes and you realize that a rename has caused this problem.  You\n>>>> now have to back out your changes to the renamed file, add the rename, commit\n>> it, then re-apply the changes.\n>>>>\n>>>> Could a command be added to git that means you tell Git that counts\n>>>> as a file rename?  Git would add a marker to the staging area that\n>>>> the file has been renamed, and upon commit, would first generate an\n>>>> additional commit for each rename before generating the main commit,\n>>>> ensuring the rename operation counts as an actual rename, and the content's\n>> history is maintained.\n>>>\n>>> Would git mv work in your situation? You can stage changes to the original file,\n>> then use git mv. Or use git mv first. The rename shows as staged in any event.\n>>> --Randall\n>>>\n>>>\n> \n> \n"},{"id":"475880","messageId":"01d301d97567$0e9bc0b0$2bd34210$@nexbridge.com","threadId":"59636","inReplyTo":"3ac19159-7314-c299-5112-b0f7aa2cc409@game-point.net","subject":"RE: Proposal: tell git a file has been renamed","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2023-04-22T22:09:01Z","receivedAt":"2023-04-22T22:09:18Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On Saturday, April 22, 2023 3:54 PM, Jeremy Morton wrote:\n>Subject: Re: Proposal: tell git a file has been renamed\n>\n>https://stackoverflow.com/a/1094392/178757\n>\n>says:\n>\n>git mv oldname newname\n>\n>is just shorthand for:\n>\n>mv oldname newname\n>git add newname\n>git rm oldname\n\nThe above stackoverflow topic is from 2009. A lot has changed since then. My test follows. Please note the status and git log contents indicating the rename.\n\n$ mkdir test2\n$ cd test2\n$ git init\n$ echo \"Initial\" > file1\n$ git add file1\n$ commit -m \"Commit 1\"\n$ git mv file1 file2\n$ git status\nOn branch master\nChanges to be committed:\n  (use \"git restore --staged <file>...\" to unstage)\n        renamed:    file1 -> file2\n$ git commit -m \"Rename\"\n$ git log --patch\ncommit 014068fcedaf361f45c356046cf513b79537f53f (HEAD -> master)\nAuthor: Randall S. Becker <rsbecker@nexbridge.com>\nDate:   Sat Apr 22 18:02:07 2023 -0400\n\n    Rename\n\ndiff --git a/file1 b/file2\nsimilarity index 100%\nrename from file1\nrename to file2\n\ncommit 235a33801b82eac67e25c57e512ca428f2d49cea\nAuthor: Randall S. Becker <rsbecker@nexbridge.com>\nDate:   Sat Apr 22 18:01:48 2023 -0400\n\n    Commit 1\n\ndiff --git a/file1 b/file1\nnew file mode 100644\nindex 0000000..a77fa51\n--- /dev/null\n+++ b/file1\n@@ -0,0 +1 @@\n+Initial\n\n>\n>On 22/04/2023 20:47, rsbecker@nexbridge.com wrote:\n>> No, history is preserved in the rename.\n>>\n>>> -----Original Message-----\n>>> From: Jeremy Morton <admin@game-point.net>\n>>> Sent: Saturday, April 22, 2023 3:45 PM\n>>> To: rsbecker@nexbridge.com; git@vger.kernel.org\n>>> Subject: Re: Proposal: tell git a file has been renamed\n>>>\n>>> I read that git mv is basically the equivalent to deleting the old\n>>> file, creating the new file, and adding the changes.  Isn't it?  If\n>>> so it's gonna have the same problem as I have now.\n>>>\n>>> --\n>>> Best regards,\n>>> Jeremy Morton (Jez)\n>>>\n>>> On 22/04/2023 19:54, rsbecker@nexbridge.com wrote:\n>>>> On Saturday, April 22, 2023 2:02 PM, Jeremy Morton wrote:\n>>>>> Yes, I know Linus specifically doesn't store file rename info in Git.\n>>>>> The trouble is, every now and then, I'll come across a situation\n>>>>> where Git doesn't successfully detect that I've renamed a file\n>>>>> because I'm doing something like renaming a class at the same time.\n>>>>> So I'll have a file OldClassNameTests.cs and a NewClassNameTests.cs\n>>>>> but a bunch of lines in that file have also changed from\n>>>>> OldClassName.DoThing() to NewClassName.DoThing().  I can clearly\n>>>>> see that this is a rename, but Git sees enough changed content that\n>>>>> it doesn't realize it, and puts it in as a delete/add, losing the content history.\n>>>>>\n>>>>> The standard answer for this is to rename the file in one commit,\n>>>>> then make the changes.  That's fine if you know ahead of time\n>>>>> you'll want to do this.  However it's a total PITA if you have a\n>>>>> bunch of changes and you realize that a rename has caused this\n>>>>> problem.  You now have to back out your changes to the renamed\n>>>>> file, add the rename, commit\n>>> it, then re-apply the changes.\n>>>>>\n>>>>> Could a command be added to git that means you tell Git that counts\n>>>>> as a file rename?  Git would add a marker to the staging area that\n>>>>> the file has been renamed, and upon commit, would first generate an\n>>>>> additional commit for each rename before generating the main\n>>>>> commit, ensuring the rename operation counts as an actual rename,\n>>>>> and the content's\n>>> history is maintained.\n>>>>\n>>>> Would git mv work in your situation? You can stage changes to the\n>>>> original file,\n>>> then use git mv. Or use git mv first. The rename shows as staged in any event.\n>>>> --Randall\n>>>>\n>>>>\n>>\n>>\n\n"},{"id":"475896","messageId":"CA+JQ7M8avZiZuBHUtkQu2WqtR4zozU3C2ayCjBxRsQcKjAr16g@mail.gmail.com","threadId":"59636","inReplyTo":"01d301d97567$0e9bc0b0$2bd34210$@nexbridge.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Erik Cervin Edin","fromEmail":"erik@cervined.in","sentAt":"2023-04-23T09:38:52Z","receivedAt":"2023-04-23T09:39:32Z","isPatch":false,"sender":{"key":"erik@cervined.in","avatar":null},"body":"On Sat, Apr 22, 2023 at 9:57 PM Jeremy Morton <admin@game-point.net> wrote:\n>\n> https://stackoverflow.com/a/1094392/178757\n>\n> says:\n>\n> git mv oldname newname\n>\n> is just shorthand for:\n>\n> mv oldname newname\n> git add newname\n> git rm oldname\n\nThat's what I though but it's more like:\n  git show :0:oldname > newname\n  git add newname\n  git rm --cached oldname\n  mv oldname newname\n\nBasically, a move but also preserving staged/unstaged contents. But\nyes. How git handles renames can sometimes be a bit of a PITA.\n\nOn Sun, Apr 23, 2023, 12:16 AM <rsbecker@nexbridge.com> wrote:\n>\n> $ git add file1\n> $ commit -m \"Commit 1\"\n> $ git mv file1 file2\n> $ git status\n> On branch master\n> Changes to be committed:\n>   (use \"git restore --staged <file>...\" to unstage)\n>         renamed:    file1 -> file2\n\nI think your point is better illustrated\n  git add file1\n  commit -m \"Commit 1\"\n  echo 'Changed' > file1\n  git mv file1 file2\n  git status\nWhich yields:\nChanges to be committed:\n  (use \"git restore --staged <file>...\" to unstage)\n        renamed:    file1 -> file2\n\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git restore <file>...\" to discard changes in working directory)\n        modified:   file2\n\nOr perhaps even:\n  echo Initial > file1\n  seq 1 10 >> file1 # We need a larger file to detect rename with change\n  git add file1\n  git commit -m 'Commit 1'\n  seq -i 's/Initial/Changed/' file1\n  git add file1 # Stage changes\n  seq 11 20 >> file1 # Add some unstaged changes\n  git mv file1 file2\n\nThis will result in a staged rename, as well as the staged change\n'Initial'  -> 'Changed' with a bunch of additional unstaged lines of\nnumbers 11 to 20.\nNB that this doesn't play nice unless the contents of file1 in HEAD\nand index are similar enough (at least 50%?)\n"},{"id":"475904","messageId":"f249ec0f-f2f0-43d8-bb70-5a4a7c91c608@app.fastmail.com","threadId":"59636","inReplyTo":"8fe188a9-c01f-9fb5-5877-8ff508094b22@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Kristoffer Haugsbakk","fromEmail":"code@khaugsbakk.name","sentAt":"2023-04-23T21:01:25Z","receivedAt":"2023-04-23T21:01:52Z","isPatch":false,"sender":{"key":"code@khaugsbakk.name","avatar":"https://avatars.githubusercontent.com/u/2229597?v=4"},"body":"On Sat, Apr 22, 2023, at 20:01, Jeremy Morton wrote:\n> Could a command be added to git that means you tell Git that counts as\n> a file rename?  Git would add a marker to the staging area that the\n> file has been renamed, and upon commit, would first generate an\n> additional commit for each rename before generating the main commit,\n> ensuring the rename operation counts as an actual rename, and the\n> content's history is maintained.\n\nI don’t see the (conceptual) problem with a modification of this as a\nhistory rewriting tool:\n\n• Given a series of commits:\n• Tool X modifies all the commits so that the default similarity index\n  for tools like git-log(1) is triggered on intended file renames\n• The user will be probably be prompted with a list of initial potential\n  renames and then will\n  • Keep the intended renames\n  • Remove the not-intended renames\n  • Add the additional renames\n\nBut this looks like something that a third-party tool could implement.\n\n-- \nKristoffer Haugsbakk\n"},{"id":"475905","messageId":"CAPx1Gvdc6bqzt2PpqD1Z4e5w+b=8gZhUSyfUQC1n8QazdBacEw@mail.gmail.com","threadId":"59636","inReplyTo":"8fe188a9-c01f-9fb5-5877-8ff508094b22@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Chris Torek","fromEmail":"chris.torek@gmail.com","sentAt":"2023-04-24T01:43:18Z","receivedAt":"2023-04-24T01:43:36Z","isPatch":false,"sender":{"key":"chris.torek@gmail.com","avatar":"https://avatars.githubusercontent.com/u/16826774?v=4"},"body":"(By the way, apologies for the stuttering \"gitt\" typos that seem\nto keep creeping into my messages here. I'm not sure what's\ncausing them -- I make a lot of typos but this is abnormal!)\n\nOn Sat, Apr 22, 2023 at 12:22 PM Jeremy Morton <admin@game-point.net> wrote:\n\n> [renames are a problem]\n\nI have long wondered if there was a way to improve this\nexperience myself.\n\n(I also note that most of the followup messages up to this point\nhave missed the point.  It's true that you can run `git mv` and\n`git commit`, but you've already said that this becomes\nparticularly painful when you realize that it's appropriate *after\nthe fact*, when you've already made intermediate commits and/or\nstaged changes or whatever.)\n\n> The standard answer for this is to rename the file in one commit, then\n> make the changes.  That's fine if you know ahead of time you'll want\n> to do this.  However it's a total PITA if you have a bunch of changes\n> and you realize that a rename has caused this problem.  You now have\n> to back out your changes to the renamed file, add the rename, commit\n> it, then re-apply the changes.\n>\n> Could a command be added to git that means you tell Git that counts as\n> a file rename?  Git would add a marker to the staging area that the\n> file has been renamed, and upon commit, would first generate an\n> additional commit for each rename before generating the main commit,\n> ensuring the rename operation counts as an actual rename, and the\n> content's history is maintained.\n\nThe index *currently* has no room to store anything like this: it\nis, in effect, just the proposed next commit, stored as a\nflattened tree.  There are, however, extra marker records that\ncan be added.  So:\n\nIf `git mv` (or a new command) had a flag to say \"make a special\nindex entry so that the next `git commit` does a double commit\",\nwe could in fact make this work.  Alternatively, we could have a\ncommand -- similar to `git commit --only` in effect -- that uses\nthe current (HEAD) commit to construct a renames-only commit, in\nwhich 100%-identical-file matching would (in general) find the\ndesired renames -- and make it, perhaps also co-ordinating with\n`git mv` of existing files in the index.  (I'd also like to have\n`git mv --after`, in the same vein as `hg mv --after`; I long ago\nwrote a cheesy script to achieve this, but it would be nice to\nhave a proper command.)\n\nOn top of this, it might be nice to have a standardized commit\nmessage and/or other marker (in the commit header?) for a \"rename-\nonly\" commit, which this kind of extra-rename-commit operation\nwould use.  Then `git log` and `git blame` and other commands\ncould easily detect such commits and default to an automatic\n`--follow` style following, and `git log` might be allowed to omit\nthe *display* of such a commit by default, by showing all the\nrenames as renames in the subsequent commit (though this would\npresumably require an internal verification step to check for\nspoofed renames that are not in fact rename-only operations).\n\nIn any case, this *idea* is easy, like many ideas.  It really\ncomes down to implementation.  If someone thinks this is a great\nidea, someone (perhaps me) should work on *implementing* it. :-)\n\nChris\n"},{"id":"475907","messageId":"74a361fd-4ee6-f362-8d49-92417f0e2dac@game-point.net","threadId":"59636","inReplyTo":"CAPx1Gvdc6bqzt2PpqD1Z4e5w+b=8gZhUSyfUQC1n8QazdBacEw@mail.gmail.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-24T10:10:59Z","receivedAt":"2023-04-24T10:15:44Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"On 24/04/2023 02:43, Chris Torek wrote:>> [renames are a problem]\n> \n> I have long wondered if there was a way to improve this\n> experience myself.\n> \n> (I also note that most of the followup messages up to this point\n> have missed the point.  It's true that you can run `git mv` and\n> `git commit`, but you've already said that this becomes\n> particularly painful when you realize that it's appropriate *after\n> the fact*, when you've already made intermediate commits and/or\n> staged changes or whatever.)\n> \n> The index *currently* has no room to store anything like this: it\n> is, in effect, just the proposed next commit, stored as a\n> flattened tree.  There are, however, extra marker records that\n> can be added.  So:\n> \n> If `git mv` (or a new command) had a flag to say \"make a special\n> index entry so that the next `git commit` does a double commit\",\n> we could in fact make this work.  Alternatively, we could have a\n> command -- similar to `git commit --only` in effect -- that uses\n> the current (HEAD) commit to construct a renames-only commit, in\n> which 100%-identical-file matching would (in general) find the\n> desired renames -- and make it, perhaps also co-ordinating with\n> `git mv` of existing files in the index.  (I'd also like to have\n\nI'm not sure what the utility of the --only thing would be - to detect \nrenames that didn't have changed content so that all renames could be \ndone in one pre-commit?\n\n> `git mv --after`, in the same vein as `hg mv --after`; I long ago\n> wrote a cheesy script to achieve this, but it would be nice to\n> have a proper command.)\n\nHuh, I just read the docs on that... does that mean hg already has \nthis functionality of being able to store a \"this was renamed\" marker \nin its index?\n\n> On top of this, it might be nice to have a standardized commit\n> message and/or other marker (in the commit header?) for a \"rename-\n> only\" commit, which this kind of extra-rename-commit operation\n> would use.  Then `git log` and `git blame` and other commands\n> could easily detect such commits and default to an automatic\n> `--follow` style following, and `git log` might be allowed to omit\n> the *display* of such a commit by default, by showing all the\n> renames as renames in the subsequent commit (though this would\n> presumably require an internal verification step to check for\n> spoofed renames that are not in fact rename-only operations).\n\nI'm surprised --follow isn't the default, actually... isn't the whole \npoint of detecting renames to allow content history to be tracked back \nthrough renames?\n\nAnother one that jumped to mind for me is bisect.  As rename-only \ncommits are liable to create broken builds, it should skip over them \nto the 'content' commit.\n\n> In any case, this *idea* is easy, like many ideas.  It really\n> comes down to implementation.  If someone thinks this is a great\n> idea, someone (perhaps me) should work on *implementing* it. :-)\n\nIf you do please feel free to CC me in an email about it, it'd be good \nto know if this became available!\n\n-- \nBest regards,\nJeremy Morton (Jez)\n"},{"id":"475908","messageId":"CAPx1GvfszM00DzW9JxxoNZfnM3-eUJCxPArUzwFV7E+t==cJ4g@mail.gmail.com","threadId":"59636","inReplyTo":"74a361fd-4ee6-f362-8d49-92417f0e2dac@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Chris Torek","fromEmail":"chris.torek@gmail.com","sentAt":"2023-04-24T10:24:27Z","receivedAt":"2023-04-24T10:27:51Z","isPatch":false,"sender":{"key":"chris.torek@gmail.com","avatar":"https://avatars.githubusercontent.com/u/16826774?v=4"},"body":"On Mon, Apr 24, 2023 at 3:15 AM Jeremy Morton <admin@game-point.net> wrote:\n> On 24/04/2023 02:43, Chris Torek wrote:\n> > ... Alternatively, we could have a\n> > command -- similar to `git commit --only` in effect\n\n> I'm not sure what the utility of the --only thing would be - to detect\n> renames that didn't have changed content so that all renames could be\n> done in one pre-commit?\n\nI mentioned `git commit --only` here just to point out that `git\ncommit` already has the ability to make a commit without using the\ncurrent index as the new commit's source.  A \"just do renames\"\ncommit operation (in spite of other changes already made in the\ncurrent index) would need similar functionality.\n\nExactly how this might work, I haven't defined.\n\n> Huh, I just read the docs on [hg mv]... does that mean hg already has\n> this functionality of being able to store a \"this was renamed\" marker\n> in its index?\n\nMercurial does not have an index in the first place.  The internal\nstructure of the Mercurial database is an append-only series of\nchangelongs, with files stored as deltas from the previous version\nof that file (with some exceptions).  Files are listed in a manifest,\nand renaming a file preserves the file's identity despite the\nchange of name.\n\n(This internal format is very different from Git's.  Git is a\ncontent-addressable file system, rather than an append-only\nchangelog.)\n\nChris\n"},{"id":"475909","messageId":"CA+JQ7M-1YvZFzE_CtBQa5_eEXa1sPqK4xsTxdwpAQo_YcmW+-A@mail.gmail.com","threadId":"59636","inReplyTo":"74a361fd-4ee6-f362-8d49-92417f0e2dac@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Erik Cervin Edin","fromEmail":"erik@cervined.in","sentAt":"2023-04-24T10:49:19Z","receivedAt":"2023-04-24T10:50:00Z","isPatch":false,"sender":{"key":"erik@cervined.in","avatar":null},"body":"On Mon, Apr 24, 2023 at 12:21 PM Jeremy Morton <admin@game-point.net> wrote:\n>\n> I'm surprised --follow isn't the default, actually... isn't the whole\n> point of detecting renames to allow content history to be tracked back\n> through renames?\n\nYou can set log to --follow by default\n  If true, git log will act as if the --follow option was used when a\nsingle <path> is given.\n  This has the same limitations as --follow, i.e. it cannot be used to\nfollow multiple files\n  and does not work well on non-linear history.\n  https://git-scm.com/docs/git-log#Documentation/git-log.txt-logfollow\n\nThe reason it's not default is probably those limitations.\n\n>\n> Another one that jumped to mind for me is bisect.  As rename-only\n> commits are liable to create broken builds, it should skip over them\n> to the 'content' commit.\n>\n\nI always find this to be the main dilemma.\nI try to make commits as discrete changes but it's not always possible\nwith renames.\nSometimes, renaming a file changes it so much that the rename\ndetection doesn't work by default.\nThere are also other problems that arise when reordering commits and\nchanges in a feature branch.\nI've found that the safest thing is to split renames out into discrete\ncommits and only do 100% renames.\n"},{"id":"475910","messageId":"91dab444-5f65-31ae-c0c6-0b84313bcd94@game-point.net","threadId":"59636","inReplyTo":"CA+JQ7M-1YvZFzE_CtBQa5_eEXa1sPqK4xsTxdwpAQo_YcmW+-A@mail.gmail.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-24T11:17:19Z","receivedAt":"2023-04-24T11:18:00Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"On 24/04/2023 11:49, Erik Cervin Edin wrote:\n\n> I always find this to be the main dilemma.\n> I try to make commits as discrete changes but it's not always possible\n> with renames.\n> Sometimes, renaming a file changes it so much that the rename\n> detection doesn't work by default.\n> There are also other problems that arise when reordering commits and\n> changes in a feature branch.\n> I've found that the safest thing is to split renames out into discrete\n> commits and only do 100% renames.\n\nThere's no getting away from the fact that this adds a lot of (IMHO \nunnecessary) work if you've already done a rename that git can't \ndetect and have both that and a bunch of other changes sitting in the \nindex.  What feels like it would be a natural resolution in these \ncases, though, is a \"no, this remove/add is actually a rename\" command.\n\n-- \nBest regards,\nJeremy Morton (Jez)\n"},{"id":"475916","messageId":"CA+JQ7M_Lv1acopOpPoHxp7mPwWMFj-7wwwDPpV7KUbwFsjpoxA@mail.gmail.com","threadId":"59636","inReplyTo":"91dab444-5f65-31ae-c0c6-0b84313bcd94@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Erik Cervin Edin","fromEmail":"erik@cervined.in","sentAt":"2023-04-24T14:00:58Z","receivedAt":"2023-04-24T14:01:44Z","isPatch":false,"sender":{"key":"erik@cervined.in","avatar":null},"body":"On Mon, Apr 24, 2023 at 1:17 PM Jeremy Morton <admin@game-point.net> wrote:\n>\n> There's no getting away from the fact that this adds a lot of (IMHO\n> unnecessary) work if you've already done a rename that git can't\n> detect and have both that and a bunch of other changes sitting in the\n> index.  What feels like it would be a natural resolution in these\n> cases, though, is a \"no, this remove/add is actually a rename\" command.\n\nIt can definitely be both arduous and non-obvious how to deal with this.\n\nThe problem is that such a command cannot exist atm. because renames\ndon't exist, they are only interpreted. So the only way to achieve\nthis is to revert enough of the contents staged to the index such that\nthe rename is detected. The only way to do that in a foolproof manner\nis reverting all the staged changes except the path so that the moved\nfile in the index is identical to the old file in HEAD.\n\nIf I understand you correctly, your point here is that it's\nnon-trivial to go from a state where a file has been renamed, with\nenough changes staged into the index that the rename hasn't been\ndetected, to a state where the rename is recorded in the index?\n\nThe most straightforward method I can think of to restore the staged\nchanges, do the rename without changes, commit and then go about the\nrest\neg:\n  git restore --staged file2\n  mv file2 file1\n  git mv file1 file2\n  git commit -m rename\n"},{"id":"475917","messageId":"b157077e-a336-e550-2666-9880130eb5aa@game-point.net","threadId":"59636","inReplyTo":"CA+JQ7M_Lv1acopOpPoHxp7mPwWMFj-7wwwDPpV7KUbwFsjpoxA@mail.gmail.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-24T14:42:04Z","receivedAt":"2023-04-24T14:42:28Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"Yep, and that suggestion is rather arduous compared to something like:\n\ngit markasrenamed file2 file1\ngit commit\n\n-- \nBest regards,\nJeremy Morton (Jez)\n\nOn 24/04/2023 15:00, Erik Cervin Edin wrote:\n> On Mon, Apr 24, 2023 at 1:17 PM Jeremy Morton <admin@game-point.net> wrote:\n>>\n>> There's no getting away from the fact that this adds a lot of (IMHO\n>> unnecessary) work if you've already done a rename that git can't\n>> detect and have both that and a bunch of other changes sitting in the\n>> index.  What feels like it would be a natural resolution in these\n>> cases, though, is a \"no, this remove/add is actually a rename\" command.\n> \n> It can definitely be both arduous and non-obvious how to deal with this.\n> \n> The problem is that such a command cannot exist atm. because renames\n> don't exist, they are only interpreted. So the only way to achieve\n> this is to revert enough of the contents staged to the index such that\n> the rename is detected. The only way to do that in a foolproof manner\n> is reverting all the staged changes except the path so that the moved\n> file in the index is identical to the old file in HEAD.\n> \n> If I understand you correctly, your point here is that it's\n> non-trivial to go from a state where a file has been renamed, with\n> enough changes staged into the index that the rename hasn't been\n> detected, to a state where the rename is recorded in the index?\n> \n> The most straightforward method I can think of to restore the staged\n> changes, do the rename without changes, commit and then go about the\n> rest\n> eg:\n>    git restore --staged file2\n>    mv file2 file1\n>    git mv file1 file2\n>    git commit -m rename\n> \n"},{"id":"475957","messageId":"xmqqfs8pdtld.fsf@gitster.g","threadId":"59636","inReplyTo":"8fe188a9-c01f-9fb5-5877-8ff508094b22@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-04-24T18:26:54Z","receivedAt":"2023-04-24T18:26:59Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeremy Morton <admin@game-point.net> writes:\n\n> Could a command be added to git that means you tell Git that counts as\n> a file rename?\n\nTelling Git is the easy part.  How to make it honor what it was told\nearlier is harder.\n\nI recall that there was an idea about recording similarity index\nbetween two blobs precomputed so that the same pair of blobs do not\nhave to be computed over and over again, when you do \"git log -M\"?\n\nAn obvious way to implement this \"I know HEAD^:path1 and HEAD:path2\nare similar enough that they deserve to be called a rename\" can be\nto invalidate and then contaminate such a similarity cache with\nend-user supplied data.\n\n\n"},{"id":"475960","messageId":"6446d78fbbe82_cd61294e5@chronos.notmuch","threadId":"59636","inReplyTo":"CA+JQ7M_Lv1acopOpPoHxp7mPwWMFj-7wwwDPpV7KUbwFsjpoxA@mail.gmail.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2023-04-24T19:25:03Z","receivedAt":"2023-04-24T19:25:13Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Erik Cervin Edin wrote:\n> On Mon, Apr 24, 2023 at 1:17 PM Jeremy Morton <admin@game-point.net> wrote:\n> >\n> > There's no getting away from the fact that this adds a lot of (IMHO\n> > unnecessary) work if you've already done a rename that git can't\n> > detect and have both that and a bunch of other changes sitting in the\n> > index.  What feels like it would be a natural resolution in these\n> > cases, though, is a \"no, this remove/add is actually a rename\" command.\n> \n> It can definitely be both arduous and non-obvious how to deal with this.\n> \n> The problem is that such a command cannot exist atm. because renames\n> don't exist, they are only interpreted. So the only way to achieve\n> this is to revert enough of the contents staged to the index such that\n> the rename is detected. The only way to do that in a foolproof manner\n> is reverting all the staged changes except the path so that the moved\n> file in the index is identical to the old file in HEAD.\n\nI agree recording renames explicitely might be a good addition to git, but the\nreal question is how are they going to be stored in the object storage.\n\nMy guess is that it can be added in the commit object after \"committer\", just\nadd a \"renames\" field with all the renames, or one \"rename\" field per rename.\nIt would be backwards compatible because any field can be added this way.\n\nHow to generate these fields is a separate issue: first things first.\n\n-- \nFelipe Contreras"},{"id":"475963","messageId":"xmqq8rehdq4m.fsf@gitster.g","threadId":"59636","inReplyTo":"8fe188a9-c01f-9fb5-5877-8ff508094b22@game-point.net","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-04-24T19:41:45Z","receivedAt":"2023-04-24T19:41:50Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeremy Morton <admin@game-point.net> writes:\n\n> The standard answer for this is to rename the file in one commit, then\n> make the changes.\n\nOh, by the way, this is a pure myth that would unlikely be helpful\nin the bigger picture.\n\nWhen you rename and heavily modify the resulting new path because\nyou have to solve something, such a work would likely be done on the\nsame topic branch.  One step of it may be a pure rename, and other\nsteps may involve heavily changing the renamed result, or you may\nupdate the contents in the original and the do a rename at the end,\nbut either way, when you integrate the end result of the whole topic\nbranch into the master history, what such a merge will see is that\nthe original file has disappeared and a new file with contents not\nat all similar to the disappeared file has appeared.  \"pure rename\nwith changes in separate commits\" would have no effect when showing\nsuch a history with \"git log --first-parent -p\" for a birds-eye\nview.\n\n"},{"id":"475964","messageId":"26c4306d-f0f1-a2a6-55a5-6bb10c77cc0f@intel.com","threadId":"59636","inReplyTo":"6446d78fbbe82_cd61294e5@chronos.notmuch","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2023-04-24T19:44:47Z","receivedAt":"2023-04-24T19:44:57Z","isPatch":false,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"\n\nOn 4/24/2023 12:25 PM, Felipe Contreras wrote:\n> Erik Cervin Edin wrote:\n>> On Mon, Apr 24, 2023 at 1:17 PM Jeremy Morton <admin@game-point.net> wrote:\n>>>\n>>> There's no getting away from the fact that this adds a lot of (IMHO\n>>> unnecessary) work if you've already done a rename that git can't\n>>> detect and have both that and a bunch of other changes sitting in the\n>>> index.  What feels like it would be a natural resolution in these\n>>> cases, though, is a \"no, this remove/add is actually a rename\" command.\n>>\n>> It can definitely be both arduous and non-obvious how to deal with this.\n>>\n>> The problem is that such a command cannot exist atm. because renames\n>> don't exist, they are only interpreted. So the only way to achieve\n>> this is to revert enough of the contents staged to the index such that\n>> the rename is detected. The only way to do that in a foolproof manner\n>> is reverting all the staged changes except the path so that the moved\n>> file in the index is identical to the old file in HEAD.\n> \n> I agree recording renames explicitely might be a good addition to git, but the\n> real question is how are they going to be stored in the object storage.\n> \n> My guess is that it can be added in the commit object after \"committer\", just\n> add a \"renames\" field with all the renames, or one \"rename\" field per rename.\n> It would be backwards compatible because any field can be added this way.\n> \n> How to generate these fields is a separate issue: first things first.\n> \n\nThe other end of the solution space is to try to find ways to make the\nrename detection logic more accurate. We wouldn't need to store such a\nrename if the detection gave the correct answer in the first place.\n\nYou can already kind of do this by modifying the similarity values when\nsearching for renames: the -M option takes a percentage for how similar\nfiles need to be in order for it to be a rename. The default is 50%,\nmeaning that the files have to stay at least 50% the same in order to be\nconsidered a rename.\n\nOne potential in the case for renames which also must change class\nnames, etc could be a mechanism to say \"treat it as a rename if the\ncontent is the same after performing this replacement\", where you could\nspecify what string is being replaced in the rename somehow.\n\nThis could easily be done for reviewing a previous change, but\nspecifically how to *store* this expression so you don't need to\nremember such values in the future is a bigger challenge.\n"},{"id":"475967","messageId":"6446dfdfdd6c_cd6129446@chronos.notmuch","threadId":"59636","inReplyTo":"26c4306d-f0f1-a2a6-55a5-6bb10c77cc0f@intel.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2023-04-24T20:00:31Z","receivedAt":"2023-04-24T20:00:52Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Jacob Keller wrote:\n> On 4/24/2023 12:25 PM, Felipe Contreras wrote:\n> > Erik Cervin Edin wrote:\n> >> On Mon, Apr 24, 2023 at 1:17 PM Jeremy Morton <admin@game-point.net> wrote:\n> >>>\n> >>> There's no getting away from the fact that this adds a lot of (IMHO\n> >>> unnecessary) work if you've already done a rename that git can't\n> >>> detect and have both that and a bunch of other changes sitting in the\n> >>> index.  What feels like it would be a natural resolution in these\n> >>> cases, though, is a \"no, this remove/add is actually a rename\" command.\n> >>\n> >> It can definitely be both arduous and non-obvious how to deal with this.\n> >>\n> >> The problem is that such a command cannot exist atm. because renames\n> >> don't exist, they are only interpreted. So the only way to achieve\n> >> this is to revert enough of the contents staged to the index such that\n> >> the rename is detected. The only way to do that in a foolproof manner\n> >> is reverting all the staged changes except the path so that the moved\n> >> file in the index is identical to the old file in HEAD.\n> > \n> > I agree recording renames explicitely might be a good addition to git, but the\n> > real question is how are they going to be stored in the object storage.\n> > \n> > My guess is that it can be added in the commit object after \"committer\", just\n> > add a \"renames\" field with all the renames, or one \"rename\" field per rename.\n> > It would be backwards compatible because any field can be added this way.\n> > \n> > How to generate these fields is a separate issue: first things first.\n> \n> The other end of the solution space is to try to find ways to make the\n> rename detection logic more accurate. We wouldn't need to store such a\n> rename if the detection gave the correct answer in the first place.\n\nWe can make it more accurate, but it will never be 100%. Sometimes being\nexplicit is the only way.\n\nCheers.\n\n-- \nFelipe Contreras"},{"id":"475968","messageId":"f5d21df1-2f52-8d19-4d2d-fa25ce9efbdc@game-point.net","threadId":"59636","inReplyTo":"xmqq8rehdq4m.fsf@gitster.g","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jeremy Morton","fromEmail":"admin@game-point.net","sentAt":"2023-04-24T20:05:29Z","receivedAt":"2023-04-24T20:05:43Z","isPatch":false,"sender":{"key":"admin@game-point.net","avatar":null},"body":"But if you were doing, say, a git blame for a file, you'd be able to \nsee the commits where its lines were actually last modified even \nthrough the rename, rather than a bunch of them being stopped at the \n\"added this file (because it wasn't detected as a rename)\" commit, no?\n\n-- \nBest regards,\nJeremy Morton (Jez)\n\nOn 24/04/2023 20:41, Junio C Hamano wrote:\n> Jeremy Morton <admin@game-point.net> writes:\n> \n>> The standard answer for this is to rename the file in one commit, then\n>> make the changes.\n> \n> Oh, by the way, this is a pure myth that would unlikely be helpful\n> in the bigger picture.\n> \n> When you rename and heavily modify the resulting new path because\n> you have to solve something, such a work would likely be done on the\n> same topic branch.  One step of it may be a pure rename, and other\n> steps may involve heavily changing the renamed result, or you may\n> update the contents in the original and the do a rename at the end,\n> but either way, when you integrate the end result of the whole topic\n> branch into the master history, what such a merge will see is that\n> the original file has disappeared and a new file with contents not\n> at all similar to the disappeared file has appeared.  \"pure rename\n> with changes in separate commits\" would have no effect when showing\n> such a history with \"git log --first-parent -p\" for a birds-eye\n> view.\n> \n> \n"},{"id":"476132","messageId":"c7bb292d-903b-692e-885b-524b6bb113ee@intel.com","threadId":"59636","inReplyTo":"6446d78fbbe82_cd61294e5@chronos.notmuch","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2023-04-26T19:08:26Z","receivedAt":"2023-04-26T19:08:43Z","isPatch":false,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"\n\nOn 4/24/2023 12:25 PM, Felipe Contreras wrote:\n> Erik Cervin Edin wrote:\n>> On Mon, Apr 24, 2023 at 1:17 PM Jeremy Morton <admin@game-point.net> wrote:\n>>>\n>>> There's no getting away from the fact that this adds a lot of (IMHO\n>>> unnecessary) work if you've already done a rename that git can't\n>>> detect and have both that and a bunch of other changes sitting in the\n>>> index.  What feels like it would be a natural resolution in these\n>>> cases, though, is a \"no, this remove/add is actually a rename\" command.\n>>\n>> It can definitely be both arduous and non-obvious how to deal with this.\n>>\n>> The problem is that such a command cannot exist atm. because renames\n>> don't exist, they are only interpreted. So the only way to achieve\n>> this is to revert enough of the contents staged to the index such that\n>> the rename is detected. The only way to do that in a foolproof manner\n>> is reverting all the staged changes except the path so that the moved\n>> file in the index is identical to the old file in HEAD.\n> \n> I agree recording renames explicitely might be a good addition to git, but the\n> real question is how are they going to be stored in the object storage.\n> \n> My guess is that it can be added in the commit object after \"committer\", just\n> add a \"renames\" field with all the renames, or one \"rename\" field per rename.\n> It would be backwards compatible because any field can be added this way.\n> \n> How to generate these fields is a separate issue: first things first.\n> \n\nI think such a renames field might work, but I know historically there\nwas a lot of resistance to \"baking in\" such rename logic because you\ncan't \"fix\" it later.\n\nI know there are some big threads from early days of git discussing\nthis, with many objections on baking in renames for various reasons.\n\nI think the argument can be made that there is still value in a commit\nwhich says \"I as the commiter know this is renaming the file, please\nshow it as such and track it as such\", and I think the other use cases\n(code moving from one file to another without a full rename, multiple\ncopies of a file getting deleted, etc) can be handled in other ways or\nwith an escape hatch to disable the commit rename indicator if necessary.\n\nIn the more complex cases where code is moved without a full rename,\nthere are tools for handling this such as pickaxe or the proposed magic\nblame tool that was brought up in the discussions against static renames\nbeing coded into the object storage. I think those are interesting but\nseparate problems from \"I am renaming this file and some of its contents\".\n\nAt commit basically is the only way this could be baked into the object\nstorage, since blobs don't store filenames and trees don't store any\nmethod of difference individually. The commit is the only place to\nreally do it.\n\nThe alternative would be something like Junio suggested where we have a\nseparate rename storage database which is computed ahead of time (kind\nof like commit graph storage) and which could be overridden manually.\nThis doesn't \"bake\" anything into the objects, but obviously requires\nmanually keeping up to date and adds some difficulty in sharing such\nupdates across remotes.\n\n\n"},{"id":"476144","messageId":"xmqqwn1yqsx7.fsf@gitster.g","threadId":"59636","inReplyTo":"c7bb292d-903b-692e-885b-524b6bb113ee@intel.com","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-04-26T20:39:48Z","receivedAt":"2023-04-26T20:39:56Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jacob Keller <jacob.e.keller@intel.com> writes:\n\n> The alternative would be something like Junio suggested where we have a\n> separate rename storage database which is computed ahead of time (kind\n> of like commit graph storage) and which could be overridden manually.\n> This doesn't \"bake\" anything into the objects, but obviously requires\n> manually keeping up to date and adds some difficulty in sharing such\n> updates across remotes.\n\nI think originally the recorded rename mechanism was dreamed up to\nbe a cache.  Unlike commit-graph that requires precomputation, it\nwould be populated incrementally when you run \"git log -M\" in a part\nof the history that you haven't done so.  Sharing it would just be\nas hard as sharing notes, once we point the rename cache with a ref,\nI would think.\n\nI cannot take credit for the idea, though.\n"},{"id":"477032","messageId":"CA+JQ7M_3jLCXHokbeHB=DyphFO605GE0BTu-cqZsF1ZNExL=kg@mail.gmail.com","threadId":"59636","inReplyTo":"xmqqwn1yqsx7.fsf@gitster.g","subject":"Re: Proposal: tell git a file has been renamed","fromName":"Erik Cervin Edin","fromEmail":"erik@cervined.in","sentAt":"2023-05-11T13:44:32Z","receivedAt":"2023-05-11T13:45:34Z","isPatch":false,"sender":{"key":"erik@cervined.in","avatar":null},"body":"Another example of where the current implementation isn't working great\n\n  A - B - C\n\ncommit A makes changes to foo\ncommit B changes the name of foo to bar\ncommit C symlinks foo => bar\n\nRebasing the commits and reordering them\n\n  commit B changes the name of foo to bar\n  commit C symlinks foo => bar\n  commit A makes changes to foo\n\nis going to result in merge conflicts. The best way to achieve this\nordering is actually doing multiple rebases.\n\n  commit B changes the name of foo to bar\n  commit A makes changes to foo\n  commit C symlinks foo => bar\n\nfollowed by\n\n  commit B changes the name of foo to bar\n  commit C symlinks foo => bar\n  commit A makes changes to foo\n\nI guess the difficulty that arises from reordering commits like this\nisn't unique to renames but it arguably results in a more hostile user\nexperience. It requires an unusual amount of discipline and\nunderstanding of what is going on to resolve as well as how to avoid\nit.\n"}]}