Search code examples
gitgit-mergegit-pullgit-subtree

When does git pull cause merge between multiple branches?


I'm trying to understand the circumstances that caused git to merge a feature branch I was working on into the main develop branch after switching to the develop branch.

I was able to revert the merge but it took the better part of a day to fully resolve and I'd like to avoid it in the future.

Here is the workflow:

After working on my feature branch I need to work on a bug fix. My feature branch (refs/heads/feature/uploader/90) has been kept up with the main develop branch with:

git merge origin/develop

Then I need to switch to the develop branch:

git checkout develop

git outputs:

Switched to branch 'develop' Your branch is behind 'origin/develop' by 88 commits, and can be fast-forwarded.

Then when I issue a pull:

git pull origin refs/heads/develop

For some reason it looks like git has decided to merge my feature branch into develop, the output looks like this:

branch develop -> FETCH_HEAD
Fast-forwarding to: 102301bcc51fc6d7978e5287df9d031d82e53bc9
Trying simple merge with d139bab0a96df01408f82110e38b6e0b6b98e6e6
Merge made by the 'octopus' strategy.

And my commit log shows me committing: Merge branches 'feature/uploader/90' and 'develop' of github.com:MakerStudios/dashboard into develop


Solution

  • This is what is known as a fast-forward merge.

    It happens (by default) any time you do a merge where all the changes in the branch on which you reside are already present in the branch you're trying to merge in.

    So, since in your above example refs/heads/feature/uploader/90 already contained all the changes in refs/heads/develop, instead of creating a true merge commit, git just moved the ref develop to point to the same commit as feature/uploader/90.

    You can avoid this behavior by doing git merge --no-ff, which will not fast-forward, or changing the merge.ff property to false.

    Undoing an undesired fast-forward merge is not as difficult as you make it out to be: just git reset --hard to the last commit before the stuff which came in on the merge.