Merge branch 'maint'

* 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()
This commit is contained in:
Junio C Hamano 2009-08-12 16:36:04 -07:00
commit 6ffd781226
14 changed files with 117 additions and 18 deletions

View File

@ -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::
@ -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

View File

@ -1,7 +1,7 @@
-q::
--quiet::
Pass --quiet to git-fetch-pack and silence any other internally
used programs.
used git commands.
-v::
--verbose::

View File

@ -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
-----------

View File

@ -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

View File

@ -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
--------

View File

@ -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

View File

@ -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[]

View File

@ -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::

View File

@ -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
@ -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.

View File

@ -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

View File

@ -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);
@ -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;

4
help.c
View File

@ -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);
@ -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);

View File

@ -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;
@ -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;
}
}
@ -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);
@ -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;

View File

@ -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);