Cyberithub

Solved: git pull resolves as a fast forward and not creating a merge commit

Advertisements

In this article, we will see what need to be done when git pull is resolving as a fast forward and not creating a merge commit. Sometimes you might have observed that when you are trying to fetch and merge the changes from remote branch to the current local branch using git pull command, then the changes are resolving as Fast Forward(FF) and not really creating a merge commit.

This poses a challenge when you have to push the changes to a different remote branch. Since there is no new commit, nothing will get pushed. While this is a very common problem faced by many Git users, the fix is quite simple. But before providing with the solution let's understand our current Lab setup so that you can compare the same with yours and see if the below given fix helps you as well.

Lab Setup

In my Lab setup, I am using example-app repo which is having three branches  - release-1.0.1develop and master. Usually develop and master branch contains the same files. In other words, develop is the exact replica of master. But since the master is critical for production, all the release branches starts from develop. Here we have created release-1.0.1 branch from develop. This branch contains all the files from the develop and the added changes that we want to deploy in our application 1.0.1 release.

Once my release branch is ready we are going to merge this branch to master post approval because as per our branching strategy all the deployment can only happen from master. Hence we are going to first merge the release-1.0.1 branch with master and then to develop. So that both master and develop contain the same files.

Solved: git pull resolves as a fast forward and not creating a merge commit

Solved: git pull resolves as a fast forward and not creating a merge commit

Also Read: How to Merge Git Release Branch with both Master and Develop

First we need to clone the example-app repo to the local system using below git clone command. Below command will create a local directory example-app and copy all the repo contents into it.

cyberithub@ubuntu:~$ git clone https://app.cyberithub.com/bitbucket/scm/application/example-app.git
Cloning into 'example-app' ...
remote: Enumerating objects: 499, done.
remote: Counting objects: 100% (499/499), done.
remote: Compressing objects: 100% (332/332), done.
remote: Total 981 (delta 324), reused 454 (delta 332), pack-reused 876
Receiving objects: 100% (981/981), 1.01 MiB | 156.000 KiB/s, done.
Resolving deltas: 100% (820/820), done.
Updating files: 100% (267/267), done.

Then we need to change our directory to example-app and check the current branch using git branch command. As you can see below, by default only develop branch got replicated in our local copy of the repo.

cyberithub@ubuntu:~$ cd example-app
cyberithub@ubuntu:~/example-app$ git branch
* develop

So here we will create a new local master branch and switch into it using git checkout -b master command as shown below.

cyberithub@ubuntu:~/example-app$ git checkout -b master
Switched to a new branch 'master'

You can verify the current branch by using git branch command as shown below.

cyberithub@ubuntu:~/example-app$ git branch
  develop
* master

Then we will check for any latest changes in the remote master branch using git pull origin master command as shown below.

cyberithub@ubuntu:~/example-app$ git pull origin master
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

git config pull.rebase false # merge (the default strategy)
git config pull.rebase true # rebase
git config pull.ff only # fast-forward only

You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.

From https://app.cyberithub.com/bitbucket/scm/application/example-app.git
* branch master -> FETCH_HEAD
Already up to date.

Now when I try to fetch and merge the changes from remote release-1.0.1 branch to master using git pull origin release-1.0.1 command then I noticed that the changes are getting resolved as fast forward and not really creating a merge commit.

cyberithub@ubuntu:~/example-app$ git pull origin release-1.0.1
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

git config pull.rebase false # merge (the default strategy)
git config pull.rebase true # rebase
git config pull.ff only # fast-forward only

You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.

From https://app.cyberithub.com/bitbucket/scm/application/example-app.git
* branch release-1.0.1 -> FETCH_HEAD
Updating 6049e2f..bc76b8d
Fast-forward
 config/test.yaml  | 2 +-
 config/hello.yaml | 2 +-
 2 Files changed, 4 insertions(+), 4 deletions(-)

As you can see from the above output, git is doing the fast-forward because we are merging a branch that is ahead of the branch we have checked out. To solve this problem, we need to use --no-ff switch with git pull command as shown below. This switch will create a merge commit even when the merge resolves as a fast-forward.

NOTE:

Please note that before proceeding with the below steps, I would strongly recommend you to start from the beginning to avoid any unforeseen error as you already ran git pull command above without --no-ff switch so continuing with the below command would might create some unexpected result. To avoid all this, please start from cloning the repo again.
cyberithub@ubuntu:~/example-app$ git pull origin release-1.0.1 --no-ff
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

git config pull.rebase false # merge (the default strategy)
git config pull.rebase true # rebase
git config pull.ff only # fast-forward only

You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.

From https://app.cyberithub.com/bitbucket/scm/application/example-app.git
* branch release-1.0.1 -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 config/test.yaml  | 2 +-
 config/hello.yaml | 2 +-
 2 Files changed, 4 insertions(+), 4 deletions(-)

Now if you check the commit ID using git log command then you will notice a commit is created and HEAD is now pointing to master branch in that commit.

cyberithub@ubuntu:~/example-app$ git log
commit a287db7ea8768baf9fc79369ba318376 (HEAD -> master)
Merge: b00dccf ea0d6b4
Author: Admin <admin@cyberithub.com>
Date: Thu Sep 1 13:47:16 2022 +0530

Merge branch 'release-1.0.1' of https://app.cyberithub.com/bitbucket/scm/application/example-app.git

commit c842ac8e7df8bf9549af9c617b21849 (origin/develop, origin/HEAD, develop)
Merge: b00dccf ea0d6b4
Author: John <john@cyberithub.com>
Date: Wed Aug 31 10:04:00 2022 +0530
............................................................

Now that a commit is generated, you can push the changes to the remote branch. Here we are pushing all the changes to remote master branch using git push -u origin master command. As you can see below, all the changes are getting pushed successfully. This confirms that our problem is solved now. We can now proceed with the rest of the activity.

cyberithub@ubuntu:~/example-app$ git push -u origin master
Enumerating objects: 16, done. 
Counting objects: 100% (16/16), done. 
Compressing objects: 100% (1/1), done. 
Writing objects: 100% (2/2), 565 bytes | 565.00 KiB/s, done. 
Total 2 (delta 1), reused 0(delta 0), pack-reused 0 
remote: Checking connectivity: 2, done.
remote:
remote: Create pull request for master:
remote: https://app.cyberithub.com/bitbucket/scm/projects/EXAMPLE/repos/example-app/pull-requests?create&sourceBranch=refs/heads/master
remote:
To https://app.cyberithub.com/bitbucket/scm/application/example-app.git
768ca03..9acb8ca master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

Hopefully, above solution worked for you as well. Please let me know your feedback on the comment box.

Leave a Comment