Search code examples
gitgit-pushfast-forward

Git gives 'non-fast-forward updates' error even after 'git pull'


Github is the default repository for my project (just "origin" renamed to "github"). Something has happened so that "git push" causes a "non-fast-forward updates" error, even though "git push github master" works. "git pull" and "git pull github master" both indicate an up-to-date status. How can I (a) be sure there are no unmerged changes on Github and (b) correct the non-fast-forward error?

$ git status
# On branch master
nothing to commit (working directory clean)
$ git pull
Already up-to-date.
$ git pull github master
From github.com:MikeBlyth/mission_net
 * branch            master     -> FETCH_HEAD
Already up-to-date.
$ git push github master
Everything up-to-date
$ git push
To git@github.com:MikeBlyth/mission_net.git
 ! [rejected]        add_command -> add_command (non-fast-forward)
error: failed to push some refs to 'git@github.com:MikeBlyth/mission_net.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again.  See the
'Note about fast-forwards' section of 'git push --help' for details.

My git config file is

[core]
  repositoryformatversion = 0
  filemode = true
  bare = false
  logallrefupdates = true
[remote "github"]
  url = git@github.com:MikeBlyth/mission_net.git
  fetch = +refs/heads/*:refs/remotes/github/*
[branch "master"]
  remote = github
  merge = refs/heads/master
[remote "heroku"]
  url = git@heroku.com:joslink.git
  fetch = +refs/heads/*:refs/remotes/heroku/*
  merge = refs/heads/master
[remote "heroku"]
url = git@heroku.com:joslink.git
fetch = +refs/heads/*:refs/remotes/heroku/*

Solution

  • The syntax of 'git push' supports both an explicit and a shorthand version. The explicit version git push github master works for you. The shorthand version git push does not.

    If you use the shorthand version you do not tell git what remote to use and what local branch shall be pushed to what remote branch. Hence git has to guess what you mean.

    You can configure this with the setup of your remote and the push.default config:

       push.default
           Defines the action git push should take if no refspec is given on
           the command line, no refspec is configured in the remote, and no
           refspec is implied by any of the options given on the command line.
           Possible values are:
    
           ·    nothing - do not push anything.
    
           ·    matching - push all matching branches. All branches having the
               same name in both ends are considered to be matching. This is
               the default.
    
           ·    upstream - push the current branch to its upstream branch.
    
           ·    tracking - deprecated synonym for upstream.
    
           ·    current - push the current branch to a branch of the same
               name.
    

    Have a look at git branch -vv to check what branch is tracked by your current branch. Then check git config --get push.default to verify it is doing what you expect.