I've got a branch that renames many files, and I'm trying to rebase it onto master
where the original files have been modified (preferably without this devolving into a manual conflict-resolution nightmare).
Situation
I've been porting a JavaScript project to TypeScript, in my local
typescript
branch. All of the.js
files have now become.ts
files, and some of the syntax has been upgraded.Meanwhile, changes to the original
.js
files have happened on themaster
branch.I want to rebase my
typescript
branch ontomaster
-- but the changes are not merging correctly, as the file renames hadn't been detected -- so we're getting conflicts where changes are made to.js
files which git thinks had been deleted (however they have actually been renamed to the.ts
file).
What I think I know
Git graph:
o-[typescript] .js files become .ts
|
| o-[master] changes to the .js files
| |
| o
|/
o-[root] common ancestor
So, while standing in the root
branch:
I can run this command to view all of the renames:
git diff --name-status --find-renames=10% typescript
I understand that the git merge command has the same sort of
--find-renames
functionality, though I'm having difficulty getting that to work.- Update:
git merge -X find-renames=10% mybranch
appears to be the expected syntax.
- Update:
I understand the git rebase might support
find-renames
functionality, though I'm still not clear about how that might be used.
Solution ideas?
(Nope) Perhaps from
root
, I could merge intypescript
while detecting the renames (like this:git merge -X find-renames=10% typescript
). Then, root will be just liketypescript
, except with renames (rather than mass deletions/additions).- From there, I'm hoping I could just
git rebase master
, and with the renames having been in place, the operation will go smoothly and place the edits into the correct files.- Update: I tried this, but my subsequent rebase didn't go over any better than before.
- From there, I'm hoping I could just
(Yep) I think perhaps the rebase itself needs to be performed with the
find-renames
option.. I'm investigating this...git rebase -X find-renames=10% master
-- nopegit rebase -X --find-renames=10% master
-- nopegit rebase --find-renames=10% master
-- nopegit rebase -X recursive --find-renames=10% master
-- nopegit rebase --merge -X find-renames=10% master
-- nopegit rebase --strategy-option="rename-threshold=10" master
-- that's the ticket! it works!
(Nope) Perhaps I need to look at the problem differently? Maybe I should start from
master
, and then do some kind of squash merge oftypescript
with the rename detection (rather than any kind of rebase?)- I don't need the
typescript
branch history, it will be squashed down to one fat commit for review anyways.. - Update: It looks like Git stops working when I attempt this strategy.. When I'm standing in the
root
branch, I can rungit merge -X find-renames=10 typescript
-- and it fast-forwards totypescript
.. (not quite what I was hoping for, I was hoping for a new commit that had renames rather than additions/deletions..)- When I'm standing in the
master
branch, and I run the exact same command, git tells me this:fatal: Unknown option for merge-recursive: -Xfind-renames=10
... - Now, this bothers me, because I actually did not enter what it quoted (I did include the space), and the only thing that seems different to me, is which branch I'm currently standing in -- if the option is "Unknown", then why does it work when in a different branch?
- Anyways, so that's creepy, and seems to make this approach a dead-end.
- When I'm standing in the
- I don't need the
It might help to first redo the file renaming in the
master
branch. It seems like a rather mechanical task that could be automated if required.Then it will probably be rather easy to rebase the
typescript
branch on top of that, as there will already be a common ground. Some commits of the rebasedtypescript
will end up (almost) empty, because their changes are already contained inmaster
.For this reason, you may want to consider merging
typescript
intomaster
instead, in order to keep the original.js
→.ts
transition history intact.You can rebase your branch while detecting renames like so:
Edit: Since Git 2.8.0, the term 'rename-threshold' has been deprecated in favor of 'find-renames'.
At the moment I'm using Git 2.7.4, and so I could only actually verify that the above command worked in my case — you may need to use the term 'find-renames' if the above command doesn't work in your case on your newer version of Git...
In this example,
master
10%
is specifiedmaster
to the original files will be placed in the new (renamed) files (as opposed to running merelygit rebase master
).git diff
,git log
, andgit merge
commandsThe git rebase documentation isn't very clear about this rename-detection aspect in particular.. I thought I read in another command somewhere, that the term "rename-threshold" was deprecated, though in this context
find-renames
did not seem to work as a synonym -- so if anybody knows about a better way to run this same command, please mention so :)