Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rebase after squashing commits in the original branch?

I have

A--B--C master        \         D branch0 

Then I squash B and C into B'. How do I rebase branch0 such that it looks like this:

A--B' master     \      D branch0 
like image 713
erensezener Avatar asked Mar 09 '16 20:03

erensezener


People also ask

How do you rebase squashed commits?

In case you are using the Tower Git client, using Interactive Rebase to squash some commits is very simple: just select the commits you want to combine, right-click any of them, and select the "Squash Revisions..." option from the contextual menu.

Should you squash and REBASE your Git commits?

When it comes to squashing and rebasing your commits, the pros significantly outweigh the cons. It speeds up your debugging process, cleans up your history, reduces the pain from merge conflicts and makes collaboration in your team much better.

What is the squash REBASE workflow?

What is the squash rebase workflow? It’s simple – before you merge a feature branch back into your main branch (often master or develop ), your feature branch should be squashed down to a single buildable commit, and then rebased from the up-to-date main branch. Here’s a breakdown. Make changes as needed with as many commits that you need to.

How to rebase a branch in Git?

Here are the steps to follow while rebasing a branch: You should receive the latest changes from a remote git repository. Thus the first step is running git fetch: The second step is running git rebase. Rebase is a Git command which is used to integrate changes from one branch into another.

What happens when you REBASE to the master branch?

If you use the rebase command onto master branch, you will update feature A branch base commit. In other words, you would get all of the latest changes from master branch in feature A branch as if those commits happened first prior to you making commits to feature A branch, making sure feature A branch is up to date with master branch.


Video Answer


2 Answers

Use the --onto argument to git rebase, which changes the baseline that git replays work on.

git checkout branch0 

At this state you should still see C in your git history.

git rebase --onto B' C 

This translates to: Take all commits in my current branch since commit C (In your case that's just D) and play back on top of B'

You can also use the optional <branch> argument to do both the checkout and rebase at once:

git rebase --onto B' C branch0 
like image 86
pcrost Avatar answered Sep 22 '22 01:09

pcrost


I've run into a similar problem when using squash-merge on PRs when you have branches off of branches.

My common example is if I have one feature branch (feature-a). I push some commits to that branch. Then I create another feature branch off of that (feaure-b-off-a). Then I squash-merge feature-a into main, I'll see duplicate commits in the PR of feature-b-off-a into main.

To fix this, we can use a rebase --onto like the accepted answer, here. But the manual work of that is finding C (I refer to common-ancestor below). Rewritten another way:

git rebase --onto main common-ancestor feature-b-off-a

  • Take all the commits between common-ancestor and feature-b-off-a and rebase them onto main

Fortunately, git has a way of finding the common ancestor between two branches:

git merge-base feature-b-off-a feature-a


TL;DR:

# This will print out the 'common-ancestor' commit between the commits/branches causing the problem git merge-base feature-b-off-a feature-a # Take all the commits between common-ancestor and feature-b-off-a and rebase them onto main git rebase --onto main <common-ancestor> feature-b-off-a # Then you'll need to force push since it's a rebase git push -f origin feature-b-off-a 

🎉 Your PR into main should now only show the new commits.


Bonus git-alias

Note: This assumes your flow is squash-merging both into main

git config --global alias.rebase-onto '!f() { git rebase --onto main $(git merge-base "$1" "$2") "$1"; }; f' 

Which you'd call with:

git rebase-onto feature-b-off-a feature-a # Then you'll need to force push since it's a rebase git push -f origin feature-b-off-a 
like image 33
Kyle Venn Avatar answered Sep 18 '22 01:09

Kyle Venn