Richard
Richard

Reputation: 65550

Commit a renamed and edited file in git, reliably, in a single commit?

I have both renamed and moved a file in git. I took the bar.js file, edited the contents extensively, and moved it across directories.

This is what git status is showing me:

$ git status

On branch feature/bar-chart
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

deleted:    js/journey-graph/bar.js

Untracked files:
(use "git add <file>..." to include in what will be committed)

js/bar-chart/bar.js

I'd like to make a single commit that encompasses both the rename and the editing, and preserves the history attached to the file.

Is this possible with git?

Please note: I don't want to rely on git spotting automatically that the files are similar, and guessing that they have been renamed rather than manually added and deleted. I want to tell git exactly what has happened. (This is because I actually have quite a few edited files, and I'm nervous about git getting them confused.)

Upvotes: 0

Views: 51

Answers (2)

vonbrand
vonbrand

Reputation: 11831

You can go

git mv file newname    # Rename
edit, edit, edit, ...  # Mangle
git add newname        # Make *sure* the last version gets saved
git commit             # Away we go

No changes are really recorded until the commit. And git mv does exactky the same as deleting the old file and creating a new one with the same contents, as far as git cares. How the contents moved from one place to the other is none of git's concern.

Upvotes: 1

torek
torek

Reputation: 489073

Git commit does not care about renames.

Commit simply writes a commit that records the complete state of a work-tree (plus the usual other commit data). "The state of a work tree" never has any renaming in it. It just has files. File a.js exists, or does not. File b.js exists, or does not.

Renaming comes in when (and only when) you ask git to compare two trees. You can, for instance, ask git to compare "tree in latest commit" with "tree in working directory". That's what git status does.

You can also ask git to compare the trees of two different commits:

git diff HEAD~7 HEAD~2  # what changed between "7 commits ago" and "2 ago"

and git diff takes options—-M, -C, and so on—that let you control how aggressive git gets in terms of rename and copy detection. The git status command has no options for this; its rename-detector is permanently set to a moderate level.

The key point, though, is all this happens when you run the other commands: git commit simply records a tree, and it's later (and earlier!), with other git commands, that git attempts to figure out whether things were renamed and/or copied.

Upvotes: 1

Related Questions