Git reset –hard and a remote repository

I had a repository that had some bad commits on on it (D, E and F for this example).

A-B-C-D-E-F master and origin/master

  • git - does it work on image?
  • Eclipse + Maven + Git + Multi-Module projects = Unhappiness
  • Unexpected merge error in a git svn system?
  • How to clone from github from behind corporate proxy
  • No refs in common and none specified; doing nothing
  • How does npm version work?
  • I’ve modified the local repository specifically with a git reset hard. I took a branch before the reset so now I have a repo that looks like:

    A-B-C master  
         \ D-E-F old_master
    
    A-B-C-D-E-F origin/master
    

    Now I needed some parts of those bad commits so I cheery picked the bits I needed and made some new commits so now I have the following locally:

    A-B-C-G-H master
         \ D-E-F old_master
    

    Now I want to push this state of affairs to the remote repo. However, when I try to do a git push git politely gives me the brush off:

    $ git push origin +master:master --force  
    Total 0 (delta 0), reused 0 (delta 0)  
    error: denying non-fast forward refs/heads/master (you should pull first)  
    To git@git.example.com:myrepo.git  
    ! [remote rejected] master -> master (non-fast forward)  
    error: failed to push some refs to 'git@git.example.com:myrepo.git'  
    

    How do I get the remote repo to take the current state of the local repo?

  • Git Merge without removing the other branch to pull the changes
  • How do I load a specific git commit?
  • How to branch and merge properly with Git?
  • migrate git to perforce import
  • How to run release:perform from a given Git tag?
  • Git and “The branch 'x' is not fully merged” Error
  • 4 Solutions collect form web for “Git reset –hard and a remote repository”

    If forcing a push doesn’t help (“git push --force origin” or “git push --force origin master” should be enough), it might mean that the remote server is refusing non fast-forward pushes either via receive.denyNonFastForwards config variable (see git config manpage for description), or via update / pre-receive hook.

    With older Git you can work around that restriction by deleting “git push origin :master” (see the ‘:’ before branch name) and then re-creating “git push origin master” given branch.

    If you can’t change this, then the only solution would be instead of rewriting history to create a commit reverting changes in D-E-F:

    A-B-C-D-E-F-[(D-E-F)^-1]   master
    
    A-B-C-D-E-F                             origin/master
    

    To complement Jakub’s answer, if you have access to the remote git server in ssh, you can go into the git remote directory and set:

    user@remote$ git config receive.denyNonFastforwards false
    

    Then go back to your local repo, try again to do your commit with --force:

    user@local$ git push origin +master:master --force
    

    And finally revert the server’s setting in the original protected state:

    user@remote$ git config receive.denyNonFastforwards true
    

    Instead of fixing your “master” branch, it’s way easier to swap it with your “desired-master” by renaming the branches. See https://stackoverflow.com/a/2862606/2321594. This way you wouldn’t even leave any trace of multiple revert logs.

    The whole git resetting business looked far to complicating for me.

    So I did something along the lines to get my src folder in the state i had a few commits ago

    # reset the local state
    git reset <somecommit> --hard 
    # copy the relevant part e.g. src (exclude is only needed if you specify .)
    tar cvfz /tmp/current.tgz --exclude .git  src
    # get the current state of git
    git pull
    # remove what you don't like anymore
    rm -rf src
    # restore from the tar file
    tar xvfz /tmp/current.tgz
    # commit everything back to git
    git commit -a
    # now you can properly push
    git push
    

    This way the state of affairs in the src is kept in a tar file and git is forced to accept this state without too much fiddling basically the src directory is replaced with the state it had several commits ago.

    Git Baby is a git and github fan, let's start git clone.