[Git] How to rebase the pushed branch

Table of Contents

Learning the knowledage with a real case is always perferred. I met a case today that I need to use git rebase --interactive to solve the issue.

The story is that my colleague created a branch for doing some research one year ago. Let’s say the branch name is feat/performance-research. As the branch is mainly for research purpose, it was not merged to the master branch at that time. However, some changes and results were quite valuable.

Recently we want to revisit and re-evaluate the branch and apply some of its changes to the master branch. And I picked up the task.

After I checkout this one-year old branch feat/performance-research, I should actually rebase it to the master branch as there were so many commits on the main feature during one year. And I am pretty sure that there is no any conflicts because branch feat/performance-research only added the new files in a new directory.

Unfortunately, I mistakenly merged the master branch into the feat/performance-research branch and pushed it out.

Okay, they look like having the same results, but they are not. After pushing out, the commit history of the Pull Request of the branch feat/performance-research becomes very huge. Github even prompts something like “there are too many commits, only display the first 250 commits”. Obviously, this is not what I want.


At the moment, I can use git revert to save my mistake. But I learned another decent solution which is the git rebase --interactive.

Currently, the last commit of the branch feat/performance-research on both local and remote is the “Merge commit”. What I will do is

git rebase -i master

After running the command, the terminal will open an editor to list the commit history like below

pick 2231360 some old commit
pick ee2adc2 Adds new feature


# Rebase 2cf755d..ee2adc2 onto 2cf755d (9 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

I find the commit “Merge commit” SHA and add the below code at the end of the commands

pick 2231360 some old commit
pick ee2adc2 Adds new feature
drop 3c98bf9a7

# Rebase 2cf755d..ee2adc2 onto 2cf755d (9 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

Save the changes. Git command will run automatically to rebase each commit into the branch feat/performance-research. Since the original Pull Request has over 20 commits and the commits in the time sequence had many changes on the same code, it had many conflicts during the interactive rebase. Give an example like below

CONFLICT (add/add): Merge conflict in ./performance-research
Auto-merging ./performance-research
error: could not apply b54161f12... separate scheduled and pr-bound actions
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply b54161f12... separate scheduled and pr-bound actions

In this case, I just need to refer to the last version of the code and resolve the conflicts one by one. After resolving the conflict and saving the code, run the below commands

git add performance-research/*
git rebase --continue

After all the commits are rebased, it will output

Successfully rebased and updated refs/heads/feat/performance-search

It’s not finished yet.

At this moment, the local branch feat/performance-research has rebased against master branch, which is great. However, the remote branch feat/performance-research still has the “Merge commit”.

The git status is like below:

It can be tested with git push and you will see

To https://github.com/xxx
 ! [rejected]            feat/performance-research -> feat/performance-research (non-fast-forward)
error: failed to push some refs to 'https://xxxx'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

In this case, if we are sure that the local branch is correct and has no problem to rewrite the remote branch. We can force to push the local branch by

git push -f origin feat/performance-research

Now refreshing the Pull Request page, we can see that the huge commits are all gone, instead, only the new rebase commits are added into the history.

It is much tider and cleaner.


Extend reading:

git rebase
git - your branch and 'origin/xxx' have diverged error


If this post helped you to solve a problem or provided you with new insights, please upvote it and share your experience in the comments below. Your comments can help others who may be facing similar challenges. Thank you!
Buy Me A Coffee
DigitalOcean Referral Badge
Sign up to get $200, 60-day account credit !