Git merge moved files

I unlocked the repo and modified file A. Now file A in the upstream repo has moved to a subdirectory. I am trying to combine an upward repo on my fork.

Git believes that file A was deleted at its original location and a new new one was created in a new auxiliary directory (this could also be due to the fact that they moved the file upstream).

I want to get my changes to this file in a new place with the least possible consequences, a history of commits, etc. wrt Can someone help me with ways to achieve this?

+5
source share
2 answers

Git always detects post-fact renames by comparing the two trees (or one tree and index, for cases that do not include git merge ). (Linus Torvalds considers this feature, for example, this question is SO) .

In any case, git merge will run git internal diff with merge detection enabled and the default value of 50% unless you configure it differently. 1 Similarly, git diff has some default values ​​that are also configurable. If you run git diff --find-renames -M50% manually between the merge base and the upstream, you are probably fine (but see Footnote 1 on tuning).

If git does not detect renaming, you may need to set renaming thresholds and / or increase the number of files that git needs to consider. The first one is the rename-threshold value in the -X options ( rename-threshold first appeared in git 1.7.4). See the documentation for more details.


1 You can set merge.renameLimit number of files to consider in terms of renaming detection. If you do not install it, the current default value is 1000 files (but over time, the default value has changed). Also, if you don't install it, merge uses diff.renameLimit , so you can only set the second of them, and both diff and merge use both values.

The method for detecting file renaming is a bit complicated, but simple enough to describe with an example. Suppose git compares commit 12345 with commit 67890 , and in 12345 files with paths A , B/C and D ; but in 67890 there are B/gronk , B/C and D paths. This means that path A disappeared, but a new path B/gronk . git will then remember such paths (down to the rename value) and compare the contents of 12345:A with the contents of 67890:B/gronk . If the files are "fairly similar," git will announce that 12345:A been renamed 67890:B/gronk .

I'm not sure exactly how git decides that a file is 50%, or 75%, or something similar / similar. I have seen that the similarity index is based on β€œchunks” rather than strings (although the usual diff output is linearly oriented).

+5
source

To move the file you need to use git mv , not just mv .

Since git accepts a snapshot of the content, it does not care about the file name (which is stored in the idx file as metadata).

If you just move the file, git will not "understand" that you want to move it, and will treat it as a new file.

You need to revert your changes and then use:

 git mv <old path> <new path> 

Now in git status you will see the file moving, not deleting one and creating a new one.

+1
source

Source: https://habr.com/ru/post/1234230/


All Articles