Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Mercurial graft cope with renamed files

Tags:

mercurial

I want to use hg graft to copy a changeset from one branch to another.

However, a file that is modified in the changeset has been renamed (using hg rename) in the source branch -- before the changeset that I want to graft.

When I try I get:

scanning for duplicate grafts
grafting revision 3
  searching for copies back to rev 2
  unmatched files in local:
   f1.txt
resolving manifests
 overwrite: False, partial: False
 ancestor: c06936303423, local: cfeaa3003c57+, remote: e3f2a201d1e2
remote changed f1a.txt which local deleted
use (c)hanged version or leave (d)eleted? c

Neither (c) nor (d) seem like the right option.

The file f1a.txt was renamed from f1.txt in the source branch. f1a.txt never even existed in the target branch.

Is this possible?

like image 856
Rob Walker Avatar asked Oct 05 '12 20:10

Rob Walker


3 Answers

This is an excellent question. It looks like it is not possible. I replayed your scenario and also tried transplant and rebase -- with the same effect.

I guess the basic reason why this does not work is because a graft explicitly only picks the changes of one revision, i.e. past changes (including file renames) explicitly are not considered (update: could be a bug or missing feature as well, see @Soulman's answer).

You did not ask for, but here's a work around ..

  1. Get a patch of the changeset you want to graft:

    $ hg export --git -r <rev-to-graft> > my.patch
    
  2. In this patch, replace f1a.txt with f1.txt, so you get:

    ...
    diff --git a/f1.txt b/f1.txt
    --- a/f1.txt
    +++ b/f1.txt
    @@ -1,1 +1,1 @@
    ...
    

    Sed is your friend here: sed -i my.patch -e "s,\([ab]\)/f1a\.txt,\1/f1.txt,g"

  3. Import the edited patch to the target revision:

    $ hg up <target-rev>
    $ hg import my.patch
    
like image 72
Oben Sonne Avatar answered Oct 10 '22 21:10

Oben Sonne


I think this is simply a bug that will hopefully be fixed. There is a ticket: Graft fails when files have been moved in an ancestor revision.

like image 4
Soulman Avatar answered Oct 10 '22 21:10

Soulman


A rename is a delete + add + a note saying to treat history of the old file as the history of the new file. When doing a graft (that is making a new changeset by duplicating the same changes without creating a relation as opposed to a merge), you have to incorporate the changes of the changeset some how. You can only graft an "add" operation in this case or decide not to add the file (leave it deleted). I am sorry to say, that it is fundamentally impossible to graft a rename in this case, because it is meaningless if the other branch did not have that file.

I am sorry, if I didn't understand correctly the situation you are in. If that is the case, then please provide an example. (Few commands to set up a dummy repo, which reproduces your case will do the trick).

like image 1
Eiver Avatar answered Oct 10 '22 21:10

Eiver