John Smith
John Smith

Reputation: 7407

Why is Git merge creating multiple commits on master branch?

There are two branches I am working with, master and newFeature. While building the "new feature", I added multiple commits to the newFeature branch. My understanding of git merge is that it will create a single commit on master once the branches are merged, however when merged, master now has the full commit history that is on newFeature. For example-

master (pre-merge):

    1=>2=>3

newVersion:

    1=>2=>3=>4=>5=>6

master (actual results of merge):

    1=>2=>3=>4=>5=>6

master (expected results of merge):

    1=>2=>3=>6

Is there any way to remove the intermediary commits from newVersion during the merge, and why isn't merge working as expected?

Upvotes: 10

Views: 7658

Answers (2)

John Smith
John Smith

Reputation: 7407

The key to note here, is that no changes have been made to master throughout the course of your work on newVersion. In these situations, Git defaults to a "fast-forward" merge, which can essentially be thought of as taking all of the new commits from newVersion and appending them to the most recent commit on master (which does not separate the commit history that was done on newVersion). This can be overridden with the --no-ff flag, for example:

git merge newVersion --no-ff

Results in:

master (pre-merge):

    1=>2=>3

newVersion:

    1=>2=>3=>4=>5=>6

master (actual results of merge):

    1=>2=>3=========>7
            4=>5=>6

Note that, commit 7 represents the merge, and does not replace the commit history.

Reference: https://sandofsky.com/images/fast_forward.pdf

Alternatively, if you would prefer to consolidate the entire commit history of newVersion into a single commit on master (could be useful if they were simply minor commits throughout the progression of the "new version") you could run the merge with the --squash flag. For example:

git merge --squash newVersion

Results in:

master (pre-merge):

    1=>2=>3

newVersion:

    1=>2=>3=>4=>5=>6

master (actual results of merge):

    1=>2=>3=>7

Note that, 7 consolidates the commit history that was done in commit 4 - 6

Upvotes: 13

Michael Mior
Michael Mior

Reputation: 28752

It's not possible to have a final history that looks like what you want. Each commit in git is tied to its parent. Each commit contains a reference to its parent, so 6 explicitly references 5.

If you do actually want only the changes between 5 and 6 to be added on top of 1=>2=>3, then you can use git cherry-pick newFeature. This will create a new commit which has just the changes between 5 and 6, but applied on top of 3.

If you want all the changes from 4, 5, and 6 but you only want a single commit, then you can use the --squash flag to git merge. This will create a single new commit which contains all the changes from 4, 5, and 6. However, your history will not be 1=>2=>3=>6, but 1=>2=>3=>7 where 7 is this new commit.

Note that if you choose the --squash option, you can only do this once for each branch since by squashing, you're losing the information about what's different between the two branches.

Upvotes: 1

Related Questions