Skip to content

Commit

Permalink
Merge branch 'maint'
Browse files Browse the repository at this point in the history
* maint:
  push: point to 'git pull' and 'git push --force' in case of non-fast forward
  Documentation: add: <filepattern>... is optional
  Change mentions of "git programs" to "git commands"
  Documentation: merge: one <remote> is required
  help.c: give correct structure's size to memset()
  • Loading branch information
Junio C Hamano committed Aug 12, 2009
2 parents 19a7fcb + 2cd9c2a commit 6ffd781
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 18 deletions.
4 changes: 2 additions & 2 deletions Documentation/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ color.interactive.<slot>::
Use customized color for 'git-add --interactive'
output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
four distinct types of normal output from interactive
programs. The values of these variables may be specified as
commands. The values of these variables may be specified as
in color.branch.<slot>.

color.pager::
Expand Down Expand Up @@ -1113,7 +1113,7 @@ instaweb.port::
linkgit:git-instaweb[1].

interactive.singlekey::
In interactive programs, allow the user to provide one-letter
In interactive commands, allow the user to provide one-letter
input with a single key (i.e., without hitting enter).
Currently this is used only by the `\--patch` mode of
linkgit:git-add[1]. Note that this setting is silently
Expand Down
2 changes: 1 addition & 1 deletion Documentation/fetch-options.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-q::
--quiet::
Pass --quiet to git-fetch-pack and silence any other internally
used programs.
used git commands.

-v::
--verbose::
Expand Down
2 changes: 1 addition & 1 deletion Documentation/git-add.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
[--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
[--refresh] [--ignore-errors] [--] <filepattern>...
[--refresh] [--ignore-errors] [--] [<filepattern>...]

DESCRIPTION
-----------
Expand Down
2 changes: 1 addition & 1 deletion Documentation/git-merge.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
[-m <msg>] <remote> <remote>...
[-m <msg>] <remote>...
'git merge' <msg> HEAD <remote>...

DESCRIPTION
Expand Down
86 changes: 86 additions & 0 deletions Documentation/git-push.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,92 @@ reason::
refs, no explanation is needed. For a failed ref, the reason for
failure is 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 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) nor 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
--------

Expand Down
2 changes: 1 addition & 1 deletion Documentation/git-rev-list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ between the two operands. The following two commands are equivalent:
$ git rev-list A...B
-----------------------------------------------------------------------

'git-rev-list' is a very essential git program, since it
'rev-list' is a very essential git command, since it
provides the ability to build and traverse commit ancestry graphs. For
this reason, it has a lot of different options that enables it to be
used by commands as different as 'git-bisect' and
Expand Down
2 changes: 1 addition & 1 deletion Documentation/git.txt
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ Synching repositories

include::cmds-synchingrepositories.txt[]

The following are helper programs used by the above; end users
The following are helper commands used by the above; end users
typically do not use them directly.

include::cmds-synchelpers.txt[]
Expand Down
2 changes: 1 addition & 1 deletion Documentation/gitattributes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ Performing a three-way merge

The attribute `merge` affects how three versions of a file is
merged when a file-level merge is necessary during `git merge`,
and other programs such as `git revert` and `git cherry-pick`.
and other commands such as `git revert` and `git cherry-pick`.

Set::

Expand Down
4 changes: 2 additions & 2 deletions Documentation/gitcore-tutorial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ git *
DESCRIPTION
-----------

This tutorial explains how to use the "core" git programs to set up and
This tutorial explains how to use the "core" git commands to set up and
work with a git repository.

If you just need to use git as a revision control system you may prefer
Expand Down Expand Up @@ -1328,7 +1328,7 @@ into it later. Obviously, this repository creation needs to be
done only once.

[NOTE]
'git-push' uses a pair of programs,
'git-push' uses a pair of commands,
'git-send-pack' on your local machine, and 'git-receive-pack'
on the remote machine. The communication between the two over
the network internally uses an SSH connection.
Expand Down
2 changes: 1 addition & 1 deletion Documentation/user-manual.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4131,7 +4131,7 @@ What does this mean?

