{"thread":{"id":"64516","subject":"Feature request: git cp","startedAt":"2025-11-20T14:57:00Z","lastAt":"2025-11-21T21:52:30Z","messageCount":10,"participants":["Martin Guy","Kristoffer Haugsbakk","D. Ben Knoble","Lucas Seiki Oshiro","rsbecker@nexbridge.com"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"531057","messageId":"CAL4-wQrgD3nnW2BfNf6e9d7tDANE60dYBRRP_0FW3Z-LvQrZmg@mail.gmail.com","threadId":"64516","inReplyTo":null,"subject":"Feature request: git cp","fromName":"Martin Guy","fromEmail":"martinwguy@gmail.com","sentAt":"2025-11-20T14:56:47Z","receivedAt":"2025-11-20T14:57:00Z","isPatch":false,"sender":{"key":"martinwguy@gmail.com","avatar":"https://gravatar.com/avatar/702a80021885e76563919dd1674bfa4dac9d9ec1eab3ab45da95ebce83346505?d=mp&s=160"},"body":"I am splitting a large source file into three smaller ones (mp3.c into\nmad.c, lame.c and twolame.c)\nand would like the history to track the relevant lines in each file,\nlike \"git mv\" does,\nbut I only seem able to do this with one file by \"git mv\"ing it and\ncopying that to the other\nas a new file.\n\nSo what I'd like is \"git cp\" that is like \"git mv\" but where blame for\nboth the resulting files\ngoes back the original one, if that's possible and unless there's a\nway to achieve the same\neffect that I haven't figured out.\n\nA fairly rare thing to wish to do, but may be useful in this case.\n\n    M\n"},{"id":"531061","messageId":"0e971281-d1c4-4030-9297-f5e2c0765431@app.fastmail.com","threadId":"64516","inReplyTo":"CAL4-wQrgD3nnW2BfNf6e9d7tDANE60dYBRRP_0FW3Z-LvQrZmg@mail.gmail.com","subject":"Re: Feature request: git cp","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2025-11-20T15:17:33Z","receivedAt":"2025-11-20T15:17:55Z","isPatch":false,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Thu, Nov 20, 2025, at 15:56, Martin Guy wrote:\n> I am splitting a large source file into three smaller ones (mp3.c into\n> mad.c, lame.c and twolame.c)\n> and would like the history to track the relevant lines in each file,\n> like \"git mv\" does,\n> but I only seem able to do this with one file by \"git mv\"ing it and\n> copying that to the other\n> as a new file.\n>\n> So what I'd like is \"git cp\" that is like \"git mv\" but where blame for\n> both the resulting files\n> goes back the original one, if that's possible and unless there's a\n> way to achieve the same\n> effect that I haven't figured out.\n>\n> A fairly rare thing to wish to do, but may be useful in this case.\n\nCopies and file moves are detected dynamically when you use things like\n`git log`.\n\nTry `git log --stat --find-copies-harder`.  I get this output after copying a file three times.\n\n     README.md => rm1.md | 0\n     README.md => rm2.md | 0\n     README.md => rm3.md | 0\n     3 files changed, 0 insertions(+), 0 deletions(-)\n\nI get this output when I change one of the lines in the same commit on one of the files.\n\n     README.md => rm1.md | 2 +-\n     README.md => rm2.md | 0\n     README.md => rm3.md | 0\n     3 files changed, 1 insertion(+), 1 deletion(-)\n\nThis is the first time I’ve tried this option so I don’t know\nmore about it.\n"},{"id":"531065","messageId":"CALnO6CDBQWXSvJeXOtVYdM83vibuqDbvjAXn6WfpgsAp_Ky+xg@mail.gmail.com","threadId":"64516","inReplyTo":"0e971281-d1c4-4030-9297-f5e2c0765431@app.fastmail.com","subject":"Re: Feature request: git cp","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-11-20T16:28:17Z","receivedAt":"2025-11-20T16:28:31Z","isPatch":false,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Thu, Nov 20, 2025 at 10:34 AM Kristoffer Haugsbakk\n<kristofferhaugsbakk@fastmail.com> wrote:\n>\n> On Thu, Nov 20, 2025, at 15:56, Martin Guy wrote:\n> > I am splitting a large source file into three smaller ones (mp3.c into\n> > mad.c, lame.c and twolame.c)\n> > and would like the history to track the relevant lines in each file,\n> > like \"git mv\" does,\n> > but I only seem able to do this with one file by \"git mv\"ing it and\n> > copying that to the other\n> > as a new file.\n> >\n> > So what I'd like is \"git cp\" that is like \"git mv\" but where blame for\n> > both the resulting files\n> > goes back the original one, if that's possible and unless there's a\n> > way to achieve the same\n> > effect that I haven't figured out.\n> >\n> > A fairly rare thing to wish to do, but may be useful in this case.\n>\n> Copies and file moves are detected dynamically when you use things like\n> `git log`.\n>\n> Try `git log --stat --find-copies-harder`.  I get this output after copying a file three times.\n>\n>      README.md => rm1.md | 0\n>      README.md => rm2.md | 0\n>      README.md => rm3.md | 0\n>      3 files changed, 0 insertions(+), 0 deletions(-)\n>\n> I get this output when I change one of the lines in the same commit on one of the files.\n>\n>      README.md => rm1.md | 2 +-\n>      README.md => rm2.md | 0\n>      README.md => rm3.md | 0\n>      3 files changed, 1 insertion(+), 1 deletion(-)\n>\n> This is the first time I’ve tried this option so I don’t know\n> more about it.\n\nSee also https://lore.kernel.org/git/20240311213928.1872437-1-sam@gentoo.org/\nand related threads (Gentoo's Git still comes with these patches for\nebuild developers).\n\n-- \nD. Ben Knoble\n"},{"id":"531082","messageId":"CAL4-wQpeYc8-FfcZGWcs6KmR-oswTs3Kjcc7xAb34cFX7s0c-A@mail.gmail.com","threadId":"64516","inReplyTo":"0e971281-d1c4-4030-9297-f5e2c0765431@app.fastmail.com","subject":"Re: Feature request: git cp","fromName":"Martin Guy","fromEmail":"martinwguy@gmail.com","sentAt":"2025-11-20T21:24:03Z","receivedAt":"2025-11-20T21:24:17Z","isPatch":false,"sender":{"key":"martinwguy@gmail.com","avatar":"https://gravatar.com/avatar/702a80021885e76563919dd1674bfa4dac9d9ec1eab3ab45da95ebce83346505?d=mp&s=160"},"body":"Thanks, but that only seems to affect \"git log\" retroactively, whereas\nI'm interested in it being part of the history so that \"git blame\"\nknows about it. At present, the blame for a line would end at the time\nof the split (when the file appears to have been created ex novo)\nthough I suppose people would end up at that break and could then\nswitch to tracking the old file instead.\n\nMaybe I'm expecting too much of git, with all the truly wonderful\nthings it does already, but the idea seems to fit into the current\nscheme of things as seen from the outside (I don't know how the \"git\nmv\" line-based trackback works).\n\n    M\n\nOn Thu, 20 Nov 2025 at 16:17, Kristoffer Haugsbakk\n<kristofferhaugsbakk@fastmail.com> wrote:\n>\n> On Thu, Nov 20, 2025, at 15:56, Martin Guy wrote:\n> > I am splitting a large source file into three smaller ones (mp3.c into\n> > mad.c, lame.c and twolame.c)\n> > and would like the history to track the relevant lines in each file,\n> > like \"git mv\" does,\n> > but I only seem able to do this with one file by \"git mv\"ing it and\n> > copying that to the other\n> > as a new file.\n> >\n> > So what I'd like is \"git cp\" that is like \"git mv\" but where blame for\n> > both the resulting files\n> > goes back the original one, if that's possible and unless there's a\n> > way to achieve the same\n> > effect that I haven't figured out.\n> >\n> > A fairly rare thing to wish to do, but may be useful in this case.\n>\n> Copies and file moves are detected dynamically when you use things like\n> `git log`.\n>\n> Try `git log --stat --find-copies-harder`.  I get this output after copying a file three times.\n>\n>      README.md => rm1.md | 0\n>      README.md => rm2.md | 0\n>      README.md => rm3.md | 0\n>      3 files changed, 0 insertions(+), 0 deletions(-)\n>\n> I get this output when I change one of the lines in the same commit on one of the files.\n>\n>      README.md => rm1.md | 2 +-\n>      README.md => rm2.md | 0\n>      README.md => rm3.md | 0\n>      3 files changed, 1 insertion(+), 1 deletion(-)\n>\n> This is the first time I’ve tried this option so I don’t know\n> more about it.\n"},{"id":"531086","messageId":"CALnO6CDpBpRdbpXy26v5ug5n5opqzn-Uos+Qr=jx9mA-5wR9Ag@mail.gmail.com","threadId":"64516","inReplyTo":"CAL4-wQpeYc8-FfcZGWcs6KmR-oswTs3Kjcc7xAb34cFX7s0c-A@mail.gmail.com","subject":"Re: Feature request: git cp","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-11-20T22:10:48Z","receivedAt":"2025-11-20T22:11:00Z","isPatch":false,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Thu, Nov 20, 2025 at 4:24 PM Martin Guy <martinwguy@gmail.com> wrote:\n>\n> Thanks, but that only seems to affect \"git log\" retroactively, whereas\n> I'm interested in it being part of the history so that \"git blame\"\n> knows about it. At present, the blame for a line would end at the time\n> of the split (when the file appears to have been created ex novo)\n> though I suppose people would end up at that break and could then\n> switch to tracking the old file instead.\n>\n> Maybe I'm expecting too much of git, with all the truly wonderful\n> things it does already, but the idea seems to fit into the current\n> scheme of things as seen from the outside (I don't know how the \"git\n> mv\" line-based trackback works).\n>\n>     M\n>\n\nPlease avoid top-posting ;)\n\n\"git mv\" doesn't track the movement; Git reconstructs it post-hoc. See\n[1]; while the tone obviously leaves a lot to be desired, the\ntechnical rationale has stuck.\n\n[1]: https://lore.kernel.org/git/Pine.LNX.4.58.0504150753440.7211@ppc970.osdl.org/\n\n\n-- \nD. Ben Knoble\n"},{"id":"531093","messageId":"6F4B3935-7F2F-43C9-8E5E-12E2FB3331BD@gmail.com","threadId":"64516","inReplyTo":"CAL4-wQrgD3nnW2BfNf6e9d7tDANE60dYBRRP_0FW3Z-LvQrZmg@mail.gmail.com","subject":"Re: Feature request: git cp","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2025-11-20T23:07:43Z","receivedAt":"2025-11-20T23:07:57Z","isPatch":false,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"Hi, Martin!\n\n> and would like the history to track the relevant lines in each file,\n> like \"git mv\" does,\n\nAs a consequence of Git being based on snapshots instead of\ndeltas (see [1]), `git mv` actually doesn't keep track of\nrenames. You can think of `git mv` as `git rm`ing the file\nwith the old name + `git add`ing the same file with the the\nnew name.\n\nAs Kristoffer said, the renames are detected by tools like \n`git log`, `git diff` or `git status` based on similarity \nbetween files, which are considered a rename if they are\nsimilar enough. That similarity can even be tuned by using\nthe flag --find-renames, available in those three commands.\n\n\n[1] https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F\n"},{"id":"531096","messageId":"CAL4-wQqH2=68MJ7o0aU9hJ2bgYY1G=xWvgEjpVz9QvTPWMgSsw@mail.gmail.com","threadId":"64516","inReplyTo":"6F4B3935-7F2F-43C9-8E5E-12E2FB3331BD@gmail.com","subject":"Re: Feature request: git cp","fromName":"Martin Guy","fromEmail":"martinwguy@gmail.com","sentAt":"2025-11-20T23:17:51Z","receivedAt":"2025-11-20T23:18:05Z","isPatch":false,"sender":{"key":"martinwguy@gmail.com","avatar":"https://gravatar.com/avatar/702a80021885e76563919dd1674bfa4dac9d9ec1eab3ab45da95ebce83346505?d=mp&s=160"},"body":"Many thanks. So it should notice anyway! Wow.\n\nBlessings\n\n   M\n"},{"id":"531098","messageId":"010b01dc5a7b$4790ee30$d6b2ca90$@nexbridge.com","threadId":"64516","inReplyTo":"6F4B3935-7F2F-43C9-8E5E-12E2FB3331BD@gmail.com","subject":"RE: Feature request: git cp","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2025-11-21T00:10:38Z","receivedAt":"2025-11-21T00:10:53Z","isPatch":false,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On November 20, 2025 6:08 PM, Lucas Seiki wrote:\n>> and would like the history to track the relevant lines in each file,\n>> like \"git mv\" does,\n>\n>As a consequence of Git being based on snapshots instead of deltas (see\n[1]), `git\n>mv` actually doesn't keep track of renames. You can think of `git mv` as\n`git rm`ing\n>the file with the old name + `git add`ing the same file with the the new\nname.\n>\n>As Kristoffer said, the renames are detected by tools like `git log`, `git\ndiff` or `git\n>status` based on similarity between files, which are considered a rename if\nthey are\n>similar enough. That similarity can even be tuned by using the flag\n--find-renames,\n>available in those three commands.\n>\n>\n>[1] https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F\n\nI know this might sound trite or wrong but... does this mean that git log\ncan actually detect SHA-1 collisions based on similarity checks of file\ncontents?\n\n"},{"id":"531145","messageId":"CAL4-wQra+7HOJ6_qNy+4_tvz7=KApW7yb7BNE6B86JnowschXg@mail.gmail.com","threadId":"64516","inReplyTo":"010b01dc5a7b$4790ee30$d6b2ca90$@nexbridge.com","subject":"Re: Feature request: git cp","fromName":"Martin Guy","fromEmail":"martinwguy@gmail.com","sentAt":"2025-11-21T14:32:41Z","receivedAt":"2025-11-21T14:32:55Z","isPatch":false,"sender":{"key":"martinwguy@gmail.com","avatar":"https://gravatar.com/avatar/702a80021885e76563919dd1674bfa4dac9d9ec1eab3ab45da95ebce83346505?d=mp&s=160"},"body":"On Fri, 21 Nov 2025 at 01:10, <rsbecker@nexbridge.com> wrote:\n>\n> On November 20, 2025 6:08 PM, Lucas Seiki wrote:\n>\n> I know this might sound trite or wrong but... does this mean that git log\n> can actually detect SHA-1 collisions based on similarity checks of file\n> contents?\n\nIf a git mv is no more than a git rm and a git add then yes.\nIf i understand correctly from Linus' fabulous rant, that it does\nline matching retrospectively always, so not only will it notice\nthe split of mp3.c but will also notice that the functions in mp3-util.h\none of which only mad used and one of which only lame used,\nhave jumped to their new files and mp3-util.h purged.\n\nStaggering\n\nMy only regret with git is that it's line-based instead of word-based\nas that would see a change from < limit to <= limit as one symbol\nchange, allowing semantic analysis of program changes but\nif it's all retrospective anyway, the line-based change analysis\ncould gain a word-based mode.\n\n   M\n"},{"id":"531155","messageId":"6D0DEC5C-0912-4D48-A108-3E0D1B2017D7@gmail.com","threadId":"64516","inReplyTo":"CAL4-wQra+7HOJ6_qNy+4_tvz7=KApW7yb7BNE6B86JnowschXg@mail.gmail.com","subject":"Re: Feature request: git cp","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2025-11-21T21:52:15Z","receivedAt":"2025-11-21T21:52:30Z","isPatch":false,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"\n> My only regret with git is that it's line-based instead of word-based\n> as that would see a change from < limit to <= limit as one symbol\n> change, allowing semantic analysis of program changes but\n> if it's all retrospective anyway, the line-based change analysis\n> could gain a word-based mode.\n\nAgain, since Git is based on snapshots instead of deltas, actually\nit doesn't really matter. Git doesn't store diffs (deltas), they\nare only computed when using `git diff`, `git show` and `git log`.\nIf you want the diff based on words instead of lines, you can use\nthe flag --word-diff in those three commands.\n\nAnd, again, since Git is based on snapshots, if one wants a more\nsemantic diff, they can use the snapshots of two commits and them\ngenerate the diff the way they want. One example of that (and one\nthat I use a lot) is git-latexdiff [1].\n\n[1] https://gitlab.com/git-latexdiff/git-latexdiff\n\n"}]}