Ankit Bansal
Ankit Bansal

Reputation: 5072

How to merge files in git when directory is already moved to different directory

I was working on a branch taken from master branch for sometime. Now I need to merge my changes. The changes are in specific folder e.g. admin which is a subdirectory in my project.

When I took the latest from master branch, this directory is moved to another location e.g. master/admin. So, now when I try to merge, it shows me all of the admin related files as new file.

I would like to avoid any manual effort to merge and would like a way so that I can let git know that this is not new folder but is the existing folder which has been moved.

Upvotes: 4

Views: 6477

Answers (3)

VonC
VonC

Reputation: 1329292

Git 2.18 (Q2 2018) should facilitate such a merge.

Rename detection logic in "diff" family that is used in "merge" has learned to guess that:

  • when all of x/a, x/b and x/c have moved to z/a, z/b and z/c,
  • => it is likely that x/d added in the meantime would also want to move to z/d
    by taking the hint that the entire directory 'x' moved to 'z'.

See commit 1de70db, commit 05cf21e, commit 277292d, commit a35edc8, commit c04ba51, commit 2f682e2, commit bd42380, commit fd53b7f, commit 6e7e027, commit bc71c4e, commit 18797a3, commit 64b1abe, commit 79c4759, commit 9c0743f, commit 5b047ac, commit f6f7755, commit e95ab70, commit 96e7ffb, commit 7fe40b8, commit ffc16c4 (19 Apr 2018) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit c67de74, 23 May 2018)

You can see the new tests for merge with moved folders in t/t6043-merge-rename-directories.sh.

It details scenarios like:

###########################################################################
# SECTION 1: Basic cases we should be able to handle
###########################################################################

# Testcase 1a, Basic directory rename.
#   Commit O: z/{b,c}
#   Commit A: y/{b,c}
#   Commit B: z/{b,c,d,e/f}
#   Expected: y/{b,c,d,e/f}

The expected result would be when merging branch B into A.

That includes more complex use-cases:

# Testcase 1f, Split a directory into two other directories
# 
#   Commit O: z/{b,c,d,e,f}
#   Commit A: z/{b,c,d,e,f,g}
#   Commit B: y/{b,c}, x/{d,e,f}
#   Expected: y/{b,c}, x/{d,e,f,g}

The bottom line is:

So, now when I try to merge, it shows me all of the admin related files as new file

That should no longer be the case with Git 2.18.


With Git 2.25 (Q1 2020), when all files from some subdirectory were renamed to the root directory, the directory rename heuristics would fail to detect that as a rename/merge of the subdirectory to the root directory, which has been corrected.

See commit da1e295, commit 49b8133, commit d3eebaa (22 Oct 2019) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit d980035, 10 Nov 2019)

merge-recursive: fix merging a subdirectory into the root directory

Signed-off-by: Elijah Newren

We allow renaming all entries in e.g. a directory named z/ into a directory named y/ to be detected as a z/ -> y/ rename, so that if the other side of history adds any files to the directory z/ in the mean time, we can provide the hint that they should be moved to y/.

There is no reason to not allow 'y/' to be the root directory, but the code did not handle that case correctly.


With Git 2.25 (Q1 2020), that merge fix includes some code cleanup.

See commit 675ef6b, commit 01ed17d, commit f670adb (18 Dec 2019), and commit 8c02fe6, commit cb05d6a (11 Dec 2019) by René Scharfe (``).
(Merged by Junio C Hamano -- gitster -- in commit 8be0a42, 25 Dec 2019)

t3501: don't create unused file

Signed-off-by: René Scharfe

The file "out" became unused with fd53b7ffd1 ("merge-recursive: improve add_cacheinfo error handling", 2018-04-19, Git v2.18.0-rc0 -- merge listed in batch #6); get rid of it.

Upvotes: 3

CodeWizard
CodeWizard

Reputation: 142632

So, now when I try to merge, it shows me all of the admin related files as new file.

Restore the old branch and move the file with git mv and not a simple mv command.


Why do i have to use git mv and not just mv?

Git does not track file names. it store the content inside a .pack file and the file names (metadata) inside a .idx file and its not part of the content itself.

To get to know it much better read this out how does git store file names
https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#Tree-Objects

Git cannot track moved files unless you moved them with the git mv. If you simply move or rename them git will track them as new files and will delete the old one.


How to track changes of the moved files?

# you have to use the --follow flag
git log --follow ./path/to/file

Upvotes: 6

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522741

The answer by @CodeWizard looks good, but if that doesn't work then would there be anything wrong with simply adding the entire new folder?

Use this:

$ cd master
$ git add admin

Upvotes: 0

Related Questions