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:
- Create
a
. - Create
b
. - Rename
a
toc
. - Create
a
.
And that is exactly what I think I did too, so Git is "helpful" in the desired way here.