Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smarter rebase avoiding redundant work?

Tags:

One issue I run into with long rebases is having to resolve redundant conflicts. Say I have a branch with a sequence of commits that keeps modifying a function, and the final commit removes the function entirely.

When I do rebase master, Git naively applies each of the commits in turn. That means I need to resolve each of these commits with the tip of master - even though ultimately that work is wasted.

What's a good way to deal with this situation? Perhaps I should just generate a single patch for the whole branch, and apply that against master? If so, is there any way to preserve some history? Thoughts, suggestions, etc.

like image 832
Steve Bennett Avatar asked May 15 '12 13:05

Steve Bennett


People also ask

What is the main issue with git rebase?

The golden rule of git rebase is to never use it on public branches. The rebase moves all of the commits in main onto the tip of feature . The problem is that this only happened in your repository. All of the other developers are still working with the original main .

What is main issue with git rebase when working with multiple developers?

recommends that rebase should not be done on branch shared between developers. I understand that, because a developer might first merge the code and then he decides to rebase the code, other developers might end up in creating multiple duplicates commits as explained in Perils of Rebasing.

What is the purpose of rebasing?

The primary reason for rebasing is to maintain a linear project history. For example, consider a situation where the main branch has progressed since you started working on a feature branch.

How do you force stop rebasing?

You can run git rebase --abort to completely undo the rebase. Git will return you to your branch's state as it was before git rebase was called. You can run git rebase --skip to completely skip the commit. That means that none of the changes introduced by the problematic commit will be included.


2 Answers

You want to use git rerere combined with teaching the rerere database from historical commits using rerere-train.sh (you may already have it at /usr/share/doc/git/contrib/rerere-train.sh). This allows git to automatically use merge conflict resolutions learned from the history.

Warning: you're basically making git rewrite the source code by blindly using historical string replacements to fix the conflicting merge. You should review all conflicting merges after the rebase. I find that gitk works fine for this (it will show only conflict resolution as the patch for merges). I've had only good experiences with rerere, you might not be that lucky. Basically, if your history does contain broken merges (that is, merges that are technically incorrectly done and then later fixed in following commits), you do not want to use rerere from the history, unless you want to have similarly broken merges done automatically for you.

Long story short, you just run

git config --global rerere.enabled 1 bash /usr/share/doc/git/contrib/rerere-train.sh --all 

followed by the rebase you really want to do and it should just magically work.

After you have enabled rerere globally, you no longer need to learn from the history in the future. The learning feature is required only for using rerere after the fact the conflict resolution is already done before enabling rerere.

PS. I found similar answer to another question: https://stackoverflow.com/a/4155237/334451

like image 86
Mikko Rantalainen Avatar answered Nov 10 '22 15:11

Mikko Rantalainen


You could use git rerere feature.

You have to enable it using git config --global rerere.enabled 1, after that, every conflict you resolve get stored for later use and the resolution is reapplied in the same contexts.

You can check the stored resolutions with git rerere diff.

Take a look at this tutorial for more information.

like image 36
KurzedMetal Avatar answered Nov 10 '22 14:11

KurzedMetal