git merge with renamed files

Since git 1.7.4, you can specify the rename threshold for merge as git merge -X rename-threshold=25 in order to control that a similarity of 25% is already enough to consider two files rename candidates. This, depending on the case together with -X ignore-space-change may make rename detection more reliable.

However, I wanted to have more direct control and was cooking up a related script the last days. Maybe it helps - let me know.

https://gist.github.com/894374


Should have work automatically, thanks to rename detection. Below there is sample session:

$ git init test
Initialized empty Git repository in /tmp/jnareb/test/.git/
$ cp ~/git/README .    # example file, large enough so that rename detection works
$ git add .
$ git commit -m 'Initial commit'
[master (root-commit) b638320] Initial commit
 1 files changed, 54 insertions(+), 0 deletions(-)
 create mode 100644 README
$ git checkout -b new-feature        
Switched to a new branch 'new-feature'
$ git mv README README.txt
$ git commit -m 'Renamed README to README.txt'
[new-feature ce7b731] Renamed README to README.txt
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename README => README.txt (100%)
$ git checkout master
Switched to branch 'master'
$ sed -e 's/UNIX/Unix/g' <README >README+ && mv -f README+ README
$ git commit -a -m 'README changed'
[master 57b1114] README changed
 1 files changed, 1 insertions(+), 1 deletions(-)
$ git merge new-feature 
Merge made by recursive.
 README => README.txt |    0
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename README => README.txt (100%)

If you were doing "git merge master" on 'new-feature' branch instead of, like above, "git merge new-feature" on 'master', you would get:

$ git merge master
Merge made by recursive.
 README.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Could you tell what you were doing differently?

Note that ordinary "git rebase" (and "git pull --rebase") do not pick up renames: you need to run "git rebase -m" or interactive rebase.


I figured out a fix. Since the renaming of the files was done by a script I was able to copy the new .php files and rerun the script before the merge. Since the files had the same name the merge worked without conflicts.

Here are the steps for the whole process.

  1. Create git repo git init
  2. Copy existing files in
  3. Commit
  4. Run script to rename files
  5. Commit
  6. Create a branch but don't check it out
  7. Make fixes committing changes as you go
  8. Checkout the branch you made in step 6
  9. Copy the new versions of the files
  10. Run the script to rename the files (this should replace the ones from the first run)
  11. Commit
  12. Checkout master
  13. merge the branch into master

This works because to git the changes were made to the files with the new name.


In my case when rename detection failed, I found that during merge resolution I could do the following:

Given:

fileA: A modified file that was moved to the new place but is currently in the old place.
destB: The location where fileB was moved to. This could include a new filename.

Run these commands:

git add fileA
git mv fileA destB

Thats all I had to do. Then I committed and the rebase continued.