threads / discuss / 64516

Feature request: git cp

Subject: Feature request: git cp

## tl;dr

10 messages between Nov 20, 2025 and Nov 21, 2025.

replies: 9people: 5as markdown or json

Martin Guy· Nov 20, 2025, 14:56 UTC · lore

I am splitting a large source file into three smaller ones (mp3.c into mad.c, lame.c and twolame.c) and would like the history to track the relevant lines in each file, like "git mv" does, but I only seem able to do this with one file by "git mv"ing it and copying that to the other as a new file.

So what I'd like is "git cp" that is like "git mv" but where blame for both the resulting files goes back the original one, if that's possible and unless there's a way to achieve the same effect that I haven't figured out.

A fairly rare thing to wish to do, but may be useful in this case.
    M
Kristoffer Haugsbakk· Nov 20, 2025, 15:17 UTC · re: Martin Guy · lore

Re: Feature request: git cp

On Thu, Nov 20, 2025, at 15:56, Martin Guy wrote:
Show 15 quoted lines
> I am splitting a large source file into three smaller ones (mp3.c into
> mad.c, lame.c and twolame.c)
> and would like the history to track the relevant lines in each file,
> like "git mv" does,
> but I only seem able to do this with one file by "git mv"ing it and
> copying that to the other
> as a new file.
>
> So what I'd like is "git cp" that is like "git mv" but where blame for
> both the resulting files
> goes back the original one, if that's possible and unless there's a
> way to achieve the same
> effect that I haven't figured out.
>
> A fairly rare thing to wish to do, but may be useful in this case.

Copies and file moves are detected dynamically when you use things like `git log`.

Try `git log --stat --find-copies-harder`.  I get this output after copying a file three times.
     README.md => rm1.md | 0
     README.md => rm2.md | 0
     README.md => rm3.md | 0
     3 files changed, 0 insertions(+), 0 deletions(-)
I get this output when I change one of the lines in the same commit on one of the files.
     README.md => rm1.md | 2 +-
     README.md => rm2.md | 0
     README.md => rm3.md | 0
     3 files changed, 1 insertion(+), 1 deletion(-)

This is the first time I’ve tried this option so I don’t know more about it.

D. Ben Knoble· Nov 20, 2025, 16:28 UTC · re: Kristoffer Haugsbakk · lore

Re: Feature request: git cp

On Thu, Nov 20, 2025 at 10:34 AM Kristoffer Haugsbakk <kristofferhaugsbakk@fastmail.com> wrote:

Show 37 quoted lines
>
> On Thu, Nov 20, 2025, at 15:56, Martin Guy wrote:
> > I am splitting a large source file into three smaller ones (mp3.c into
> > mad.c, lame.c and twolame.c)
> > and would like the history to track the relevant lines in each file,
> > like "git mv" does,
> > but I only seem able to do this with one file by "git mv"ing it and
> > copying that to the other
> > as a new file.
> >
> > So what I'd like is "git cp" that is like "git mv" but where blame for
> > both the resulting files
> > goes back the original one, if that's possible and unless there's a
> > way to achieve the same
> > effect that I haven't figured out.
> >
> > A fairly rare thing to wish to do, but may be useful in this case.
>
> Copies and file moves are detected dynamically when you use things like
> `git log`.
>
> Try `git log --stat --find-copies-harder`.  I get this output after copying a file three times.
>
>      README.md => rm1.md | 0
>      README.md => rm2.md | 0
>      README.md => rm3.md | 0
>      3 files changed, 0 insertions(+), 0 deletions(-)
>
> I get this output when I change one of the lines in the same commit on one of the files.
>
>      README.md => rm1.md | 2 +-
>      README.md => rm2.md | 0
>      README.md => rm3.md | 0
>      3 files changed, 1 insertion(+), 1 deletion(-)
>
> This is the first time I’ve tried this option so I don’t know
> more about it.

See also https://lore.kernel.org/git/20240311213928.1872437-1-sam@gentoo.org/ and related threads (Gentoo's Git still comes with these patches for ebuild developers).

-- 
D. Ben Knoble
Martin Guy· Nov 20, 2025, 21:24 UTC · re: Kristoffer Haugsbakk · lore

Re: Feature request: git cp

Thanks, but that only seems to affect "git log" retroactively, whereas I'm interested in it being part of the history so that "git blame" knows about it. At present, the blame for a line would end at the time of the split (when the file appears to have been created ex novo) though I suppose people would end up at that break and could then switch to tracking the old file instead.

Maybe I'm expecting too much of git, with all the truly wonderful things it does already, but the idea seems to fit into the current scheme of things as seen from the outside (I don't know how the "git mv" line-based trackback works).

    M

On Thu, 20 Nov 2025 at 16:17, Kristoffer Haugsbakk <kristofferhaugsbakk@fastmail.com> wrote:

