Skip to contentSkip to conversation

Merge after directory rename ?

DISCUSSION Marcin Wiśnicki 3 participants 8 messages Jun 15, 2016

lore
Share & tools
lore
#0 lore raw

Is it possible to merge files after performing directory renames in such way that new files will end up in renamed directories ?

For example:
1. [master] add dir1/file1
2. [branch1] branch from master
3. [branch1] add dir1/file2
4. [master] rename dir1 to dir2
5. [master] merge branch1

Where it should notice that dir1=>dir2 and therefore {dir1=>dir2}/file2.

Currently I end up with dir1/file2 which is undesirable as it breaks refactorings and requires a lot of manual effort to clean-up.

#1 lore raw

2011/8/21 Marcin Wiśnicki <[email protected]>:

Quoted 10 lines

Is it possible to merge files after performing directory renames in such way that new files will end up in renamed directories ?

For example:
1. [master]  add dir1/file1
2. [branch1] branch from master
3. [branch1] add dir1/file2
4. [master]  rename dir1 to dir2
5. [master]  merge branch1

Quoted 4 lines

Where it should notice that dir1=>dir2 and therefore {dir1=>dir2}/file2.

Currently I end up with dir1/file2 which is undesirable as it breaks refactorings and requires a lot of manual effort to clean-up.

Part of the assumption for someone working on branch1' might be that dir1/file2' is in fact in dir1'. The rename via master' conflicts with that assumption. In this case, a full-blown conflict might be useful.

However, suppose that the author who is working with master' doesn't need dir1', but the author who is working with `branch1' does need it INDEPENDENTLY:

1. [master] add dir2/file1
2. [branch1] branch from master
3. [branch1] add dir1/file2

  4. [master]  add dir1/file3
  5. [master]  rename dir1/file3 to dir3/file3
  6. [master]  merge branch1

In that case, you'd want dir1/file2' from the branch1' work to be silently created rather than automatically renamed to `dir3/file3'. This should not result in a conflict or a rename.

So, from your grievance, I suppose that git currently assumes the latter case (and hence, gives no indication of a possible conflict). Perhaps git could be improved here at least in terms of a warning. Perhaps the merger could request that directory renames be considered conflicts or enforced, but this would have to involve the intent of the merger me thinks (using command line flags).

#2 lore raw

2011/8/21 Michael Witten <[email protected]>:

Quoted 36 lines

2011/8/21 Marcin Wiśnicki <[email protected]>:

Quoted 10 lines

Is it possible to merge files after performing directory renames in such way that new files will end up in renamed directories ?

For example:
1. [master]  add dir1/file1
2. [branch1] branch from master
3. [branch1] add dir1/file2
4. [master]  rename dir1 to dir2
5. [master]  merge branch1

Quoted 4 lines

Where it should notice that dir1=>dir2 and therefore {dir1=>dir2}/file2.

Currently I end up with dir1/file2 which is undesirable as it breaks refactorings and requires a lot of manual effort to clean-up.

Part of the assumption for someone working on branch1' might be that dir1/file2' is in fact in dir1'. The rename via master' conflicts with that assumption. In this case, a full-blown conflict might be useful.

However, suppose that the author who is working with master' doesn't need dir1', but the author who is working with `branch1' does need it INDEPENDENTLY:

 1. [master]  add dir2/file1
 2. [branch1] branch from master
 3. [branch1] add dir1/file2
 4. [master]  add dir1/file3
 5. [master]  rename dir1/file3 to dir3/file3
 6. [master]  merge branch1

In that case, you'd want dir1/file2' from the branch1' work to be silently created rather than automatically renamed to `dir3/file3'. This should not result in a conflict or a rename.

Quoted 6 lines

So, from your grievance, I suppose that git currently assumes the latter case (and hence, gives no indication of a possible conflict). Perhaps git could be improved here at least in terms of a warning. Perhaps the merger could request that directory renames be considered conflicts or enforced, but this would have to involve the intent of the merger me thinks (using command line flags).

Importantly, note that I used only file names in my example, specifically:

5. [master] rename dir1/file3 to dir3/file3

rather than mirroring your example by writing:

5. [master] rename dir1 to dir3

This is because git fundamentally tracks content, and paths are just one kind of content associated with another blob of content. Consequently, git really knows next to nothing about directories, so it's not too surprising that git doesn't bother finding such a DIRECTORY rename anyway (at most, git would detect a FILE rename, and your FILE dir1/file2' has nothing to do with, say, the FILE dir1/file1' being renamed `dir2/file1').

Still, some command line switches could be useful to help the user express to git what should be going on in a case such as yours.

#3 lore raw
Quoted 11 lines · Michael Witten

Importantly, note that I used only file names in my example, specifically:

5. [master] rename dir1/file3 to dir3/file3

rather than mirroring your example by writing:

5. [master] rename dir1 to dir3

This is because git fundamentally tracks content, and paths are just one kind of content associated with another blob of content. Consequently,

I know it tracks content, yet it puts effort to detect file renames. I want it to also detect directory renames, detecting it should be quite easy.

Quoted 8 lines

git really knows next to nothing about directories, so it's not too surprising that git doesn't bother finding such a DIRECTORY rename anyway (at most, git would detect a FILE rename, and your FILE dir1/file2' has nothing to do with, say, the FILE dir1/file1' being renamed `dir2/file1').

Still, some command line switches could be useful to help the user express to git what should be going on in a case such as yours.

I would prefer it to be fully automatic :)
Or at least detect/warn about tree conflict.
Directory renames can happen quite frequently when working with Java/C# and it is unreasonable to expect that lazy user will have to keep track of it manually (with huge number of files it's impossible).

