Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my "git rebase master" returning too much commits than "normal" after the lastest merge?

I try to understand what I am doing wrong but nothing. I am totally confused. I know that another way to merge branches (or commits) is to use "git rebase". I have 3 branches: master and 2 others for different features. Let's talk about master, f1 and f2. I am working on my f1, and I need another feature, so I create f2. when I finish with f1, master has already another changes. I want to rebase f1 on master. I did it, and I see 144 steps. I try to fix all commits and I push the changes. Now I apply my f2 commits to f1 and decide to do a pull request to master. I try to rebase f1 on master and I get 244 steps. or it is just 4 new commits on master. And I already get them on my local master.

I am so confused. Everytimes I want to use rebase, it seems I get more steps that commits really done.

I must tell that in the beginning I was just doing merges with "git merge" but I was asked to do them with "git rebase".

I try to search why I have too much steps, I followed tutorials again, but I cannot try to fix more that 200 steps again. It is boring and needs time. Can you explain me more and help to fix this situation, please? I do not want to fix this now and get more than 300 later. thanks

like image 669
Cutis Avatar asked Jul 12 '19 14:07

Cutis


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 .


1 Answers

That is a misunderstanding of what rebase does, and I believe this is what has created this very frustrating situation.

What might have happened

Suppose you have the follow situation (which I believe is what you described).

master  o---o---o---o---o---o
                 \
feature1          A---B---C
                           \
feature2                    X---Y---Z

You're done with work on feature1, but there are some commits on master that haven't been tested with the feature1 changes. So, to update feature1 you do the following:

  • git checkout feature1
  • git rebase master

This results in the following situation:

master  o---o---o---o---o---o
                 \           \
feature1          \           A'---B'---C'
                   \        
feature2            A---B---C---X---Y---Z

Wait, what? Why are there two copies of A-B-C!?

That's what rebase does. Rebase makes NEW commits starting from the base given in the command (master in this situation).

What probably happened next

Now that feature1 has been updated with the latest from master, you need to update feature2. So, you follow the same process:

  • git checkout feature2
  • git rebase feature1

This results in the following situation:

master  o---o---o---o---o---o
                             \
feature1                      A'---B'---C'
                                         \        
feature2                                  A"---B"---C"---X---Y---Z

Uh oh.

As you can see, after a few times through this cycle you end up in a very bad place where you have to resolve "conflicts" that are just applying the same changes over and over.

How to fix the current mess

Just bite the bullet and use merge. Seriously, this is the fastest way to deal with it. Update the feature branches from master with git merge master and then merge the feature branches back into master (when appropriate).

Alternatively, you can delve into the dark magic that is interactive rebase. Use the -i flag when running git rebase and you will see a list of all commits it is attempting to reapply. Remove the duplicates and carry on your merry way. I don't like this approach because it's easy to make a mistake, and it's a PIA to recover from these mistakes.

How to avoid this going forward

Detailed article

In short, you need to tell git to ignore the duplicated commits. Updating feature1 using rebase was fine, the problem happened with feature2.

  • git checkout feature2
  • git rebase --onto feature1 feature1@{1} feature2

Which gets us

master  o---o---o---o---o---o
                             \
feature1                      A'---B'---C'
                                         \        
feature2                                  X'---Y'---Z'

Exactly what we wanted!

So, what is this command doing?

git rebase --onto feature1 feature1@{1} feature2

  • --onto feature1 - we're going move these commits onto the branch feature1
  • feature1@{1} - We just rebase'd feature1, so we need to get the previous commit (IE the one before the rebase). This is the start of the commit range we're moving
  • feature2 - This is the end of the commit range we're moving

NOTE: feature1@{1} will work when used as part of the process described in the article, but may not be correct if other git commands are run between updating feature1 and feature2. In this instance, you can substitute this for the raw commit id - obtained by reviewing the output from git log while on feature2 and selecting the last commit from feature1 ("C" in the example given here).

Other Good Reading:

  • Atlassian article: Merging vs Rebasing

  • When do you use Git rebase instead of Git merge?

like image 106
Vlad274 Avatar answered Sep 22 '22 01:09

Vlad274