Git pull results in extraneous "Merge branch" messages in commit log

56,908

Solution 1

The commit you are seeing is perfectly fine. A pull effectively runs git fetch and then git merge so a merge is usually happening when you run git pull.

The alternative to use rebasing instead of merging is possible, but usually you should avoid it. Rebasing allows you to keep a linear history, but also removes any information about the branching that originally happened. It will also cause the history of the current branch being rewritten, recreating all commits that are not contained in the target branch (in your case, the remote). As the recreated commits are different commits, this can cause a lot of confusion when developing together with others, especially when people already checked out parts of those commits before they get rewritten (for example with feature branches). So as a rule of thumb, you should never rewrite any commit that was already pushed.

The commits you see are there to combine two (or more) branches. It is perfectly fine to have a commit that does nothing else then merging multiple branches. In fact it makes it very clear when you have a merge commit that combines branches when looking at the history. In comparison to rebasing, merging also allows you to effectively see the original history as it was developed, including the actual branches that coexisted.

So, long story short: Yes, having merge commits is perfectly fine and you should not worry about them.

Solution 2

This answer has been revised, as my understanding, diagrams, and conclusions were incorrect.


git pull causes merge commits because git is merging. This can be changed by setting your branches to use rebase instead of merge. Using rebase instead of merge on a pull provides a more linear history to the shared repository. On the other hand, merge commits show the parallel development efforts on the branch.

For example, two people are working on the same branch. The branch starts as:

...->C1

The first person finishes their work and pushes to the branch:

...->C1->C2

The second person finishes their work and wants to push, but can't because they need to update. The local repository for the second person looks like:

...->C1->C3

If the pull is set to merge, the second persons repository will look like.

...->C1->C3->M1
      \      /
       ->C2->

Where M1 is a merge commit. This new branch history will be pushed to the repo. If instead, the pull is set to rebase the local repo would look like:

...->C1->C2->C3

There is no merge commit. The history has been made more linear.

Both choices reflect the history of the branch. git allows you to choose which history you prefer.

There are indeed places where rebase can cause a problem with remote branches. This is not one of those cases. We prefer to use rebase as it simplifies an already complicated branch history as well as shows a version of the history relative to the shared repository.

You can set branch.autosetuprebase=always to have git automatically establish your remote branches as rebase instead of master.

git config --global branch.autosetuprebase always

This setting causes git to automatically create a configuration setting for each remote branch:

branch.<branchname>.rebase=true

You can set this yourself for your remote branches that are already setup.

git config branch.<branchname>.rebase true

I would like to thank @LaurensHolst for questioning and pursuing my previous statements. I have certainly learned more about how git works with pull and merge commits.

For more information about merge commits you can read Contributing to a Project in ProGit-Book. The Private Small Team section shows merge commits.

Solution 3

You can do:

git pull --rebase

However, this will always put your changes on top of your collaborators'. But you won't get any polluting merge message.

Solution 4

There is actually a much simpler answer to this. Just have developer B do a pull BEFORE making his commit. This will prevent those merge commits, since they're caused by the history you've created on your local repo from your local commit trying to merge with the history of the commits on the remote repo. If you get a message saying something along the lines of 'changes will be overwritten' when doing a pull, it just means you both touched the same file, so do:

git stash
git pull
git stash pop

then you can resolve any merge conflicts if there are any.

Solution 5

Doing a git pull will insert the "Merge branch" messages, that's just what it does. By doing a git pull, you have merged the remote branch into your local branch.

When you do a git pull and there are conflicts, the git log will show the updates to the conflicted files as coming from the user that resolved the conflicts. I assume this is because the person that fixes the conflict re-commits the file.

As far as I know that's just how git works, and there is not a way around it.

Rebasing will blow away the git history, so you won't be able to see when merges occurred.

Share:
56,908
mshafrir
Author by

mshafrir

Languages: Ruby, Python, Java, Javascript, Coffeescript, C#

Updated on June 27, 2021