#4 lore raw

2011/8/22 Marcin Wiśnicki <[email protected]>:

Quoted 23 lines · Michael Witten
Quoted 11 lines

Importantly, note that I used only file names in my example, specifically:

  5. [master]  rename dir1/file3 to dir3/file3

rather than mirroring your example by writing:

  5. [master]  rename dir1 to dir3

This is because git fundamentally tracks content, and paths are just one kind of content associated with another blob of content. Consequently,

I know it tracks content, yet it puts effort to detect file renames. I want it to also detect directory renames, detecting it should be quite easy.

Quoted 6 lines

git really knows next to nothing about directories, so it's not too surprising that git doesn't bother finding such a DIRECTORY rename anyway (at most, git would detect a FILE rename, and your FILE dir1/file2' has nothing to do with, say, the FILE dir1/file1' being renamed `dir2/file1').

Quoted 4 lines
Quoted 2 lines

Still, some command line switches could be useful to help the user express to git what should be going on in a case such as yours.

I would prefer it to be fully automatic :)

I assume the smiley is tongue-in-cheek; however, in case it is not: It can't be automatic in general; did my examples mean nothing?

Quoted 1 line

Or at least detect/warn about tree conflict.

Did my examples mean nothing?

Quoted 3 lines

Directory renames can happen quite frequently when working with Java/C# and it is unreasonable to expect that lazy user will have to keep track of it manually (with huge number of files it's impossible).

Git doesn't know anything about Java/C#; that's the point.

In general, the user could make use of switches (as suggested). In particular, perhaps there are merge hooks or merge drivers that could be used or implemented for allowing a more environment-specific handling of merges, a la GNU's ChangeLog merge driver:

http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/git-merge-changelog.c

Also, see the configuration section of git help merge'. Also look at the tool git mergetool'.

#5 lore raw

2011/8/22 Michael Witten <[email protected]>:

Quoted 6 lines

I assume the smiley is tongue-in-cheek; however, in case it is not: It can't be automatic in general; did my examples mean nothing?

Quoted 1 line

Or at least detect/warn about tree conflict.

Did my examples mean nothing?

Well kind of. Your example was different because you have created dir1 independently on branch1 and master in which case automatic rename wouldn't be expected. If you would've created dir1 before branching and renamed dir1 to dir3 (renamed all files under dir1) then I would expect a rename while merging.

The exact behaviour of merging branch1 to master I want is:

let base = $(git merge-base master branch1)
for each {modified,added,deleted} file in $base..branch1:
let dir = $(dirname $file)
if $dir exists in master:
if $dir existed in $base: [1]
proceed
else: # both branches independently introduced same directory
tree conflict
else: # no $dir in master
if $dir existed in $base:
if all $dir/* files in $base..master were renamed to $newdir/*:
rename $file [s/$dir/$newdir/]
else: # $dir was removed
tree conflict
else:
proceed # simple addition

Where "$dir exists" means that a file with path of matching prefix exists. By default tree conflict should be ignored (proceed with merge as today) but user should be able to make it fatal.

[1] It would be better if instead of comparing two trees it would analyze each commit independently to detect shadowed renames:
(dir1=>dir2 then new dir1) => still rename.

Quoted 6 lines
Quoted 4 lines

Directory renames can happen quite frequently when working with Java/C# and it is unreasonable to expect that lazy user will have to keep track of it manually (with huge number of files it's impossible).

Git doesn't know anything about Java/C#; that's the point.

And it shouldn't. Renames can happen with anything, I'm just pointing out that they are quite frequent in Java/C#.
You might as well have a C project and rename directory "src" to "sources" and, when merging branch created from before that, expect to get automatic s/src/sources/.

Quoted 7 lines

In general, the user could make use of switches (as suggested). In particular, perhaps there are merge hooks or merge drivers that could be used or implemented for allowing a more environment-specific handling of merges, a la GNU's ChangeLog merge driver:
Also, see the configuration section of git help merge'. Also look at the tool git mergetool'.

Merge drivers are file type specific, mergetool is used to resolve conflicts after merge and I don't see a pre-merge hook :(

#6 lore raw

2011/8/22 Marcin Wiśnicki <[email protected]>:

Quoted 5 lines

Well kind of. Your example was different because you have created dir1 independently on branch1 and master in which case automatic rename wouldn't be expected. If you would've created dir1 before branching and renamed dir1 to dir3 (renamed all files under dir1) then I would expect a rename while merging.

I already covered this case in my initial paragraph. Good Luck!

#7 lore raw
In reply to Michael Witten
Quoted 10 lines · Michael Witten

This is because git fundamentally tracks content, and paths are just one kind of content associated with another blob of content. Consequently, git really knows next to nothing about directories, so it's not too surprising that git doesn't bother finding such a DIRECTORY rename anyway (at most, git would detect a FILE rename, and your FILE dir1/file2' has nothing to do with, say, the FILE dir1/file1' being renamed `dir2/file1').

Still, some command line switches could be useful to help the user express to git what should be going on in a case such as yours.

FYI, Yann Dirson was working on some patches to detect directory renames, but we haven't heard anything for a while. The last version I could find was:

http://thread.gmane.org/gmane.comp.version-control.git/163328

-Peff