Show 37 quoted lines
>
> On Thu, Nov 20, 2025, at 15:56, Martin Guy wrote:
> > I am splitting a large source file into three smaller ones (mp3.c into
> > mad.c, lame.c and twolame.c)
> > and would like the history to track the relevant lines in each file,
> > like "git mv" does,
> > but I only seem able to do this with one file by "git mv"ing it and
> > copying that to the other
> > as a new file.
> >
> > So what I'd like is "git cp" that is like "git mv" but where blame for
> > both the resulting files
> > goes back the original one, if that's possible and unless there's a
> > way to achieve the same
> > effect that I haven't figured out.
> >
> > A fairly rare thing to wish to do, but may be useful in this case.
>
> Copies and file moves are detected dynamically when you use things like
> `git log`.
>
> Try `git log --stat --find-copies-harder`.  I get this output after copying a file three times.
>
>      README.md => rm1.md | 0
>      README.md => rm2.md | 0
>      README.md => rm3.md | 0
>      3 files changed, 0 insertions(+), 0 deletions(-)
>
> I get this output when I change one of the lines in the same commit on one of the files.
>
>      README.md => rm1.md | 2 +-
>      README.md => rm2.md | 0
>      README.md => rm3.md | 0
>      3 files changed, 1 insertion(+), 1 deletion(-)
>
> This is the first time I’ve tried this option so I don’t know
> more about it.
D. Ben Knoble· Nov 20, 2025, 22:10 UTC · re: Martin Guy · lore

Re: Feature request: git cp

On Thu, Nov 20, 2025 at 4:24 PM Martin Guy <martinwguy@gmail.com> wrote:
Show 15 quoted lines
>
> Thanks, but that only seems to affect "git log" retroactively, whereas
> I'm interested in it being part of the history so that "git blame"
> knows about it. At present, the blame for a line would end at the time
> of the split (when the file appears to have been created ex novo)
> though I suppose people would end up at that break and could then
> switch to tracking the old file instead.
>
> Maybe I'm expecting too much of git, with all the truly wonderful
> things it does already, but the idea seems to fit into the current
> scheme of things as seen from the outside (I don't know how the "git
> mv" line-based trackback works).
>
>     M
>
Please avoid top-posting ;)

"git mv" doesn't track the movement; Git reconstructs it post-hoc. See [1]; while the tone obviously leaves a lot to be desired, the technical rationale has stuck.

[1]: https://lore.kernel.org/git/Pine.LNX.4.58.0504150753440.7211@ppc970.osdl.org/
-- 
D. Ben Knoble
Lucas Seiki Oshiro· Nov 20, 2025, 23:07 UTC · re: Martin Guy · lore

Re: Feature request: git cp

Hi, Martin!
> and would like the history to track the relevant lines in each file,
> like "git mv" does,

As a consequence of Git being based on snapshots instead of deltas (see [1]), `git mv` actually doesn't keep track of renames. You can think of `git mv` as `git rm`ing the file with the old name + `git add`ing the same file with the the new name.

As Kristoffer said, the renames are detected by tools like `git log`, `git diff` or `git status` based on similarity between files, which are considered a rename if they are similar enough. That similarity can even be tuned by using the flag --find-renames, available in those three commands.

[1] https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F
rsbecker@nexbridge.com· Nov 21, 2025, 00:10 UTC · re: Lucas Seiki Oshiro · lore

RE: Feature request: git cp

On November 20, 2025 6:08 PM, Lucas Seiki wrote:
>> and would like the history to track the relevant lines in each file,
>> like "git mv" does,
>
>As a consequence of Git being based on snapshots instead of deltas (see
[1]), `git
>mv` actually doesn't keep track of renames. You can think of `git mv` as
`git rm`ing
>the file with the old name + `git add`ing the same file with the the new
name.
>
>As Kristoffer said, the renames are detected by tools like `git log`, `git
diff` or `git
>status` based on similarity between files, which are considered a rename if
they are
>similar enough. That similarity can even be tuned by using the flag
--find-renames,
>available in those three commands.
>
>
>[1] https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F

I know this might sound trite or wrong but... does this mean that git log can actually detect SHA-1 collisions based on similarity checks of file contents?

Martin Guy· Nov 21, 2025, 14:32 UTC · re: rsbecker@nexbridge.com · lore

Re: Feature request: git cp

On Fri, 21 Nov 2025 at 01:10, <rsbecker@nexbridge.com> wrote:
Show 6 quoted lines
>
> On November 20, 2025 6:08 PM, Lucas Seiki wrote:
>
> I know this might sound trite or wrong but... does this mean that git log
> can actually detect SHA-1 collisions based on similarity checks of file
> contents?

If a git mv is no more than a git rm and a git add then yes. If i understand correctly from Linus' fabulous rant, that it does line matching retrospectively always, so not only will it notice the split of mp3.c but will also notice that the functions in mp3-util.h one of which only mad used and one of which only lame used, have jumped to their new files and mp3-util.h purged.

Staggering

My only regret with git is that it's line-based instead of word-based as that would see a change from < limit to <= limit as one symbol change, allowing semantic analysis of program changes but if it's all retrospective anyway, the line-based change analysis could gain a word-based mode.

   M
Lucas Seiki Oshiro· Nov 21, 2025, 21:52 UTC · re: Martin Guy · lore

Re: Feature request: git cp

Show 5 quoted lines
> My only regret with git is that it's line-based instead of word-based
> as that would see a change from < limit to <= limit as one symbol
> change, allowing semantic analysis of program changes but
> if it's all retrospective anyway, the line-based change analysis
> could gain a word-based mode.

Again, since Git is based on snapshots instead of deltas, actually it doesn't really matter. Git doesn't store diffs (deltas), they are only computed when using `git diff`, `git show` and `git log`. If you want the diff based on words instead of lines, you can use the flag --word-diff in those three commands.

And, again, since Git is based on snapshots, if one wants a more semantic diff, they can use the snapshots of two commits and them generate the diff the way they want. One example of that (and one that I use a lot) is git-latexdiff [1].

[1] https://gitlab.com/git-latexdiff/git-latexdiff

← back to recent threads