601

Is it possible to do a git merge, but without a commit?

"man git merge" says this:

With --no-commit perform the merge but pretend the merge failed and do not autocommit,
to give the user a chance to inspect and further tweak the merge result before
committing.

But when I try to use git merge with the --no-commit it still auto-commits. Here's what I did:

$> ~/git/testrepo$ git checkout master
Switched to branch 'master'

$> ~/git/testrepo$ git branch
* master
  v1.0

$> ~/git/testrepo$ git merge --no-commit v1.0
Updating c0c9fd2..18fa02c
Fast-forward
 file1 |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

$> ~/git/testrepo$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)

A subsequent git log reveals all the commits from the v1.0 branch merged into master.

0

7 Answers 7

883

Note the output while doing the merge - it is saying Fast Forward.

In such situations, you want to do:

git merge <name-of-branch> --no-commit --no-ff

Important: If you do it this way, then you are not able to do any changes to the files in the staging area e.g. you can't remove/add files or make any changes to the files.

If you want to merge the changes and then commit as if you had manually typed all of the changes you merged in (as opposed to a traditional merge) you need to run rm .git/MERGE_HEAD afterward, which will force git to forget that the merge happened.

14
  • 11
    what if there's a confict. Commented Jan 3, 2015 at 5:06
  • 26
    @PineappleUndertheSea Fast forwards never cause conflicts. In case of "real" merge without fast forward the --no-commit switch is effective only if no conflict occurs, in case of conflict git will never auto-commit.
    – gronostaj
    Commented Jan 5, 2015 at 19:20
  • 56
    FYI: If you want to merge the changes and then commit as if you had manually typed all of the changes you merged in (as opposed to a traditional merge) you need to run rm .git/MERGE_HEAD afterward, which will force git to forget that the merge happened.
    – Jonn
    Commented Feb 27, 2016 at 0:23
  • 10
    FYI: Here is sample output for a successful merge: Automatic merge went well; stopped before committing as requested
    – kevinarpe
    Commented Mar 17, 2017 at 11:24
  • 10
    Apparently git merge BRANCHENAME --no-commit --no-ff left my workspace in a git "MERGING" state. Not quite sure what this does exactly, but a simple git stash save and git stash pop cycle seemed to return everything to normal; with just the modified files from the target branch in place as intended, and no longer a MERGING status.
    – MoonLite
    Commented Aug 15, 2017 at 14:49
70

You're misunderstanding the meaning of the merge here.

The --no-commit prevents the MERGE COMMIT from occuring, and that only happens when you merge two divergent branch histories; in your example that's not the case since Git indicates that it was a "fast-forward" merge and then Git only applies the commits already present on the branch sequentially.

4
  • 15
    That wouldn't (imo) necessarily clear up the confusion; I think this is one (relatively rare) time the docs are actually clear: git help merge => "With --no-commit perform the merge but pretend the merge failed and do not autocommit, to give the user a chance to inspect and further tweak the merge result before committing." The key of course is using it in conjunction with --no-ff
    – michael
    Commented Feb 12, 2013 at 0:58
  • 6
    ...maybe it would be less confusing to break from strict terminology and describe it this way: a "git merge" that does a fast-forward doesn't have a merge commit because there isn't actually a merge at all. This is in fact the ideal situation: fast-forwards are a Good Thing, and not having this extra "merge commit" Makes Sense. This is good default behavior and shouldn't be disabled. (In proper parlance, a fast-forward is a type of merge, but it isn't a "true merge".)
    – michael
    Commented Mar 27, 2013 at 8:32
  • 4
    it's relative to the policies of the project, in some cases it's useful to have/force those extra "merge commits" even when it's a ff because you need to mark the inclusion of the feature into the main branch.
    – Samus_
    Commented Jun 22, 2013 at 1:28
  • 10
    ...what. All right, I think git is pretty much unsalvageable. This answer in particular has convinced me to try Mercurial.
    – Rag
    Commented Apr 1, 2015 at 2:18
45

If you only want to commit all the changes in one commit as if you typed yourself, --squash will do too

$ git merge --squash v1.0
$ git commit
5
  • 1
    Is this the same effect as git merge v1.0 --no-commit --no-ff
    – jpierson
    Commented Aug 18, 2017 at 13:30
  • 5
    No, different effect. Squash creates a new commit with a new hash. It combines all the commits in a branch into one commit for the merge. Commented Jan 17, 2018 at 22:49
  • Can you explain a little bit more about the difference? Commented Mar 16, 2021 at 16:30
  • @KaviSiegel --no-squash will not create a commit automatically, user has to do that. In fact, --commit is not even allowed if --squash is used. So, merge --squash is kind of equivalent to copying all changes (from all commits) from the other branch and doing git add on those.
    – Mohnish
    Commented Oct 8, 2021 at 15:38
  • This dose the trick! Commented Nov 7, 2023 at 14:00
38

I prefer this way so I don't need to remember any rare parameters.

git merge branch_name

It will then say your branch is ahead by "#" commits, you can now pop these commits off and put them into the working changes with the following:

git reset @~#

For example if after the merge it is 1 commit ahead, use:

git reset @~1

Note: On Windows, quotes are needed. (As Josh noted in comments) eg:

git reset "@~1"
2
  • 6
    On windows, quotes are needed: git reset "@~1"
    – Josh
    Commented May 29, 2018 at 22:33
  • 2
    Way better than the accepted answer! Very logical and easy to follow. Tip for GIT GUI'ers: In the Vizualize All Branch, merge the target branch, right-click the commit you were and Reset main branch to here in default mode (AKA "Mixed, leave working tree untouched, reset index") Commented Jan 19, 2023 at 3:39
6

When there is one commit only in the branch, I usually do

git merge branch_name --ff
2

You could also do

git cherry-pick <commit hash> 

for each commit if you want to preserve the commit history...

I'm not really seeing a "nice" way to merge multiple commits from another branch with the git merge command without it adding a merge commit at some point (i.e. only having the commits you want to include)

1

Old question with many answers, but this is too big for a comment.


As another answer mentioned, merging v1.0 into master resulted in a fast-forward merge. In fact, there really was no merge. The v1.0 tag had a commit whose parent commit was the tip of master. Got just advanced the pointer for master ahead one commit.

If doing that introduces an bad merge, what you *really" gave us a bad commit at the v1.0 tag.

The more appropriate solution is to do the fast forward merge of v1.0 into master, the add a commit to master correcting the bad code. After that either delete the v1.0 tag and recreate it, or retag v1.0 and force push the tag. Better yet, create a v1.0.1 tag from the commit that fixes v1.0.

Every other answer points you too the wrong solution from a coding standpoint.

Not the answer you're looking for? Browse other questions tagged or ask your own question.