16

I'm trying to place into git's history successive snapshots of a specific project. I am doing this by populating the repository directory with the contents of each snapshot and then running

git add -A .
git commit -m 'Version X'

This is the method recommended in this answer. However, I see that the commit recognizes file renames only when 100% of the file contents remain the same. Is there a way to influence rename detection of git commit to make it find renames where the file contents have changed a bit? I see that git merge and git diff have various options for controlling the rename threshold, but these options do not exist for git commit.

Things I have tried:

  • Locating the renamed files with a home-brew script, and performing a commit with the original files renamed to their new locations before committing the new file contents. However, this introduces an artificial commit, and seems inelegant, because it doesn't use git's rename detection functionality.
  • Creating a separate branch for each snapshot and then merging the successive branches onto master using

    git merge -s recursive -Xtheirs -Xpatience -Xrename-threshold=20

    However, this left me with the renamed files of the old version in place, while also failing to detect the renames.

Community
  • 1
  • 1
Diomidis Spinellis
  • 18,734
  • 5
  • 61
  • 83
  • 2
    Does it matter? Setting such an option in `git commit` would only influence that commands' UI; Git does not actually track renames. – Fred Foo Feb 12 '13 at 12:51
  • 1
    I would like `git log --follow` to work across the renames. With a plain sequence of commits it stops at the most recent version of the file. – Diomidis Spinellis Feb 12 '13 at 13:08

2 Answers2

15

git commit never detects renames. It just writes content to the repository. Renames (and copies as well) are only detected after the fact, i.e. when running git diff, git merge and friends. That's because git does not store any rename/copy information.

Michael Wild
  • 24,977
  • 3
  • 43
  • 43
  • 4
    The output of `git commit` indicates whether some files have been renamed or not. I've seen that when this output indicates a rename I can follow back the file's history with `git log --follow`. This is what I whish to accomplish. – Diomidis Spinellis Feb 12 '13 at 13:10
  • 1
    But that information is *not stored*, so it doesn't make sense for `git-commit` to have such an option. – Michael Wild Feb 12 '13 at 13:17
  • 1
    I was sidetracked by the fact that a commit with the same content in the new location seems to improve the heuristics used by `git log --follow`. – Diomidis Spinellis Feb 12 '13 at 13:29
  • 1
    That's a pattern I try to follow: Make the rename and the modification two separate commits. This dramatically improves rename-detection and in my experience also helps with merge conflicts. – Michael Wild Feb 12 '13 at 14:16
  • 1
    If git does not store any rename/copy information as the answer implies, so what does git mv command do?! – smohadjer May 09 '18 at 06:51
  • 1
    It is the equivalent of `git rm --cached` followed by `git add`. – Michael Wild May 10 '18 at 09:29
15

As indicated in comments and another answer, it doesn't make sense to adjust the rename detection threshold in the commit, because this would only change the command's output, not what's actually stored in the commit.

What you can do however, is adjust the rename detection threshold in the git log command. You do this by using the --find-renames parameter. This mostly accomplishes the result I wanted to achieve.

Diomidis Spinellis
  • 18,734
  • 5
  • 61
  • 83
  • 3
    git log --find-renames just shows me the commit log. I know that I need to change the copy / rename threshold percentage but I haven't seen any direct syntax examples. Can you be just slightly more specific? – fIwJlxSzApHEZIl Nov 12 '14 at 00:52
  • The --find-renames changes the threshold. I don't know of options that provide you greater control. – Diomidis Spinellis Nov 13 '14 at 07:12
  • I found more about my exact issue. I make a ton of changes to my code over the course of a day. Including things like file adds and deletes. I then run git add *.java to add all my changes to the current changelist. And git incorrectly assumes that some files are renames which none of them are. To get around this I have to git add the files which are incorrectly assumed to be renames to an exclusive changelist, commit those, and then do another commit with all the other files. So I was hoping to change the find-renames threshold but can't find it for the git add command – fIwJlxSzApHEZIl Nov 19 '14 at 20:36
  • 6
    @anon58192932 `--find-renames` (or `-M`) takes an optional threshold param as well: https://git-scm.com/docs/git-diff. For example, `-M90%` means Git should consider a delete/add pair to be a rename if more than 90% of the file is unchanged. – Kevin Cooper Jan 31 '17 at 16:28
  • 1
    that's awesome thanks @KevinCooper - amazingly still helpful 1.5 years later. – fIwJlxSzApHEZIl Feb 08 '17 at 19:14