`git rev-list` is the original version of the revision walker, which
_always_ printed a list of revisions to stdout. It is still functional,
and needs to, since most new Git programs start out as scripts using
and needs to, since most new Git commands start out as scripts using
`git rev-list`.

`git rev-parse` is not as important any more; it was only used to filter out
Expand Down
9 changes: 8 additions & 1 deletion builtin-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ static int do_push(const char *repo, int flags)
struct transport *transport =
transport_get(remote, url[i]);
int err;
int nonfastforward;
if (receivepack)
transport_set_option(transport,
TRANS_OPT_RECEIVEPACK, receivepack);
Expand All @@ -148,13 +149,19 @@ static int do_push(const char *repo, int flags)

if (flags & TRANSPORT_PUSH_VERBOSE)
fprintf(stderr, "Pushing to %s\n", url[i]);
err = transport_push(transport, refspec_nr, refspec, flags);
err = transport_push(transport, refspec_nr, refspec, flags,
&nonfastforward);
err |= transport_disconnect(transport);

if (!err)
continue;

error("failed to push some refs to '%s'", url[i]);
if (nonfastforward) {
printf("To prevent you from losing history, non-fast-forward updates were rejected.\n"
"Merge the remote changes before pushing again.\n"
"See 'non-fast forward' section of 'git push --help' for details.\n");
}
errs++;
}
return !!errs;
Expand Down
4 changes: 2 additions & 2 deletions help.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ const char *help_unknown_cmd(const char *cmd)
struct cmdnames main_cmds, other_cmds;

memset(&main_cmds, 0, sizeof(main_cmds));
memset(&other_cmds, 0, sizeof(main_cmds));
memset(&other_cmds, 0, sizeof(other_cmds));
memset(&aliases, 0, sizeof(aliases));

git_config(git_unknown_cmd_config, NULL);
Expand Down Expand Up @@ -334,7 +334,7 @@ const char *help_unknown_cmd(const char *cmd)
const char *assumed = main_cmds.names[0]->name;
main_cmds.names[0] = NULL;
clean_cmdnames(&main_cmds);
fprintf(stderr, "WARNING: You called a Git program named '%s', "
fprintf(stderr, "WARNING: You called a Git command named '%s', "
"which does not exist.\n"
"Continuing under the assumption that you meant '%s'\n",
cmd, assumed);
Expand Down
11 changes: 8 additions & 3 deletions transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
}

static void print_push_status(const char *dest, struct ref *refs,
int verbose, int porcelain)
int verbose, int porcelain, int * nonfastforward)
{
struct ref *ref;
int n = 0;
Expand All @@ -836,11 +836,14 @@ static void print_push_status(const char *dest, struct ref *refs,
if (ref->status == REF_STATUS_OK)
n += print_one_push_status(ref, dest, n, porcelain);

*nonfastforward = 0;
for (ref = refs; ref; ref = ref->next) {
if (ref->status != REF_STATUS_NONE &&
ref->status != REF_STATUS_UPTODATE &&
ref->status != REF_STATUS_OK)
n += print_one_push_status(ref, dest, n, porcelain);
if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
*nonfastforward = 1;
}
}

Expand Down Expand Up @@ -999,7 +1002,8 @@ int transport_set_option(struct transport *transport,
}

int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags)
int refspec_nr, const char **refspec, int flags,
int * nonfastforward)
{
verify_remote_names(refspec_nr, refspec);

Expand Down Expand Up @@ -1029,7 +1033,8 @@ int transport_push(struct transport *transport,

if (!quiet || push_had_errors(remote_refs))
print_push_status(transport->url, remote_refs,
verbose | porcelain, porcelain);
verbose | porcelain, porcelain,
nonfastforward);

if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
struct ref *ref;
Expand Down
3 changes: 2 additions & 1 deletion transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ int transport_set_option(struct transport *transport, const char *name,
const char *value);

int transport_push(struct transport *connection,
int refspec_nr, const char **refspec, int flags);
int refspec_nr, const char **refspec, int flags,
int * nonfastforward);

const struct ref *transport_get_remote_refs(struct transport *transport);

Expand Down

0 comments on commit 6ffd781

Please sign in to comment.