Leonardo
Leonardo

Reputation: 11389

Git Rebase -> Why is there a merge when pulling?

I created a branch to develop a new feature. Since this new feature was develop entirely as a new project, the only possible source of conflict would be in the solution file.

As the feature was developed, the master branch was updated several times. When I completed my development and testing, I did:

git checkout master
git fetch
git pull
git checkout myFeature
git rebase master

The rebase (and all other commands) went fine and no conflicts/errors/problems were reported. My next step was to git status and the result was:

On branch myFeature
Your branch and 'origin/myFeature' have diverged, and have 7 and 5 different commits each, respectively. (use "git pull" to merge the remote branch into yours)

When I git pull a merge was open and looking at the history, my commits were duplicated. This duplication, in my point of view was not supposed to happen. I was expecting that my commits were supposed to be re-applied AFTER the last (currently) commit on the master.

Am I doing something wrong or my expectation is wrong?

Upvotes: 5

Views: 3289

Answers (3)

Masudur Rahman
Masudur Rahman

Reputation: 1683

This part was enough for rebasing with master branch.

git checkout master
git fetch
git pull
git checkout myFeature
git rebase master

However, you can just use the following command instead of all the above command to do the same thing.

$ git pull origin master --rebase

After this all the commit hash will be rewritten that's why git status showed that your branch has diverged.

Ignoring this, you could run the following command to push the rebased code to the remote branch.

$ git push origin HEAD -f

While rebasing if you face conflicts and you are not willing to continue the rebase, you can just run git rebase --abort to abort the rebasing.

In any case, if you find yourself in the middle of some unwanted commit related hazard, you can follow the following steps.

  • git reflog - to find the last perfect commit & note its commit hash
  • git reset --hard <commit-hash> - provide the last perfect commit hash

It will take you to the last perfect code of the repo.

Upvotes: 1

kid_x
kid_x

Reputation: 1475

The previous answer looks great. Just trying to illustrate visually what's going, in case that's helpful:

Since git rebase modifies history, you branch after rebasing looks different from the one you have on origin.

origin/master:

A -> B -> C -> D -> E

yourbranch, origin/yourbranch:

A -> B -> F -> G -> H

After rebasing, yourbranch would look like:

A -> B -> C -> D -> E -> F -> G -> H

Then, when you pull origin/yourbranch, you would have:

A -> B -> C -> D -> E -> F -> G -> H - I (merge commit)
      \                              /
        -> F -> G -> H -------------

Since the histories are different, it becomes a normal, non-fast-forward merge. Effectively, your remote and local branches have become different branches.

Upvotes: 3

Julian
Julian

Reputation: 36710

Why is there a merge commit

When you do a rebase, you're changing Git history. When you do a pull again, Git tries to combine both histories again. As by default git pull is a git fetch + git merge, this will lead to a merge commit.

This isn't what you want after changing history as it will (partly) reverts you history changes. Unfortunately the hint of git status is a bit misleading...

What should you do after a rebase / changing history

After changing history (e.g. rebase), you need a force push so you will get that history also on the remote. You're telling git then "the history is different, but trust me, that's intended".

It's recommend to use a "force push with lease": git push --force-with-lease - see git push --force-with-lease vs. --force.

Steps to fix the current state

Luckily you could go back before the git pull by using the Git reflog!

This will fix the wrong pull and there won't be any conflicts to solve :)

So steps to do:

  1. Find correct commit in the reflog git reflog, so before the git pull (note: you could quit the reflog by typing q)
  2. Git reset to that commit, e.g. git reset 327fb961e --hard
  3. Double check and do a git push --force-with-lease.

Note: if you are making a mistake with git reset, you could use the git reflog again :)

Note 2: the reflog is only on your local machine

Upvotes: 12

Related Questions