Comments

  • mshafrir
    mshafrir about 3 years

    I'm working with another developer on a project, and we're using Github as our remote repo. I'm on a Mac using git 1.7.7.3, he's on Windows using git 1.7.6.

    This is what's happening

    1. One of us (let's call him developer A, but it doesn't matter which one) pushes a set of commits to GitHub.
    2. The other (developer B) makes some local commits.
    3. B does a git pull.
    4. B does a git push.
    5. Looking at the commit history log, I see Merge branch 'master' of github.com:foo/bar

    The commit log gets littered with "Merge branch" messages over time, and also shows developer B as committing changes that developer A made. The only way we've found to prevent this issue has been to do a git pull --rebase at step 3, but I don't know what side effects rebasing will introduce. This is my first time working on a multi-developer git repo, so is this just normal behavior? Any thoughts on how to solve this issue?

  • Laurens Holst
    Laurens Holst over 12 years
    “Using rebase instead of merge on a pull provides the correct history to the shared repository. Using merge provides a false history.” — What’s the rationale backing up this rather bold statement? There is no way a history with merges is ‘false history’. It is an accurate depiction of the order in which things happened. What you’re doing by rebasing is actually altering history, to create a slightly more linear version of it. You sacrifice accuracy for aesthetics. Maybe something you prefer to do, but in no way more truthful.
  • Bill Door
    Bill Door over 12 years
    Using rebase instead of merge does not sacrifice accuracy for aesthetics. We use --no-ff for merges, so aesthetics is not a requirements. Accuracy is a desire. Rebase provides that accuracy.
  • Laurens Holst
    Laurens Holst over 12 years
    How is the rebased history more accurate? You don’t clarify this, and I don’t see how it would be.
  • Bill Door
    Bill Door over 12 years
    History is a reflection of the time at which commits occurred in the shared repo. One day 1, the shared repo saw commit C2. On day 2, the shared repo sees commit C3. If C3 came before C2 then the reflection of time would not be correct. C3 did not come before C2. All that rebase, does is re-organize the commits on the local repository to properly reflect the history shown by the shared repository.
  • Laurens Holst
    Laurens Holst over 12 years
    I don’t see why that first sentence would be true. This is how it works with SVN, but that’s more of an artefact of its limitations than an actual reflection of history. SVN forgets everything that happened locally, while Git records it. By rebasing instead of merging you’re filtering this out. I’m perfectly fine if this is what you want to do, but it is an aesthetic choice, and claims that a history which does not do this filtering would be false are absolutely un-true. It is a more complete representation history.
  • Bill Door
    Bill Door over 12 years
    Your questions caused me to review my understanding of merge commits. My diagram is incorrect. I am revising the discussion. My conclusions are also incorrect. The history for rebase and merge are equally correct. You can make your own choice.
  • Meligy
    Meligy about 12 years
    Very good answer. I myself tried the rebase style since it was recommended in some open source projects contribution guidelines, and it caused me problems. A new member in the team had the same too. I think the rebase option isn't for teams working together all day, but is correct for projects that have main contributors and other contributors who just submit patches. Those should be fine fetching main repo and rebasing their changes just before their issue a pull request.
  • sTodorov
    sTodorov over 11 years
    @poke, is it possible, though, there to be no changes on the github remote repository and, still, when you pull, there to be a commit of this type (merge branch master of github.com...)? I've seen that happen a couple of times.
  • poke
    poke over 11 years
    @sTodorov If there are no new changes, then the fetch-part of the pull will do nothing, but the merge is still being executed. So if your current local branch is not up-to-date, it will merge the new changes into your branch. And if it can’t do a fast-forward merge (if you have diverging commits), then it will create a merge commit.
  • sTodorov
    sTodorov over 11 years
    @poke, thanks for the answer. It explains why I get the extra commit from time to time.
  • bob esponja
    bob esponja about 10 years
    This answer makes it seem like using rebase as the OP has described is dangerous, but it isn't. Rebasing at step 3 doesn't rewrite the entire history. Only the local commits that haven't been pushed are rewritten by being reapplied on top of the new HEAD (the latest commit pushed to that branch). This prevents the extraneous merge commits and has no other side effects.
  • poke
    poke about 10 years
    @bobesponja All commits that are not on the pulled remote branch are rewritten. This can include published commits from other branches, e.g. with feature branches, which others may already have accessed before. As such, yes, rebasing without thinking about what you rebase is somewhat dangerous.
  • bob esponja
    bob esponja about 10 years
    @poke which scenario would include published commits from other branches in the current branch to be rebased? The only one I can think of is by rebasing the published feature branch onto the current branch which seems to go against all the rebasing guidelines I've read. I'm interested as I fetch and rebase upstream changes rather than pulling and merging.
  • poke
    poke about 10 years
    @bobesponja Yes, if you are publishing your feature branch early (because others work on it, or simply as backup), then you shouldn’t rebase it because others could already have fetched it. Rebasing then—as you say yourself—goes against rebasing guidelines which I stated in my answer. However, if you don’t publish your commits, then rebasing is fine if you want and don’t mind the linear history. But it depends on how you work, so the general answer is to avoid it unless it’s really safe. Btw. I revised my answer, so if the issue is resolved, I would appreciate if you removed your downvote.
  • bob esponja
    bob esponja about 10 years
    @poke Isn't that a different situation from the one described by the OP though? They describe two (or more) people working on the same branch, pulling each other's changes. Not rebasing already published commits. This answer[1] describes the situation I'm understanding. In the OP's case "all commits that are not contained in the target branch (in your case, the remote)" are exclusively local, non published commits. There is no branching information to be lost as the purpose is solely to pull in changes. Thanks for discussion, I removed the downvote [1]: stackoverflow.com/a/4675513/19927
  • poke
    poke about 10 years
    @bobesponja Yes, I agree, in OP’s exact case it wouldn’t be a problem, and depending on the workflow it might be the desirable action. But I think it doesn’t hurt to always mention the problems that can occur from rebasing ;)
  • Hi-Angel
    Hi-Angel almost 8 years
    But, wouldn't those messages seen when I do a pull request?
  • poke
    poke almost 8 years
    @Hi-Angel I’m not sure what you’re referring to. What messages?
  • Hi-Angel
    Hi-Angel almost 8 years
    @poke the extraneous “Merge branch” messages in commit log ☺ But never mind, since I commented, I pushed a code to github, and I didn't see this message there.
  • poke
    poke almost 8 years
    @Hi-Angel You will get that commit if the one responsible for closing the pull request decides to merge the changes, yes. But they could equally rebase it (or simply decline it ^^). But as said before, it’s not “extraneous”; it has a purpose and it’s fine being there.
  • Hi-Angel
    Hi-Angel almost 8 years
    @poke no, I didn't mean PR, I just pushed to my fork, and though I see in the local log the message, but the github site says that I'm 2 commits ahead, and none of them has the message.
  • user2061057
    user2061057 over 7 years
    Merging almost always results in a horrible mess in the history that's also impossible to bisect so I always prefer rebase. This answer spreads biased and incorrect information about rebase - please stop upvoting it!
  • poke
    poke over 7 years
    @user2061057 Whether you prefer rebasing or not is your personal preference. There are people and teams that care about maintaining a linear history and there are those that don’t, or even prefer having the original branch structure persisted in the history. The things I explain about both merging and rebasing are facts, allowing people to form their own opinion.
  • Green
    Green over 6 years
    Upvote for simple ascii art graphical representation of the difference. Accepted answer doesn't have it
  • Green
    Green over 6 years
    Most annoying and anxious are exactly merge conflicts. I rather avoid it
  • Zoso
    Zoso over 6 years
    @Green If you're worried about merge conflicts then even git pull's no different.
  • linuxNoob
    linuxNoob over 5 years
    Except that one time when you forget to stash before you pull. Ugh git requires me to be at the top of my game all the time.
  • vonbrand
    vonbrand about 5 years
    Need to git pull --rebase to integrate remote changes before the local ones, regardless.
  • autopilot
    autopilot about 2 years
    @poke your explanation makes perfect sense, in fact, this is the most appropriate way of collaborating workflow. I have a question though, why is a merge happening when the same user commiting from two different locations? For example, I updated the README.md file on GitHub and commits other changes from my desktop with the same user, and got a merge commit. Why is so?
  • poke
    poke about 2 years
    @autopilot The user doing a commit is actually not important. What matters there is that your branch on GitHub is a separate branch from the branch on your computer. If you make commits on each side without pushing or pulling in between, then you still have two branches that are diverging, so you need to merge.