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.1
, develop
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
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:
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.