Home > OS >  git: rename file and create file with old name in same commit
git: rename file and create file with old name in same commit

Time:06-15

In my experience, when I rename a file, git will detect the rename on my next commit. However, now I want to rename a file, say from old_name to new_name, and in the same commit, I want to create a new file named old_name. Since a (different) file named old_name exists, git is not automatically detecting that this is, in fact, a rename. Is there a way to force git to detect this rename?

So far, I have not been using git mv because I hear it is almost the same as renaming via any ordinary method, but would this help in my situation?

I can see that git is not detecting the rename by running commit -a --dry-run; it lists it as a new file and a modified file.

Even if I am able to force the commit to detect the rename, will this cause any issues down the road when I try to track code across renames e.g. via git log --follow?

CodePudding user response:

There isn't really any such thing as a rename in Git. Git knows nothing of the concept of renaming a file. No information about any such thing is built into a commit or anywhere else. The use of git mv is totally irrelevant to the matter.

What Git does do is try to be helpful to you, the human, when doing a diff between two commits, by noticing if two files with different pathnames seem to be "the same file" — that is, a file is deleted and a file is created, and they seem to have very similar contents.

So if you want to help Git help you, make a commit consisting entirely of renaming the file. Then make another commit where you create a new file with the old name. Thus when Git walks the parent chain, one commit at a time, it will stand a better chance of drawing the "right" conclusion at every step.

In general, however, you should not count on this behavior on the part of Git.

Here's an example, where I renamed a to c in one commit, and then created a new a in another commit. I'll show excerpts of the log listing so that you can see what Git thinks happened in each commit:

% git log -p

diff --git a/a b/a
new file mode 100644
index 0000000..b680253
--- /dev/null
    b/a

diff --git a/a b/c
similarity index 100%
rename from a
rename to c

diff --git a/b b/b
new file mode 100644
index 0000000..6178079
--- /dev/null
    b/b

diff --git a/a b/a
new file mode 100644
index 0000000..7898192
--- /dev/null
    b/a

As you can see, reading backwards, Git thinks I performed the following steps:

  1. Create a.
  2. Create b.
  3. Rename a to c.
  4. Create a.

And that is exactly what I think I did too, so Git is "helpful" in the desired way here.

  • Related