Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git merge of moved files

Tags:

git

github

I forked a repo and changed the file A. Now file A in the upstream repo has moved to a sub directory. I am trying to merge the upstream repo to my fork.

Git thinks that file A was deleted in its original location and a new one was created in the new sub directory (This could also be because, of the way they moved the file upstream).

I want to get my modifications into this file in the new location with least possible repercussions, w.r.t history of commits and stuff. Can anyone please help me out with ways to achieve this?

like image 765
Sreekanth Pothanis Avatar asked Oct 21 '15 21:10

Sreekanth Pothanis


People also ask

What is Mergetool in git?

Use git mergetool to run one of several merge utilities to resolve merge conflicts. It is typically run after git merge. If one or more <file> parameters are given, the merge tool program will be run to resolve differences on each file (skipping those without conflicts).

What is the fastforward merge in git?

A fast-forward merge can occur when there is a linear path from the current branch tip to the target branch. Instead of “actually” merging the branches, all Git has to do to integrate the histories is move (i.e., “fast forward”) the current branch tip up to the target branch tip.


1 Answers

Git always detects renames "after the fact", by comparing the two trees in question (or one tree and the index, for cases that don't include git merge itself). (Linus Torvalds considers this a feature; see this SO question for instance.)

In any case, git merge will run git's internal diff with merge detection enabled and the default similarity-index of 50%, unless you configure it otherwise.1 Similarly, git diff has some defaults which are also configurable. If you run git diff --find-renames -M50% manually between your merge-base and the upstream, you're probably fine (but see footnote 1 about configuring).

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


1You can set merge.renameLimit to the number of files to consider in terms of rename detection. If you do not set it, the current default is 1000 files (but the default has changed over time). Also, if you do not set it, merge uses diff.renameLimit, so you can set just the second of these, and have both diff and merge use both values.

The way file rename detection works is a bit complex, but simple enough to describe by example. Suppose that git is comparing commit 12345 with commit 67890, and in 12345 there are files with pathnames A, B/C, and D; but in 67890 there are pathnames B/gronk, B/C, and D. This means path A is gone but new path B/gronk has appeared. Git will then remember such paths (up to the rename limit value), and will compare the contents of 12345:A with the contents of 67890:B/gronk. If the files are "sufficiently similar", git will declare that 12345:A was renamed to 67890:B/gronk.

I'm not sure precisely how git decides that a file is 50%, or 75%, or whatever, similar/different. I have seen that similarity index is based on "chunks" rather than lines (even though the usual diff output is line-oriented), though.

like image 128
torek Avatar answered Oct 21 '22 01:10

torek