Home Explore Blog CI



git

8th chunk of `Documentation/git-push.adoc`
42fff95e481def516b4826b5dc2c8288e25de1bfcc197c340000000100000dd9
 described.

NOTE ABOUT FAST-FORWARDS
------------------------

When an update changes a branch (or more in general, a ref) that used to
point at commit A to point at another commit B, it is called a
fast-forward update if and only if B is a descendant of A.

In a fast-forward update from A to B, the set of commits that the original
commit A built on top of is a subset of the commits the new commit B
builds on top of.  Hence, it does not lose any history.

In contrast, a non-fast-forward update will lose history.  For example,
suppose you and somebody else started at the same commit X, and you built
a history leading to commit B while the other person built a history
leading to commit A.  The history looks like this:

----------------

      B
     /
 ---X---A

----------------

Further suppose that the other person already pushed changes leading to A
back to the original repository from which you two obtained the original
commit X.

The push done by the other person updated the branch that used to point at
commit X to point at commit A.  It is a fast-forward.

But if you try to push, you will attempt to update the branch (that
now points at A) with commit B.  This does _not_ fast-forward.  If you did
so, the changes introduced by commit A will be lost, because everybody
will now start building on top of B.

The command by default does not allow an update that is not a fast-forward
to prevent such loss of history.

If you do not want to lose your work (history from X to B) or the work by
the other person (history from X to A), you would need to first fetch the
history from the repository, create a history that contains changes done
by both parties, and push the result back.

You can perform "git pull", resolve potential conflicts, and "git push"
the result.  A "git pull" will create a merge commit C between commits A
and B.

----------------

      B---C
     /   /
 ---X---A

----------------

Updating A with the resulting merge commit will fast-forward and your
push will be accepted.

Alternatively, you can rebase your change between X and B on top of A,
with "git pull --rebase", and push the result back.  The rebase will
create a new commit D that builds the change between X and B on top of
A.

----------------

      B   D
     /   /
 ---X---A

----------------

Again, updating A with this commit will fast-forward and your push will be
accepted.

There is another common situation where you may encounter non-fast-forward
rejection when you try to push, and it is possible even when you are
pushing into a repository nobody else pushes into. After you push commit
A yourself (in the first picture in this section), replace it with "git
commit --amend" to produce commit B, and you try to push it out, because
forgot that you have pushed A out already. In such a case, and only if
you are certain that nobody in the meantime fetched your earlier commit A
(and started building on top of it), you can run "git push --force" to
overwrite it. In other words, "git push --force" is a method reserved for
a case where you do mean to lose history.


EXAMPLES
--------

`git push`::
	Works like `git push <remote>`, where <remote> is the
	current branch's remote (or `origin`, if no remote is
	configured for the current branch).

`git push origin`::
	Without additional configuration, pushes the current branch to
	the configured upstream (`branch.<name>.merge` configuration
	variable) if it has the same name as the current branch, and
	errors out without pushing otherwise.
+
The default behavior of this

Title: Understanding Fast-Forwards and Push Rejections in Git
Summary
Git push operations can be rejected if they are not fast-forwards, meaning they would lose history, and this can happen even when pushing to a repository with no other contributors. To resolve such rejections, users can perform a git pull, resolve conflicts, and push the result, or rebase their changes on top of the updated branch, and in rare cases, use git push --force to overwrite existing commits, but this should be used with caution.