Can I make fast forwarding be off by default in git?

84,777

Solution 1

Yes, there is --no-ff. You can configure merge options per branch, e.g.

git config branch.master.mergeoptions  "--no-ff"

adds the following to your $(REPO)/.git/config file:

[branch "master"]
    mergeoptions = --no-ff

Footnote: speaking of my experience, I eventually found switching fast-forward to off was mostly helpful for git newcomers - however once the feel for workflows and concepts start to sink in you definitely want to avoid blurring your log graph with tons of pointless 'merged remote ..blarf' type commits.

Footnote 2, a decade later: the other answers below provide more modern config options, but really, you probably DO want to stay with the defaults (i.e. fast-forward whenever possible) in this day and age, because empty merge-commits really only make the history much more difficult to reason about.

Solution 2

It seems there is still a pending question in the thread: How to do it globally (i.e. for all branches) ? For the records, we can use the following:

git config --add merge.ff false

...to make it apply to all branches in the current repository. To make it apply to all branches in all repositories where someone has not run it without the --global option (local settings override global) run this:

git config --global --add merge.ff false

From the documentation:

merge.ff
By default, git does not create an extra merge commit when merging a commit that is a descendant of the current commit. Instead, the tip of the current branch is fast-forwarded. When set to false, this variable tells git to create an extra merge commit in such a case (equivalent to giving the --no-ff option from the command line). When set to only, only such fast-forward merges are allowed (equivalent to giving the --ff-only option from the command line).

Solution 3

Reading the thread of answers I ended up using the following two options

git config --global pull.ff only # Disallows non ff merges on pull. Overrides merge.ff when pulling
git config --global merge.ff false # even create extra merge commit when fast forward merge would be possible

Only loosely related I've also found this setting avoids trouble during pull

git config --global pull.rebase true # set up pull to rebase instead of merge
Share:
84,777

Related videos on Youtube

Jason Baker
Author by

Jason Baker

I'm a developer on Google's Cloud Console.

Updated on December 25, 2020

