Git rebase with renamed files

You can rebase your branch while detecting renames like so:

git rebase --strategy-option="rename-threshold=10" master

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,

  • the current branch is rebased onto master
  • the rename threshold of 10% is specified
  • changes in master to the original files will be placed in the new (renamed) files (as opposed to running merely git rebase master).
  • note how the syntax is different compared to similar rename-detection functionality found in the git diff, git log, and git merge commands

The 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 :)


In addition of the find-rename rebase/merge strategy, with Git 2.29 (Q4 2020), the commit labels used to explain each side of conflicted hunks placed by the sequencer machinery have been made more readable by humans.

See commit 7d056de (12 Aug 2020) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster -- in commit 6cceea1, 19 Aug 2020)

sequencer: avoid garbled merge machinery messages due to commit labels

Signed-off-by: Elijah Newren
Reviewed-by: Taylor Blau
Acked-by: Johannes Schindelin

sequencer's get_message() exists to provide good labels on conflict hunks;
see commits

  • d68565402a ("revert: clarify label on conflict hunks", 2010-03-20, Git v1.7.1-rc0)
  • bf975d379d ("cherry-pick, revert: add a label for ancestor", 2010-03-20, Git v1.7.1-rc0)
  • 043a4492b3 ("sequencer: factor code out of revert builtin", 2012-01-11, Git v1.7.1-rc0).
    for background on this function.

These labels are of the form ... or parent of ...

These labels are then passed as branch names to the merge machinery.

However, these labels, as formatted, often also serve to confuse.

For example, if we have a rename involved in a content merge, then it results in text such as the following:

<<<<<<<< HEAD:foo.c
  int j;
========
  int counter;
>>>>>>>> b01dface... Removed unnecessary stuff:bar.c  

Or in various conflict messages, it can make it very difficult to read:

CONFLICT (rename/delete): foo.c deleted in b01dface... Removed
unnecessary stuff and renamed in HEAD.  Version HEAD of foo.c left
in tree.  

CONFLICT (file location): dir1/foo.c added in b01dface... Removed
unnecessary stuff inside a directory that was renamed in HEAD,
suggesting it should perhaps be moved to dir2/foo.c.  

Make a minor change to remove the ellipses and add parentheses around the commit summary; this makes all three examples much easier to read:

<<<<<<<< HEAD:foo.c
  int j;
========
  int counter;
>>>>>>>> b01dface (Removed unnecessary stuff):bar.c  

CONFLICT (rename/delete): foo.c deleted in b01dface (Removed
unnecessary stuff) and renamed in HEAD.  Version HEAD of foo.c left
in tree.  

CONFLICT (file location): dir1/foo.c added in b01dface (Removed
unnecessary stuff) inside a directory that was renamed in HEAD,
suggesting it should perhaps be moved to dir2/foo.c.

Tags:

Git

Merge

Rebase