1

I am following this answer to understand the difference between git merge and rebase and also created a sample repository in Github to understand it well, but what I am watching is the same number of commits with both git merge and rebase operation.

Let me explain what I performed.

Step 1: I created a project and pushed it to master branch of Github repository.

Step 2: Created feature branch with name - feature-one with base as master branch, added dummy files and committed it as follows:

git checkout -b feature-one
touch test.txt
git add .
git commit -m "feature-one first commit"

touch another-test.txt
git add .
git commit -m "feature-one second commit"

Step 3: Switched back to master branch and merged the feature-one branch in it using git merge as follows:

git checkout master
git merge feature-one

Now I can see two additional commits(feature-one first commit, feature-one second commit) in master along with initial commit.

Then, I done the same steps and rebased it with git master branch as follows:

git checkout -b feature-one
touch test-rebase.txt
git add .
git commit -m "feature-one third commit"

touch another-test-rebase.txt
git add .
git commit -m "feature-one fourth commit"

Step 4: Switched back to master branch and merged the feature-one branch in it using git rebase as follows:

git checkout master
git rebase feature-one

Now again I can see two additional commits(feature-one third commit, feature-one fourth commit) in master along with previous three commits.

What's my expectation is I will not see the feature branch commits once rebased with master.

Now my question is my expectation correct or am doing something wrong?

Can anyone please explain?

Thanks.

Community
  • 1
  • 1
Arpit Aggarwal
  • 27,626
  • 16
  • 90
  • 108

2 Answers2

2

This is the expected behaviour of git. Rebase applies the local commits on top of the other branch's changes.

If you don't want to see the individual commits of the feature branch you need to squash the commits while merging.

$ git merge --squash feature-one
iltempo
  • 15,718
  • 8
  • 61
  • 72
  • what's confusing me is `but this way a new dummy commit is added, if you want to avoid spaghetti-history and of course be sexier you can rebase` in the answer. – Arpit Aggarwal Dec 19 '15 at 07:52
  • With `--squash` yes I can merge the multiple commit messages but what I am looking for is to avoid all the commit messages of feature branch which is not possible I believe. – Arpit Aggarwal Dec 19 '15 at 08:58
2

On the step 3 you performed what is called "fast-forward" merge. Prior to the merge branch master didn't contain any commits that weren't in feature-one, so git simply "moved" master to the state of feature-one without creating an additional commit.

It could be displayed graphically:

I - initial commit, the state of master branch before the merge
 \
  -> F1 -> F2 - the state of feature-one before the merge

after the merge you get:

I -> F1 -> F2 - the state of _both_ master and feature-one

If you had a different commit in master before the merge, the picture would be different:

I -> B1 - the state of master
 \
  F1 -> F2 - the state of feature-one

then during the merge (fast-forward isn't applicable in this case) git would create another, resulting commit with changes from both master and feature-one:

I -> B1 -> M1 - the state of master after the merge.
 \        /
  F1 -> F2 - the state of feature-one

Rebasing is another feature. Suppose you have the following commit sequence:

I -> B1 - the state of master
 \
  F1 -> F2 - the state of feature-one

and do not want to have a merge commit with multiple parents like M1 from the example above. Then you may ask git to rebase, move commits F1 and F2 over B1. A rebase is much like re-applying patches corresponding to F1 and F2, one by one. Certainly there could conflicts and you have to resolve them one by one (not once as in case of merge).

As the the result you would get the following picture

I -> B1 -> F1' -> F2'  -- the state of _new_, re-written feature1
     |
      \_the state of master

Notice that F1' and F2' are different from initial F1 and F2. At least these commits have new "commit time" and different parent commits so their "sha-1" are definitely different from those of F1 and F2. That's why rebasing could be considered harmful for published commits i.e. those commits that you have published somewhere and some people could rely on them. However you may (and somethimes should) use it internally, in your local repository to "make the history sexier" :), remove unnecessary intermediate state or changes etc. rebase is well suited from "cleanup" before publication etc. But once it's published it's safer to fix all discovered mistakes by creating additional commits.

user3159253
  • 16,836
  • 3
  • 30
  • 56
  • `If you had a different commit in master before the merge, the picture would be different`, yes it happened as you explained but the commit in master should be done after feature branch is created out of it, means state of master is changed after feature branch is created. – Arpit Aggarwal Dec 19 '15 at 08:54