Comments

  • Jason Baker
    Jason Baker over 3 years

    I can't really ever think of a time when I would use git merge rather than git rebase and not want to have a commit show up. Is there any way to configure git to have fast forwarding off by default? The fact that there's an --ff option would seem to imply that there's a way, but I can't seem to find it in the documentation.

    • CB Bailey
      CB Bailey about 14 years
      I use merge all the time for branches when haven't made any commits off their remote in order to fast-forward them. It seems the simplest and safest way to do this. I'm curious, you obviously have a use case. Why would you ever want to create a merge commit where there are no commits on one side of the branch?
    • Jason Baker
      Jason Baker about 14 years
      I use branches to create a logical grouping of commits. So if I make a merge, it's basically a way to say "these commits go together". You can almost think of it as a poor man's interactive rebase and squash. :-)
    • steinybot
      steinybot over 11 years
      Turning off fast forwarding is extremely useful, particularly when following a model like A successful Git branching model
    • rjmunro
      rjmunro over 8 years
      Please change the accepted answer for this to Eric Platon's answer stackoverflow.com/a/6810687/3408 - I did the steps in the accepted answer, then realised that it was only for the master branch in the current repository, which is silly.
    • jpmc26
      jpmc26 about 8 years
      @Steiny No, it just makes your repository a mess: endoflineblog.com/gitflow-considered-harmful.
    • steinybot
      steinybot about 8 years
      @jpmc26 Each to their own I guess. I happen to disagree with that article. Finding the two parents of a merge commit is not hard and tells you exactly what the changes were. Then you can take those changes and do a "rebase onto" some other branch. With the flat model you have to manually find and cherry pick. We choose to embrace branching. Sure it is complex when looking at the entire tree but that is the reality, multiple changes occurring in parallel. Flattening everything just hides what really happened.
    • jpmc26
      jpmc26 about 8 years
      @Steiny Yes, it does hide "what really happened." And that's a good thing. It cuts out irrelevant details no one needs to care about and preserves the ones that are important; that's what good documentation does. Finding the parent of a single merge is not hard, true. Tracing back across 100 commits over 4 branches with a lot of criss crossing trying to figure out what actually changed and where does not seem especially easy, especially when those commits may or may not actually introduce changes to the code base. (This is what Gitflow recommends/requires.)
    • Brian Ogden
      Brian Ogden over 6 years
      @jpmc26 You are making claims that are very strong and biased, you literally said "No, it just makes your repository a mess" regarding this article nvie.com/posts/a-successful-git-branching-model, while this Git workflow might not work for you, it works for some enterprise teams
    • Suma
      Suma over 5 years
      I understand git config changes the settings per user. Is there a way to disable fast forwarding for the repository (for all users), creating a kind of "repository merge policy"?
    • Steve Summit
      Steve Summit about 2 years
      I think the comments (and the referenced blog post) about the way a non-fast-forward merge "makes your repository a mess" are missing the point. That "mess" is not the result of a complicated merge structure — it's the result of the lack of good tools for visualizing a complicated merge structure. A fast-forward merge "removes" the mess — but in doing so, it erases history, creating a sanitized version which can, yes, be more easily viewed using a meager one-dimensional log viewer.
  • conny
    conny about 14 years
    Learning git is a bit like mountain climbing; but instead of starting with small cliffs and progressing to tougher ones, git makes you climb the same mountain again and again, only to fall at different heights each time, every time just as surprised that the lifeline wasn't attached.
  • Tom Mayfield
    Tom Mayfield almost 14 years
    Does this affect "git pull" and its merge strategy at all?
  • Michelle Tilley
    Michelle Tilley over 13 years
    @Thomas: Yes; git pull is git fetch + git merge.
  • Tony R
    Tony R about 13 years
    This looks good, but is there any way to do it globally, for all branches, instead of having to set it up for every branch?
  • Chris Johnsen
    Chris Johnsen almost 13 years
    Note: merge.ff was introduced in Git 1.7.6. It is not effective in older versions.
  • andriy
    andriy over 12 years
    For people using Git 1.7.6, this is the best and simplest solution.
  • Dalibor Filus
    Dalibor Filus over 12 years
    Beware of the dragons. This option is dangerous just as @Thomas said... Every git pull creates merge commit. git pull --ff doesn't override the mergeoptions=no-ff in git config.
  • stigi
    stigi almost 12 years
    I'm using this together with an alias puff = "pull --ff --ff-only"
  • Bob Kerns
    Bob Kerns over 11 years
    Regarding the footnote -- instead of 1 "pointless" "merged branch fiddle-around" commits -- we get the entire "fiddle-around" series of commits merged onto our master. Often including a half-dozen merge commits. If you have the merge commits, you can ignore the detailed feature commits, and get the big overview, like this: $ git log --first-parent --pretty=oneline'feature-1'" c605cca334c722a34e3aea88c36a043ab3cca741 Merge branch 'feature-2' f93a46a24bd0761da0a1bd64b2da0549980979c8 Merge branch 'feature-1' 163602263b4f0a8463c6de82d3a7dd7b4c04ebca project inception
  • pedromanoel
    pedromanoel about 11 years
    I really like the alias option, since your pulls won't result in a merge commit always.
  • cregox
    cregox over 10 years
  • jotomo
    jotomo over 9 years
    Theres is also (now, see git-scm.com/docs/git-config) the option pull.ff which can be set to only, which will do the same as the alias.
  • Eric Platon
    Eric Platon over 9 years
    Thank you, @jotomo. That feature is available from Git v2.0.0 (from commit b814da891e8261b909fc5d9fb07b4e8b13989c2d).
  • Kadarach
    Kadarach over 9 years
    What if I'm just tired of typing git merge --no-ff (branchname)? And I want git pull to function as it always has?
  • andriy
    andriy almost 9 years
    You probably wouldn't want to set this up for your master branch. Where it's most useful is small feature branches, where you'd like to be able to see all the commits on that feature branch as distinct from other commits.
  • rjmunro
    rjmunro over 8 years
    If you want a non-fast-forward merge, use rebase. A fast forward merge is really a rebase as rebase naturally doesn't add merge commits. Set git pull to use rebase using git pull --rebase or configure it with git config --global pull.rebase true
  • rjmunro
    rjmunro over 8 years
    You could also use rebase for git pull, to prevent merge commits. Use git pull --rebase or configure it as default with git config --global pull.rebase true. If you have not made any commits, this works identically to merge --ff. If you have made some commits to the branch locally, but not pushed them, they will be added to the end of the branch, rather than merged in. This is usually what you want.
  • Eric
    Eric over 7 years
    This helped a lot! I would like to add for those who are interested you can also set other subcommand options by simply replacing the --no-ff with any other subcommand. I recently found this setting to be very beneficial. git config branch.<branchName>.mergeoptions "--log" To allow the --log subcommand to track in the merge commit the subject of all the commits being merged into the specified branch.
  • orzechow
    orzechow about 7 years
    @DaliborFilus Tame the dragons: git config branch.autosetuprebase always This enables fast-forward for the master branch when pulling, even with branch.master.mergeoptions "--no-ff"
  • wayofthefuture
    wayofthefuture over 6 years
    Is there a way to only make this apply when merging branches and not when doing a git pull?
  • Gendolph
    Gendolph about 6 years
    Since Git 2.4.3 you can specify pull.ff (to true) config options to override mergeOptions for pull command.
  • Pylinux
    Pylinux about 6 years
    FYI: This is just for the master branch, if you want for all branches you need @eric-platon's answer
  • zowers
    zowers over 4 years
    git config --global pull.rebase true # notice 'true' at the end of the line
  • bastian
    bastian over 4 years
    Thanks @zowers I've fixed this
  • Dennis Kassel
    Dennis Kassel almost 4 years
    Since nobody has mentioned this in the answer, I would like to add, that this option has side effects on how "git pull" works. I have experienced, that "git pull" will implicitly create a separate merge-commit, even though fast-forwarding the branch was possible.
  • bigbear3001
    bigbear3001 about 3 years
    For it to work on our systems i needed git config --global --bool merge.ff false (git version 2.20.1)
  • perepm
    perepm about 3 years
    I believe that the peace of mind of knowing that you can undo any faulty merge with a simple git reset HEAD~1 simply overtakes any inconvenience of always merging with a new commit. In fact, I'd mark (@eric-platon's)[stackoverflow.com/a/6810687/8699916] answer as correct. By doing what he says, pull stays the same.
  • mellow-yellow
    mellow-yellow over 2 years
    Yes! The top-ranked answer misses this. Also, Git Common Flow, arguably the de-facto standard, says, "It is RECOMMENDED that all branches be merged using git merge --no-ff " but when you're pulling, merge has already happened, so this seems the like best answer in 2021--at least to me.