How can git lose history when pushing a non-fast-forward commit?

I know that sometimes when I run git push, I get this error:

error: failed to push some refs
To prevent you from losing history, non-fast-forward updates were rejected

Can someone give an example of a situation where history would be lost if I pushed a non-fast-forward update? From my understanding, when I do git push, git will simply push my commits to the remote repository and not delete any of the existing commits, so how will it lose the history?

  • GitHub pull request showing commits that are already in target branch
  • Commit failed error when committing new version to svn repository
  • SVN 405 Error: Could not fetch resource information
  • Can git list the tags that occur between two particular commits?
  • Is it possible to reduce “git show --name-status --oneline master” to the summary line only?
  • How to remove all occurences of a file in index, from all git commits
  • Thanks!

  • GitHub Project not pulling in Android Studio
  • git difftool --dir-diff is not creating temp files for Beyond Compare 3 to use
  • Fork a file within a Git repository
  • Is there a way to add a link to the current repo in Github
  • How do I protect git-assume-unchanged files from being overwritten by remote?
  • Uneasy development life with git submodule
  • 2 Solutions collect form web for “How can git lose history when pushing a non-fast-forward commit?”

    When you push, you send your commit, but you also update the remote branch.

    Say a remote repo is:

    A <- B <- C (master)

    Now you clone it, make some dev starting with commit A, and end up with:

    A <- B <- C (origin/master)
      <- D <- E (master)

    If you force push, the remote repo will look like:

    A <- D <- E (master)
      <- B <- C

    So commits B and C still exist, but they aren’t reachable with a branch.
    And if someone clones the repo now, he will locally have:

    A <- D <- E (master; origin/master)

    ie: from his point of view, commits B and C are lost


    • “the commits still exist” means:

    Say my commit B has the sha1 abcdef. Then, there’s a file objects/ab/cdef (at the root of the remote repo, and in the .git directory on my local clone) which represents this commit.

    If you push -f, it won’t delete this remote file, hence, commit B still exists on the remote repo. (At least, as long as it is not garbage collected)

    • “but they aren’t reachable with a branch” implies:

    When someone else clones this remote after I pushed force, he’ll get this .git/objects/ab/cdef file. However, unless he is looking for it, he won’t be aware this commit once existed. For example it will not be displayed by gitk --all.

    Suppose you push your local master to the remote master.

    If your local branch and the remote branch have diverged (both have had commits since last you pulled), how would that be handled?

    One way would be to declare the current commit for your local master as the new remote master. But that would loose the history of commits that are currently on the remote master, since they would never appear in the ancestry of your commit.

    (I suppose that the “lost” commits would still exist remotely, but they would not be on the master branch.)

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