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

GitGithubCommit

Git Problem Overview


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?

Git Solutions


Solution 1 - Git

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 - Git

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 - Git

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 - Git

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 - Git

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.

Solution 6 - Git

Solution:

If other developer had made their commits on remote, then you need to take git pull before doing your commit. If you do in this way you will never get extraneous “Merge branch” messages in the commit.

If in case you committed before taking git pull, then you need to take git pull --rebase and then you won't get extraneous “Merge branch” messages in the commit.

Also, Know these things:

  1. git pull --rebase What’s happening here? Git will rewind (undo) all of your local commits, pull down the remote commits then replay your local commits on top of the newly pulled remote commits.

  2. That's how the commit-graph looks when you push that extraneous “Merge branch” commit along with your commits.

commit-graph with extraneous “Merge branch” commit

  1. And, that's how the commit-graph looks when you take a prior git pull or take git pull --rebase after your commit.

commit-graph without extraneous “Merge branch” commit

Note:

  1. The difference in the number of commits you made in both the cases and the branch structure.

  2. Also, all this happens on the same branch, the branch gets merged with itself.

Solution 7 - Git

in my case i accidentally set some config with git config -e and git config --global -e for a project which caused the problem. i fixed it by removing both added configs. forexample i had these two lines in global config :

[pull]
    ff = false

and also in local config i had :

[pull]
    rebase = off

when i removed these two configs, i could pull changes without causing a merge commit.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmshafrirView Question on Stackoverflow
Solution 1 - GitpokeView Answer on Stackoverflow
Solution 2 - GitBill DoorView Answer on Stackoverflow
Solution 3 - GitgaborousView Answer on Stackoverflow
Solution 4 - GitLukeView Answer on Stackoverflow
Solution 5 - GitkclairView Answer on Stackoverflow
Solution 6 - GitHimanshu VermaView Answer on Stackoverflow
Solution 7 - GitZahra ShahrouziView Answer on Stackoverflow