Merge refs/heads/master from .

This commit is contained in:
Junio C Hamano 2005-08-24 16:56:48 -07:00
commit 434d6ba031
30 changed files with 814 additions and 324 deletions

View File

@ -1,6 +1,6 @@
git-fetch-script(1) git-fetch-script(1)
=================== ===================
v0.99.4, Aug 2005 v0.99.5, Aug 2005
NAME NAME
---- ----
@ -9,24 +9,17 @@ git-fetch-script - Download objects and a head from another repository.
SYNOPSIS SYNOPSIS
-------- --------
'git-fetch-script' <repository> [ <head> | tag <tag> ] 'git-fetch-script' <repository> <refspec>...
DESCRIPTION DESCRIPTION
----------- -----------
Fetches a named head or a tag from another repository, along Fetches named heads or tags from another repository, along with
with the objects necessary to complete that head or tag. The the objects necessary to complete them.
head to pull defaults to HEAD if unspecified. The head or tag
fetched from the remote repository is stored in
$GIT_DIR/FETCH_HEAD.
When a <tag> is specified, the <tag> fetched from the remote is The ref names and their object names of fetched refs are stored
also copied to the local $GIT_DIR/tags/<tag> file. When no in $GIT_DIR/FETCH_HEAD. This information is left for a later merge
<head> nor <tag> is specified, and <repository> was specified operation done by "git resolve" or "git octopus".
with the short-hand notation (i.e. naming a file under the
$GIT_DIR/branches directory), the head fetched from the remote
repository is also copied to the local $GIT_DIR/heads/<repository>
file.
OPTIONS OPTIONS

View File

@ -0,0 +1,39 @@
git-octopus-script(1)
=====================
v0.99.5, Aug 2005
NAME
----
git-octopus-script - Merge more than two commits.
SYNOPSIS
--------
'git-octopus'
DESCRIPTION
-----------
After running 'git fetch', $GIT_DIR/FETCH_HEAD contains the
following information, one line per remote ref:
------------------------------------------------
<object name> <ref name> from <repository>
------------------------------------------------
Using this information, create and commit an Octopus merge on
top of the current HEAD.
Author
------
Written by Junio C Hamano <junkio@cox.net>
Documentation
--------------
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
GIT
---
Part of the link:git.html[git] suite

View File

@ -9,13 +9,16 @@ git-pull-script - Pull and merge from another repository.
SYNOPSIS SYNOPSIS
-------- --------
'git-pull-script' <repository> [ <head> | tag <tag> ] 'git-pull-script' <repository> <refspec>...
DESCRIPTION DESCRIPTION
----------- -----------
Runs 'git-fetch-script' with the given parameters, then Runs 'git-fetch-script' with the given parameters.
'git-resolve-script' to merge the local HEAD and FETCH_HEAD.
When only one ref is downloaded, runs 'git resolve' to merge it
into the local HEAD. Otherwise uses 'git octopus' to merge them
into the local HEAD.
OPTIONS OPTIONS

View File

@ -3,25 +3,23 @@ git-push-script(1)
NAME NAME
---- ----
git-push-script - Some git command not yet documented. git-push-script - Update remote refs along with associated objects.
SYNOPSIS SYNOPSIS
-------- --------
'git-push-script' [ --option ] <args>... 'git-push-script' [--all] [--force] <repository> <refspec>...
DESCRIPTION DESCRIPTION
----------- -----------
Does something not yet documented.
Updates remote refs using local refs, while sending objects
necessary to complete the given refs.
OPTIONS OPTIONS
------- -------
--option:: include::pull-fetch-param.txt[]
Some option not yet documented.
<args>...::
Some argument not yet documented.
Author Author

View File

@ -1,19 +1,25 @@
git-resolve-script(1) git-resolve-script(1)
===================== =====================
v0.99.4, Aug 2005 v0.99.5, Aug 2005
NAME NAME
---- ----
git-resolve-script - Script used to merge two trees git-resolve-script - Merge two commits
SYNOPSIS SYNOPSIS
-------- --------
'git-resolve-script' 'git resolve' <current> <merged> <message>
DESCRIPTION DESCRIPTION
----------- -----------
This script is used by Linus to merge two trees. Given two commits and a merge message, merge the <merged> commit
into <current> commit, with the commit log message <message>.
When <current> is a descendant of <merged>, or <current> is an
ancestor of <merged>, no new commit is created and the <message>
is ignored. The former is informally called "already up to
date", and the latter is often called "fast forward".
Author Author

View File

@ -9,12 +9,12 @@ git-send-pack - Push missing objects packed.
SYNOPSIS SYNOPSIS
-------- --------
'git-send-pack' [--all] [--exec=<git-receive-pack>] [<host>:]<directory> [<head>...] 'git-send-pack' [--all] [--force] [--exec=<git-receive-pack>] [<host>:]<directory> [<ref>...]
DESCRIPTION DESCRIPTION
----------- -----------
Invokes 'git-receive-pack' on a possibly remote repository, and Invokes 'git-receive-pack' on a possibly remote repository, and
updates it from the current repository, sending named heads. updates it from the current repository, sending named refs.
OPTIONS OPTIONS
@ -29,6 +29,13 @@ OPTIONS
Instead of explicitly specifying which refs to update, Instead of explicitly specifying which refs to update,
update all refs that locally exist. update all refs that locally exist.
--force::
Usually, the command refuses to update a remote ref that
is not an ancestor of the local ref used to overwrite it.
This flag disables the check. What this means is that
the remote repository can lose commits; use it with
care.
<host>:: <host>::
A remote host to house the repository. When this A remote host to house the repository. When this
part is specified, 'git-receive-pack' is invoked via part is specified, 'git-receive-pack' is invoked via
@ -37,7 +44,7 @@ OPTIONS
<directory>:: <directory>::
The repository to update. The repository to update.
<head>...: <ref>...:
The remote refs to update. The remote refs to update.
@ -48,24 +55,25 @@ There are three ways to specify which refs to update on the
remote end. remote end.
With '--all' flag, all refs that exist locally are transfered to With '--all' flag, all refs that exist locally are transfered to
the remote side. You cannot specify any '<head>' if you use the remote side. You cannot specify any '<ref>' if you use
this flag. this flag.
Without '--all' and without any '<head>', the refs that exist Without '--all' and without any '<ref>', the refs that exist
both on the local side and on the remote side are updated. both on the local side and on the remote side are updated.
When '<head>'s are specified explicitly, it can be either a When '<ref>'s are specified explicitly, it can be either a
single pattern, or a pair of such pattern separated by a colon single pattern, or a pair of such pattern separated by a colon
':' (this means that a ref name cannot have a colon in it). A ':' (this means that a ref name cannot have a colon in it). A
single pattern '<name>' is just a shorthand for '<name>:<name>'. single pattern '<name>' is just a shorthand for '<name>:<name>'.
Each pattern pair consists of the source side (before the colon) Each pattern pair consists of the source side (before the colon)
and the destination side (after the colon). The ref that is and the destination side (after the colon). The ref to be
pushed is determined by finding a match that matches the source pushed is determined by finding a match that matches the source
side, and where it is pushed is determined by using the side, and where it is pushed is determined by using the
destination side. destination side.
- It is an error if <src> does not match exactly one of local - It is an error if <src> does not match exactly one of the
refs. local refs.
- It is an error if <dst> matches more than one remote refs. - It is an error if <dst> matches more than one remote refs.
@ -78,6 +86,17 @@ destination side.
exist in the set of remote refs; the ref matched <src> exist in the set of remote refs; the ref matched <src>
locally is used as the name of the destination. locally is used as the name of the destination.
Without '--force', the <src> ref is stored at the remote only if
<dst> does not exist, or <dst> is a proper subset (i.e. an
ancestor) of <src>. This check, known as "fast forward check",
is performed in order to avoid accidentally overwriting the
remote ref and lose other peoples' commits from there.
With '--force', the fast forward check is disabled for all refs.
Optionally, a <ref> parameter can be prefixed with a plus '+' sign
to disable the fast-forward check only on that ref.
Author Author
------ ------

View File

@ -208,7 +208,16 @@ link:git-fetch-script.html[git-fetch-script]::
link:git-pull-script.html[git-pull-script]:: link:git-pull-script.html[git-pull-script]::
Fetch from and merge with a remote repository. Fetch from and merge with a remote repository.
ulink:git-commit-script.html[git-commit-script]:: link:git-resolve-script.html[git-resolve-script]::
Merge two commits.
link:git-octopus-script.html[git-octopus-script]::
Merge more than two commits.
link:git-push-script.html[git-push-script]::
Update remote refs along with associated objects.
link:git-commit-script.html[git-commit-script]::
Record changes to the repository. Record changes to the repository.
link:git-show-branch.html[git-show-branch]:: link:git-show-branch.html[git-show-branch]::
@ -240,9 +249,6 @@ link:git-merge-one-file-script.html[git-merge-one-file-script]::
link:git-prune-script.html[git-prune-script]:: link:git-prune-script.html[git-prune-script]::
Prunes all unreachable objects from the object database Prunes all unreachable objects from the object database
link:git-resolve-script.html[git-resolve-script]::
Script used to merge two trees
link:git-tag-script.html[git-tag-script]:: link:git-tag-script.html[git-tag-script]::
An example script to create a tag object signed with GPG An example script to create a tag object signed with GPG
@ -316,9 +322,6 @@ link:git-get-tar-commit-id.html[git-get-tar-commit-id]::
link:git-patch-id.html[git-patch-id]:: link:git-patch-id.html[git-patch-id]::
git-patch-id. git-patch-id.
link:git-push-script.html[git-push-script]::
git-push-script.
link:git-rebase-script.html[git-rebase-script]:: link:git-rebase-script.html[git-rebase-script]::
git-rebase-script. git-rebase-script.

View File

@ -16,21 +16,67 @@
Local directory Local directory
/path/to/repo.git/ /path/to/repo.git/
In addition to that, as a short-hand, the name of a file In addition to the above, as a short-hand, the name of a
in $GIT_DIR/branches directory can be specified; the file in $GIT_DIR/remotes directory can be given; the
named file should contain a single line, a URL in one of named file should be in the following format:
the above formats, optionally followed by a hash '#' and
the name of remote head.
<head>:: URL: one of the above URL format
The remote head name to fetch from. That is, make the Push: <refspec>...
objects reachable from the commit recorded in Pull: <refspec>...
$GIT_DIR/refs/heads/<head> in the remote repository
available locally.
tag <tag>:: When such a short-hand is specified in place of
The remote head tag to fetch from. That is, make the <repository> without <refspec> parameters on the command
objects reachable from the commit recorded in line, <refspec>... specified on Push lines or Pull lines
$GIT_DIR/refs/tags/<tag> in the remote repository are used for "git push" and "git fetch/pull",
available locally. respectively.
The name of a file in $GIT_DIR/branches directory can be
specified as an older notation short-hand; the named
file should contain a single line, a URL in one of the
above formats, optionally followed by a hash '#' and the
name of remote head (URL fragment notation).
$GIT_DIR/branches/<remote> file that stores a <url>
without the fragment is equivalent to have this in the
corresponding file in the $GIT_DIR/remotes/ directory
URL: <url>
Pull: refs/heads/master:<remote>
while having <url>#<head> is equivalent to
URL: <url>
Pull: refs/heads/<head>:<remote>
<refspec>::
The canonical format of a <refspec> parameter is
+?<src>:<dst>; that is, an optional plus '+', followed
by the source ref, followed by a colon ':', followed by
the destination ref.
When used in "git push", the <src> side can be an
arbitrary "SHA1 expression" that can be used as an
argument to "git-cat-file -t". E.g. "master~4" (push
four parents before the current master head).
For "git push", the local ref that matches <src> is used
to fast forward the remote ref that matches <dst>. If
the optional plus '+' is used, the remote ref is updated
even if it does not result in a fast forward update.
For "git fetch/pull", the remote ref that matches <src>
is fetched, and if <dst> is not empty string, the local
ref that matches it is fast forwarded using <src>.
Again, if the optional plus '+' is used, the local ref
is updated even if it does not result in a fast forward
update.
Some short-cut notations are also supported.
* For backward compatibility, "tag" is almost ignored;
it just makes the following parameter <tag> to mean a
refspec "refs/tags/<tag>:refs/tags/<tag>".
* A parameter <ref> without a colon is equivalent to
<ref>: when pulling/fetching, and <ref>:<ref> when
pushing. That is, do not store it locally if
fetching, and update the same name if pushing.

View File

@ -892,18 +892,26 @@ pull from:
It is likely that you will be pulling from the same remote It is likely that you will be pulling from the same remote
repository from time to time. As a short hand, you can store repository from time to time. As a short hand, you can store
the remote repository URL in a file under .git/branches/ the remote repository URL in a file under .git/remotes/
directory, like this: directory, like this:
mkdir -p .git/branches ------------------------------------------------
echo rsync://kernel.org/pub/scm/git/git.git/ \ mkdir -p .git/remotes/
>.git/branches/linus cat >.git/remotes/linus <<\EOF
URL: http://www.kernel.org/pub/scm/git/git.git/
EOF
------------------------------------------------
and use the filename to "git pull" instead of the full URL. and use the filename to "git pull" instead of the full URL.
The contents of a file under .git/branches can even be a prefix The URL specified in such file can even be a prefix
of a full URL, like this: of a full URL, like this:
echo rsync://kernel.org/pub/.../jgarzik/ >.git/branches/jgarzik ------------------------------------------------
cat >.git/remotes/jgarzik <<\EOF
URL: http://www.kernel.org/pub/scm/linux/git/jgarzik/
EOF
------------------------------------------------
Examples. Examples.
@ -913,9 +921,9 @@ Examples.
the above are equivalent to: the above are equivalent to:
(1) git pull rsync://kernel.org/pub/scm/git/git.git/ HEAD (1) git pull http://www.kernel.org/pub/scm/git/git.git/ HEAD
(2) git pull rsync://kernel.org/pub/scm/git/git.git/ tag v0.99.1 (2) git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1
(3) git pull rsync://kernel.org/pub/.../jgarzik/netdev-2.6.git e100 (3) git pull http://www.kernel.org/pub/.../jgarzik/netdev-2.6.git e100
Publishing your work Publishing your work
@ -1169,18 +1177,43 @@ Working with Others, Shared Repository Style
If you are coming from CVS background, the style of cooperation If you are coming from CVS background, the style of cooperation
suggested in the previous section may be new to you. You do not suggested in the previous section may be new to you. You do not
have to worry. git supports "shared public repository" style of have to worry. git supports "shared public repository" style of
cooperation you are more familiar with as well. cooperation you are probably more familiar with as well.
For this, you should set up a public repository on a machine For this, set up a public repository on a machine that is
that are reachable via SSH by people with "commit privileges". reachable via SSH by people with "commit privileges". Put the
Put them in the same user group and make the repository writable committers in the same user group and make the repository
by that group. Then, each committer would first merge with the writable by that group.
head of the branch of choice, and run "git push" to update the
branch at the public repository. "git push" refuses to update
if the reference on the remote side is not an ancestor of the
commit you are pushing, to prevent you from overwriting changes
made by somebody else.
Each committer would then:
- clone the shared repository to a local repository,
------------------------------------------------
$ git clone repo.shared.xz:/pub/scm/project.git/ my-project
$ cd my-project
$ hack away
------------------------------------------------
- merge the work others might have done while you were
hacking away.
------------------------------------------------
$ git pull origin
$ test the merge result
------------------------------------------------
- push your work as the new head of the shared
repository.
------------------------------------------------
$ git push origin master
------------------------------------------------
If somebody else pushed into the same shared repository while
you were working locally, the last step "git push" would
complain, telling you that the remote "master" head does not
fast forward. You need to pull and merge those other changes
back before you push your work when it happens.
[ to be continued.. cvsimports ] [ to be continued.. cvsimports ]

View File

@ -64,13 +64,14 @@ SCRIPTS=git git-apply-patch-script git-merge-one-file-script git-prune-script \
git-reset-script git-add-script git-checkout-script git-clone-script \ git-reset-script git-add-script git-checkout-script git-clone-script \
gitk git-cherry git-rebase-script git-relink-script git-repack-script \ gitk git-cherry git-rebase-script git-relink-script git-repack-script \
git-format-patch-script git-sh-setup-script git-push-script \ git-format-patch-script git-sh-setup-script git-push-script \
git-branch-script git-parse-remote git-verify-tag-script \ git-branch-script git-parse-remote-script git-verify-tag-script \
git-ls-remote-script git-clone-dumb-http git-rename-script \ git-ls-remote-script git-clone-dumb-http git-rename-script \
git-request-pull-script git-bisect-script git-request-pull-script git-bisect-script
SCRIPTS += git-count-objects-script SCRIPTS += git-count-objects-script
# SCRIPTS += git-send-email-script # SCRIPTS += git-send-email-script
SCRIPTS += git-revert-script SCRIPTS += git-revert-script
SCRIPTS += git-octopus-script
PROG= git-update-cache git-diff-files git-init-db git-write-tree \ PROG= git-update-cache git-diff-files git-init-db git-write-tree \
git-read-tree git-commit-tree git-cat-file git-fsck-cache \ git-read-tree git-commit-tree git-cat-file git-fsck-cache \

View File

@ -309,6 +309,7 @@ struct ref {
struct ref *next; struct ref *next;
unsigned char old_sha1[20]; unsigned char old_sha1[20];
unsigned char new_sha1[20]; unsigned char new_sha1[20];
unsigned char force;
struct ref *peer_ref; /* when renaming */ struct ref *peer_ref; /* when renaming */
char name[0]; char name[0];
}; };

View File

@ -82,15 +82,26 @@ int path_match(const char *path, int nr, char **match)
struct refspec { struct refspec {
char *src; char *src;
char *dst; char *dst;
char force;
}; };
/*
* A:B means fast forward remote B with local A.
* +A:B means overwrite remote B with local A.
* +A is a shorthand for +A:A.
* A is a shorthand for A:A.
*/
static struct refspec *parse_ref_spec(int nr_refspec, char **refspec) static struct refspec *parse_ref_spec(int nr_refspec, char **refspec)
{ {
int i; int i;
struct refspec *rs = xmalloc(sizeof(*rs) * (nr_refspec + 1)); struct refspec *rs = xcalloc(sizeof(*rs), (nr_refspec + 1));
for (i = 0; i < nr_refspec; i++) { for (i = 0; i < nr_refspec; i++) {
char *sp, *dp, *ep; char *sp, *dp, *ep;
sp = refspec[i]; sp = refspec[i];
if (*sp == '+') {
rs[i].force = 1;
sp++;
}
ep = strchr(sp, ':'); ep = strchr(sp, ':');
if (ep) { if (ep) {
dp = ep + 1; dp = ep + 1;
@ -216,8 +227,10 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
error("dst ref %s receives from more than one src.", error("dst ref %s receives from more than one src.",
matched_dst->name); matched_dst->name);
} }
else else {
matched_dst->peer_ref = matched_src; matched_dst->peer_ref = matched_src;
matched_dst->force = rs[i].force;
}
} }
return -errs; return -errs;
} }

View File

@ -58,7 +58,7 @@ bisect_start() {
bisect_bad() { bisect_bad() {
bisect_autostart bisect_autostart
case "$#" in 0 | 1) ;; *) usage ;; esac case "$#" in 0 | 1) ;; *) usage ;; esac
rev=$(git-rev-parse --revs-only --verify --default HEAD "$@") || exit rev=$(git-rev-parse --verify --default HEAD "$@") || exit
echo "$rev" > "$GIT_DIR/refs/bisect/bad" echo "$rev" > "$GIT_DIR/refs/bisect/bad"
bisect_auto_next bisect_auto_next
} }
@ -67,7 +67,7 @@ bisect_good() {
bisect_autostart bisect_autostart
case "$#" in case "$#" in
0) revs=$(git-rev-parse --verify HEAD) || exit ;; 0) revs=$(git-rev-parse --verify HEAD) || exit ;;
*) revs=$(git-rev-parse --revs-only "$@") || exit ;; *) revs=$(git-rev-parse --revs-only --no-flags "$@") || exit ;;
esac esac
for rev in $revs for rev in $revs
do do

View File

@ -25,7 +25,7 @@ case "$#" in
head="$2^0" ;; head="$2^0" ;;
esac esac
branchname="$1" branchname="$1"
rev=$(git-rev-parse --revs-only --verify "$head") || exit rev=$(git-rev-parse --verify "$head") || exit
[ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists" [ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists"

View File

@ -127,6 +127,8 @@ yes,yes)
esac esac
# Update origin. # Update origin.
mkdir -p "$D/.git/branches/" && mkdir -p "$D/.git/remotes/" &&
rm -f "$D/.git/branches/origin" && rm -f "$D/.git/remotes/origin" &&
echo "$repo" >"$D/.git/branches/origin" echo >"$D/.git/remotes/origin" \
"URL: $repo
Pull: master:origin"

View File

@ -1,54 +1,203 @@
#!/bin/sh #!/bin/sh
# #
. git-sh-setup-script || die "Not a git archive" . git-sh-setup-script || die "Not a git archive"
. git-parse-remote "$@" . git-parse-remote-script
merge_repo="$_remote_repo" _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
merge_head="$_remote_head" _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
merge_store="$_remote_store"
TMP_HEAD="$GIT_DIR/TMP_HEAD" append=
force=
while case "$#" in 0) break ;; esac
do
case "$1" in
-a|--a|--ap|--app|--appe|--appen|--append)
append=t
shift
;;
-f|--f|--fo|--for|--forc|--force)
force=t
shift
;;
*)
break
;;
esac
done
case "$merge_repo" in case "$#" in
0)
test -f "$GIT_DIR/branches/origin" ||
test -f "$GIT_DIR/remotes/origin" ||
die "Where do you want to fetch from?"
set origin ;;
esac
remote_nick="$1"
remote=$(get_remote_url "$@")
refs=
rref=
rsync_slurped_objects=
if test "" = "$append"
then
: >$GIT_DIR/FETCH_HEAD
fi
append_fetch_head () {
head_="$1"
remote_="$2"
remote_name_="$3"
remote_nick_="$4"
local_name_="$5"
# 2.6.11-tree tag would not be happy to be fed to resolve.
if git-cat-file commit "$head_" >/dev/null 2>&1
then
head_=$(git-rev-parse --verify "$head_^0") || exit
note_="$head_ $remote_name_ from $remote_nick_"
echo "$note_" >>$GIT_DIR/FETCH_HEAD
echo >&2 "* committish: $note_"
else
echo >&2 "* non-commit: $note_"
fi
if test "$local_name_" != ""
then
# We are storing the head locally. Make sure that it is
# a fast forward (aka "reverse push").
fast_forward_local "$local_name_" "$head_" "$remote_" "$remote_name_"
fi
}
fast_forward_local () {
case "$1" in
refs/tags/*)
# Tags need not be pointing at commits so there
# is no way to guarantee "fast-forward" anyway.
if test -f "$GIT_DIR/$1"
then
echo >&2 "* $1: updating with $4"
echo >&2 " from $3."
else
echo >&2 "* $1: storing $4"
echo >&2 " from $3."
fi
echo "$2" >"$GIT_DIR/$1" ;;
refs/heads/*)
# NEEDSWORK: use the same cmpxchg protocol here.
echo "$2" >"$GIT_DIR/$1.lock"
if test -f "$GIT_DIR/$1"
then
local=$(git-rev-parse --verify "$1^0") &&
mb=$(git-merge-base "$local" "$2") &&
case "$2,$mb" in
$local,*)
echo >&2 "* $1: same as $4"
echo >&2 " from $3"
;;
*,$local)
echo >&2 "* $1: fast forward to $4"
echo >&2 " from $3"
;;
*)
false
;;
esac || {
echo >&2 "* $1: does not fast forward to $4"
case "$force,$single_force" in
t,* | *,t)
echo >&2 " from $3; forcing update."
;;
*)
mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1.remote"
echo >&2 " from $3; leaving it in '$1.remote'"
;;
esac
}
else
echo >&2 "* $1: storing $4"
echo >&2 " from $3."
fi
test -f "$GIT_DIR/$1.lock" &&
mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1"
;;
esac
}
for ref in $(get_remote_refs_for_fetch "$@")
do
refs="$refs $ref"
# These are relative path from $GIT_DIR, typically starting at refs/
# but may be HEAD
if expr "$ref" : '\+' >/dev/null
then
single_force=t
ref=$(expr "$ref" : '\+\(.*\)')
else
single_force=
fi
remote_name=$(expr "$ref" : '\([^:]*\):')
local_name=$(expr "$ref" : '[^:]*:\(.*\)')
rref="$rref $remote_name"
# There are transports that can fetch only one head at a time...
case "$remote" in
http://* | https://*) http://* | https://*)
if [ -n "$GIT_SSL_NO_VERIFY" ]; then if [ -n "$GIT_SSL_NO_VERIFY" ]; then
curl_extra_args="-k" curl_extra_args="-k"
fi fi
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' && head=$(curl -nsf $curl_extra_args "$remote/$remote_name") &&
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" && expr "$head" : "$_x40\$" >/dev/null ||
head=$(curl -nsf $curl_extra_args "$merge_repo/$merge_head") && die "Failed to fetch $remote_name from $remote"
expr "$head" : "$_x40\$" >/dev/null || { echo Fetching "$remote_name from $remote" using http
echo >&2 "Failed to fetch $merge_head from $merge_repo" git-http-pull -v -a "$head" "$remote/" || exit
exit 1
}
echo Fetching "$merge_head" using http
git-http-pull -v -a "$head" "$merge_repo/" || exit
;; ;;
rsync://*) rsync://*)
rsync -L "$merge_repo/$merge_head" "$TMP_HEAD" || exit 1 TMP_HEAD="$GIT_DIR/TMP_HEAD"
rsync -L "$remote/$remote_name" "$TMP_HEAD" || exit 1
head=$(git-rev-parse TMP_HEAD) head=$(git-rev-parse TMP_HEAD)
rm -f "$TMP_HEAD" rm -f "$TMP_HEAD"
rsync -avz --ignore-existing "$merge_repo/objects/" "$GIT_OBJECT_DIRECTORY/" test "$rsync_slurped_objects" || {
rsync -avz --ignore-existing "$remote/objects/" \
"$GIT_OBJECT_DIRECTORY/" || exit
rsync_slurped_objects=t
}
;; ;;
*) *)
head=$(git-fetch-pack "$merge_repo" "$merge_head") # We will do git native transport with just one call later.
if h=`expr "$head" : '\([^ ][^ ]*\) '` continue ;;
then esac
head=$h
fi
;;
esac || exit 1
git-rev-parse --verify "$head" > /dev/null || exit 1 append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
case "$merge_store" in done
'')
;; case "$remote" in
http://* | https://* | rsync://* )
;; # we are already done.
*) *)
echo "$head" > "$GIT_DIR/$merge_store" git-fetch-pack "$remote" $rref |
esac && while read sha1 remote_name
do
found=
single_force=
for ref in $refs
do
case "$ref" in
+$remote_name:*)
single_force=t
found="$ref"
break ;;
$remote_name:*)
found="$ref"
break ;;
esac
done
# FETCH_HEAD is fed to git-resolve-script which will eventually be local_name=$(expr "$found" : '[^:]*:\(.*\)')
# passed to git-commit-tree as one of the parents. Make sure we do append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
# not give a tag object ID. done
;;
git-rev-parse "$head^0" >"$GIT_DIR/FETCH_HEAD" esac

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
revs=$(git-rev-parse --revs-only --default HEAD "$@") || exit revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
[ "$revs" ] || die "No HEAD ref" [ "$revs" ] || die "No HEAD ref"
git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | LESS=-S ${PAGER:-less} git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | LESS=-S ${PAGER:-less}

View File

@ -29,8 +29,8 @@ case ",$heads,$tags," in
,,,) heads=heads tags=tags other=other ;; ,,,) heads=heads tags=tags other=other ;;
esac esac
. git-parse-remote "$1" . git-parse-remote-script
peek_repo="$_remote_repo" peek_repo="$(get_remote_url "$@")"
shift shift
tmp=.ls-remote-$$ tmp=.ls-remote-$$

103
git-octopus-script Executable file
View File

@ -0,0 +1,103 @@
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano
#
# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD.
#
. git-sh-setup-script || die "Not a git archive"
usage () {
die "usage: git octopus"
}
# Sanity check the heads early.
while read SHA1 REPO
do
test $(git-cat-file -t $SHA1) = "commit" ||
die "$REPO given to octopus is not a commit"
done <"$GIT_DIR/FETCH_HEAD"
head=$(git-rev-parse --verify HEAD) || exit
git-update-cache --refresh ||
die "Your working tree is dirty."
test "$(git-diff-cache --cached "$head")" = "" ||
die "Your working tree does not match HEAD."
# MRC is the current "merge reference commit"
# MRT is the current "merge result tree"
MRC=$head MSG= PARENT="-p $head"
MRT=$(git-write-tree)
CNT=1 ;# counting our head
NON_FF_MERGE=0
while read SHA1 REPO
do
common=$(git-merge-base $MRC $SHA1) ||
die "Unable to find common commit with $SHA1 from $REPO"
if test "$common" = $SHA1
then
echo "Already up-to-date: $REPO"
continue
fi
CNT=`expr $CNT + 1`
PARENT="$PARENT -p $SHA1"
MSG="$MSG
$REPO"
if test "$common,$NON_FF_MERGE" = "$MRC,0"
then
# The first head being merged was a fast-forward.
# Advance MRC to the head being merged, and use that
# tree as the intermediate result of the merge.
# We still need to count this as part of the parent set.
echo "Fast forwarding to: $REPO"
git-read-tree -u -m $head $SHA1 || exit
MRC=$SHA1 MRT=$(git-write-tree)
continue
fi
NON_FF_MERGE=1
echo "Trying simple merge with $REPO"
git-read-tree -u -m $common $MRT $SHA1 || exit
next=$(git-write-tree 2>/dev/null)
if test $? -ne 0
then
echo "Simple merge did not work, trying automatic merge."
git-merge-cache -o git-merge-one-file-script -a || {
git-read-tree --reset "$head"
git-checkout-cache -f -q -u -a
die "Automatic merge failed; should not be doing Octopus"
}
next=$(git-write-tree 2>/dev/null)
fi
MRC=$common
MRT=$next
done <"$GIT_DIR/FETCH_HEAD"
# Just to be careful in case the user feeds nonsense to us.
case "$CNT" in
1)
echo "No changes."
exit 0 ;;
2)
echo "Not an Octopus; making an ordinary commit."
MSG="Merge "`expr "$MSG" : '. \(.*\)'` ; # remove LF and TAB
;;
*)
# In an octopus, the original head is just one of the equals,
# so we should list it as such.
HEAD_LINK=`readlink "$GIT_DIR/HEAD"`
MSG="Octopus merge of the following:
$HEAD_LINK from .$MSG"
;;
esac
result_commit=$(echo "$MSG" | git-commit-tree $MRT $PARENT)
echo "Committed merge $result_commit"
echo $result_commit >"$GIT_DIR"/HEAD
git-diff-tree -p $head $result_commit | git-apply --stat

View File

@ -1,79 +0,0 @@
: To be included in git-pull and git-fetch scripts.
# A remote repository can be specified on the command line
# in one of the following formats:
#
# <repo>
# <repo> <head>
# <repo> tag <tag>
#
# where <repo> could be one of:
#
# a URL (including absolute or local pathname)
# a short-hand
# a short-hand followed by a trailing path
#
# A short-hand <name> has a corresponding file $GIT_DIR/branches/<name>,
# whose contents is a URL, possibly followed by a URL fragment #<head>
# to name the default branch on the remote side to fetch from.
_remote_repo= _remote_store= _remote_head= _remote_name=
case "$1" in
*:* | /* | ../* | ./* )
_remote_repo="$1"
;;
* )
# otherwise, it is a short hand.
case "$1" in
*/*)
# a short-hand followed by a trailing path
_token=$(expr "$1" : '\([^/]*\)/')
_rest=$(expr "$1" : '[^/]*\(/.*\)$')
;;
*)
_token="$1"
_rest=
_remote_store="refs/heads/$_token"
;;
esac
test -f "$GIT_DIR/branches/$_token" ||
die "No such remote branch: $_token"
_remote_repo=$(cat "$GIT_DIR/branches/$_token")"$_rest"
;;
esac
case "$_remote_repo" in
*"#"*)
_remote_head=`expr "$_remote_repo" : '.*#\(.*\)$'`
_remote_repo=`expr "$_remote_repo" : '\(.*\)#'`
;;
esac
_remote_name=$(echo "$_remote_repo" | sed 's|\.git/*$||')
case "$2" in
tag)
_remote_name="tag '$3' of $_remote_name"
_remote_head="refs/tags/$3"
_remote_store="$_remote_head"
;;
?*)
# command line specified a head explicitly; do not
# store the fetched head as a branch head.
_remote_name="head '$2' of $_remote_name"
_remote_head="refs/heads/$2"
_remote_store=''
;;
'')
case "$_remote_head" in
'')
_remote_head=HEAD ;;
*)
_remote_name="head '$_remote_head' of $_remote_name"
_remote_head="refs/heads/$_remote_head"
;;
esac
;;
esac

151
git-parse-remote-script Executable file
View File

@ -0,0 +1,151 @@
#!/bin/sh
. git-sh-setup-script || die "Not a git archive"
get_data_source () {
case "$1" in
*/*)
# Not so fast. This could be the partial URL shorthand...
token=$(expr "$1" : '\([^/]*\)/')
remainder=$(expr "$1" : '[^/]*/\(.*\)')
if test -f "$GIT_DIR/branches/$token"
then
echo branches-partial
else
echo ''
fi
;;
*)
if test -f "$GIT_DIR/remotes/$1"
then
echo remotes
elif test -f "$GIT_DIR/branches/$1"
then
echo branches
else
echo ''
fi ;;
esac
}
get_remote_url () {
data_source=$(get_data_source "$1")
case "$data_source" in
'')
echo "$1" ;;
remotes)
sed -ne '/^URL: */{
s///p
q
}' "$GIT_DIR/remotes/$1" ;;
branches)
sed -e 's/#.*//' "$GIT_DIR/branches/$1" ;;
branches-partial)
token=$(expr "$1" : '\([^/]*\)/')
remainder=$(expr "$1" : '[^/]*/\(.*\)')
url=$(sed -e 's/#.*//' "$GIT_DIR/branches/$token")
echo "$url/$remainder"
;;
*)
die "internal error: get-remote-url $1" ;;
esac
}
get_remote_default_refs_for_push () {
data_source=$(get_data_source "$1")
case "$data_source" in
'' | branches | branches-partial)
;; # no default push mapping, just send matching refs.
remotes)
sed -ne '/^Push: */{
s///p
}' "$GIT_DIR/remotes/$1" ;;
*)
die "internal error: get-remote-default-ref-for-push $1" ;;
esac
}
# Subroutine to canonicalize remote:local notation
canon_refs_list_for_fetch () {
for ref
do
force=
case "$ref" in
+*)
ref=$(expr "$ref" : '\+\(.*\)')
force=+
;;
esac
expr "$ref" : '.*:' >/dev/null || ref="${ref}:"
remote=$(expr "$ref" : '\([^:]*\):')
local=$(expr "$ref" : '[^:]*:\(.*\)')
case "$remote" in
'') remote=HEAD ;;
*) remote="refs/heads/$remote" ;;
esac
case "$local" in
'') local= ;;
*) local="refs/heads/$local" ;;
esac
echo "${force}${remote}:${local}"
done
}
# Returns list of src: (no store), or src:dst (store)
get_remote_default_refs_for_fetch () {
data_source=$(get_data_source "$1")
case "$data_source" in
'' | branches-partial)
echo "HEAD:" ;;
branches)
remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
case "$remote_branch" in '') remote_branch=master ;; esac
echo "refs/heads/${remote_branch}:refs/heads/$1"
;;
remotes)
canon_refs_list_for_fetch $(sed -ne '/^Pull: */{
s///p
}' "$GIT_DIR/remotes/$1")
;;
*)
die "internal error: get-remote-default-ref-for-push $1" ;;
esac
}
get_remote_refs_for_push () {
case "$#" in
0) die "internal error: get-remote-refs-for-push." ;;
1) get_remote_default_refs_for_push "$@" ;;
*) shift; echo "$@" ;;
esac
}
get_remote_refs_for_fetch () {
case "$#" in
0)
die "internal error: get-remote-refs-for-fetch." ;;
1)
get_remote_default_refs_for_fetch "$@" ;;
*)
shift
tag_just_seen=
for ref
do
if test "$tag_just_seen"
then
echo "refs/tags/${ref}:refs/tags/${ref}"
tag_just_seen=
continue
else
case "$ref" in
tag)
tag_just_seen=yes
continue
;;
esac
fi
canon_refs_list_for_fetch "$ref"
done
;;
esac
}

View File

@ -1,12 +1,26 @@
#!/bin/sh #!/bin/sh
# #
. git-sh-setup-script || die "Not a git archive" # Copyright (c) 2005 Junio C Hamano
. git-parse-remote "$@" #
merge_name="$_remote_name" # Fetch one or more remote refs and merge it/them into the current HEAD.
. git-sh-setup-script || die "Not a git archive"
git-fetch-script "$@" || exit 1 git-fetch-script "$@" || exit 1
merge_head=$(sed -e 's/ .*//' "$GIT_DIR"/FETCH_HEAD | tr '\012' ' ')
merge_name=$(sed -e 's/^[0-9a-f]* //' "$GIT_DIR"/FETCH_HEAD |
tr '\012' ' ')
case "$merge_head" in
'')
echo >&2 "No changes."
exit 0
;;
*' '?*)
echo >&2 "Pulling more than one heads; making an Octopus."
exec git-octopus-script
;;
esac
git-resolve-script \ git-resolve-script \
"$(cat "$GIT_DIR"/HEAD)" \ "$(cat "$GIT_DIR"/HEAD)" \
"$(cat "$GIT_DIR"/FETCH_HEAD)" \ $merge_head "Merge $merge_name"
"Merge $merge_name"

View File

@ -20,8 +20,6 @@ do
-*) -*)
die "Unknown parameter $1" ;; die "Unknown parameter $1" ;;
*) *)
remote="$1"
shift
set x "$@" set x "$@"
shift shift
break ;; break ;;
@ -29,27 +27,13 @@ do
shift shift
done done
case "$remote" in . git-parse-remote-script
*:* | /* | ../* | ./* ) remote=$(get_remote_url "$@")
# An URL, host:/path/to/git, absolute and relative paths. case "$has_all" in
;; --all) set x ;;
* ) '') set x $(get_remote_refs_for_push "$@") ;;
# Shorthand
if expr "$remote" : '..*/..*' >/dev/null
then
# a short-hand followed by a trailing path
shorthand=$(expr "$remote" : '\([^/]*\)')
remainder=$(expr "$remote" : '[^/]*\(/.*\)$')
else
shorthand="$remote"
remainder=
fi
remote=$(sed -e 's/#.*//' "$GIT_DIR/branches/$remote") &&
expr "$remote" : '..*:' >/dev/null &&
remote="$remote$remainder" ||
die "Cannot parse remote $remote"
;;
esac esac
shift
case "$remote" in case "$remote" in
http://* | https://* | git://* | rsync://* ) http://* | https://* | git://* | rsync://* )

View File

@ -1,6 +1,20 @@
#!/bin/sh #!/bin/sh
#
# Copyright (c) 2005 Linus Torvalds
#
. git-sh-setup-script || die "Not a git archive" . git-sh-setup-script || die "Not a git archive"
no_update_info=
while case "$#" in 0) break ;; esac
do
case "$1" in
-n) no_update_info=t ;;
*) break ;;
esac
shift
done
rm -f .tmp-pack-* rm -f .tmp-pack-*
packname=$(git-rev-list --unpacked --objects $(git-rev-parse --all) | packname=$(git-rev-list --unpacked --objects $(git-rev-parse --all) |
git-pack-objects --non-empty --incremental .tmp-pack) || git-pack-objects --non-empty --incremental .tmp-pack) ||
@ -9,6 +23,11 @@ if [ -z "$packname" ]; then
echo Nothing new to pack echo Nothing new to pack
exit 0 exit 0
fi fi
mkdir -p "$GIT_OBJECT_DIRECTORY/pack" && mkdir -p "$GIT_OBJECT_DIRECTORY/pack" &&
mv .tmp-pack-$packname.pack "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.pack" && mv .tmp-pack-$packname.pack "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.pack" &&
mv .tmp-pack-$packname.idx "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.idx" mv .tmp-pack-$packname.idx "$GIT_OBJECT_DIRECTORY/pack/pack-$packname.idx" &&
case "$no_update_info" in
t) : ;;
*) git-update-server-info ;;
esac

View File

@ -19,8 +19,8 @@ head=${3-HEAD}
[ "$revision" ] || usage [ "$revision" ] || usage
[ "$url" ] || usage [ "$url" ] || usage
baserev=`git-rev-parse --verify $revision^0` && baserev=`git-rev-parse --verify "$revision"^0` &&
headrev=`git-rev-parse --verify $head^0` || exit headrev=`git-rev-parse --verify "$head"^0` || exit
echo "The following changes since commit $baserev:" echo "The following changes since commit $baserev:"
git log --max-count=1 --pretty=short "$baserev" | git log --max-count=1 --pretty=short "$baserev" |

View File

@ -10,7 +10,7 @@ case "$status" in
die "Your working tree is dirty; cannot revert a previous patch." ;; die "Your working tree is dirty; cannot revert a previous patch." ;;
esac esac
rev=$(git-rev-parse --no-flags --verify --revs-only "$@") && rev=$(git-rev-parse --verify "$@") &&
commit=$(git-rev-parse --verify "$rev^0") || exit commit=$(git-rev-parse --verify "$rev^0") || exit
if git-diff-tree -R -M -p $commit | git-apply --index && if git-diff-tree -R -M -p $commit | git-apply --index &&
msg=$(git-rev-list --pretty=oneline --max-count=1 $commit) msg=$(git-rev-list --pretty=oneline --max-count=1 $commit)

View File

@ -33,7 +33,7 @@ static int blob_objects = 0;
static int verbose_header = 0; static int verbose_header = 0;
static int show_parents = 0; static int show_parents = 0;
static int hdr_termination = 0; static int hdr_termination = 0;
static const char *prefix = ""; static const char *commit_prefix = "";
static unsigned long max_age = -1; static unsigned long max_age = -1;
static unsigned long min_age = -1; static unsigned long min_age = -1;
static int max_count = -1; static int max_count = -1;
@ -48,14 +48,14 @@ static void show_commit(struct commit *commit)
{ {
commit->object.flags |= SHOWN; commit->object.flags |= SHOWN;
if (show_breaks) { if (show_breaks) {
prefix = "| "; commit_prefix = "| ";
if (commit->object.flags & DISCONTINUITY) { if (commit->object.flags & DISCONTINUITY) {
prefix = "^ "; commit_prefix = "^ ";
} else if (commit->object.flags & BOUNDARY) { } else if (commit->object.flags & BOUNDARY) {
prefix = "= "; commit_prefix = "= ";
} }
} }
printf("%s%s", prefix, sha1_to_hex(commit->object.sha1)); printf("%s%s", commit_prefix, sha1_to_hex(commit->object.sha1));
if (show_parents) { if (show_parents) {
struct commit_list *parents = commit->parents; struct commit_list *parents = commit->parents;
while (parents) { while (parents) {
@ -481,9 +481,9 @@ static void handle_one_commit(struct commit *com, struct commit_list **lst)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct commit_list *list = NULL; struct commit_list *list = NULL;
const char *prefix = setup_git_directory();
int i, limited = 0; int i, limited = 0;
setup_git_directory();
for (i = 1 ; i < argc; i++) { for (i = 1 ; i < argc; i++) {
int flags; int flags;
char *arg = argv[i]; char *arg = argv[i];
@ -511,9 +511,9 @@ int main(int argc, char **argv)
verbose_header = 1; verbose_header = 1;
hdr_termination = '\n'; hdr_termination = '\n';
if (commit_format == CMIT_FMT_ONELINE) if (commit_format == CMIT_FMT_ONELINE)
prefix = ""; commit_prefix = "";
else else
prefix = "commit "; commit_prefix = "commit ";
continue; continue;
} }
if (!strncmp(arg, "--no-merges", 11)) { if (!strncmp(arg, "--no-merges", 11)) {

View File

@ -7,20 +7,21 @@
#include "commit.h" #include "commit.h"
#include "refs.h" #include "refs.h"
#define DO_REVS 1
#define DO_NOREV 2
#define DO_FLAGS 4
#define DO_NONFLAGS 8
static int filter = ~0;
static char *def = NULL; static char *def = NULL;
static int no_revs = 0;
static int single_rev = 0;
static int revs_only = 0;
static int do_rev_argument = 1;
static int output_revs = 0;
static int flags_only = 0;
static int no_flags = 0;
static int output_sq = 0;
static int symbolic = 0;
#define NORMAL 0 #define NORMAL 0
#define REVERSED 1 #define REVERSED 1
static int show_type = NORMAL; static int show_type = NORMAL;
static int symbolic = 0;
static int output_sq = 0;
static int revs_count = 0;
/* /*
* Some arguments are relevant "revision" arguments, * Some arguments are relevant "revision" arguments,
@ -30,13 +31,19 @@ static int show_type = NORMAL;
static int is_rev_argument(const char *arg) static int is_rev_argument(const char *arg)
{ {
static const char *rev_args[] = { static const char *rev_args[] = {
"--max-count=",
"--max-age=",
"--min-age=",
"--merge-order",
"--topo-order",
"--bisect", "--bisect",
"--header",
"--max-age=",
"--max-count=",
"--merge-order",
"--min-age=",
"--no-merges", "--no-merges",
"--objects",
"--parents",
"--pretty",
"--show-breaks",
"--topo-order",
"--unpacked",
NULL NULL
}; };
const char **p = rev_args; const char **p = rev_args;
@ -47,11 +54,13 @@ static int is_rev_argument(const char *arg)
if (!str) if (!str)
return 0; return 0;
len = strlen(str); len = strlen(str);
if (!strncmp(arg, str, len)) if (!strcmp(arg, str) ||
(str[len-1] == '=' && !strncmp(arg, str, len)))
return 1; return 1;
} }
} }
/* Output argument as a string, either SQ or normal */
static void show(const char *arg) static void show(const char *arg)
{ {
if (output_sq) { if (output_sq) {
@ -70,11 +79,13 @@ static void show(const char *arg)
puts(arg); puts(arg);
} }
/* Output a revision, only if filter allows it */
static void show_rev(int type, const unsigned char *sha1, const char *name) static void show_rev(int type, const unsigned char *sha1, const char *name)
{ {
if (no_revs) if (!(filter & DO_REVS))
return; return;
output_revs++; def = NULL;
revs_count++;
if (type != show_type) if (type != show_type)
putchar('^'); putchar('^');
@ -84,29 +95,12 @@ static void show_rev(int type, const unsigned char *sha1, const char *name)
show(sha1_to_hex(sha1)); show(sha1_to_hex(sha1));
} }
static void show_rev_arg(char *rev) /* Output a flag, only if filter allows it. */
static void show_flag(char *arg)
{ {
if (no_revs) if (!(filter & DO_FLAGS))
return; return;
show(rev); if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV))
}
static void show_norev(char *norev)
{
if (flags_only)
return;
if (revs_only)
return;
show(norev);
}
static void show_arg(char *arg)
{
if (no_flags)
return;
if (do_rev_argument && is_rev_argument(arg))
show_rev_arg(arg);
else
show(arg); show(arg);
} }
@ -122,7 +116,6 @@ static void show_default(void)
show_rev(NORMAL, sha1, s); show_rev(NORMAL, sha1, s);
return; return;
} }
show_norev(s);
} }
} }
@ -134,7 +127,7 @@ static int show_reference(const char *refname, const unsigned char *sha1)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i, as_is = 0; int i, as_is = 0, verify = 0;
unsigned char sha1[20]; unsigned char sha1[20];
const char *prefix = setup_git_directory(); const char *prefix = setup_git_directory();
@ -143,15 +136,13 @@ int main(int argc, char **argv)
char *dotdot; char *dotdot;
if (as_is) { if (as_is) {
show_norev(arg); show(arg);
continue; continue;
} }
if (*arg == '-') { if (*arg == '-') {
if (!strcmp(arg, "--")) { if (!strcmp(arg, "--")) {
show_default();
if (revs_only || flags_only)
break;
as_is = 1; as_is = 1;
continue;
} }
if (!strcmp(arg, "--default")) { if (!strcmp(arg, "--default")) {
def = argv[i+1]; def = argv[i+1];
@ -159,25 +150,24 @@ int main(int argc, char **argv)
continue; continue;
} }
if (!strcmp(arg, "--revs-only")) { if (!strcmp(arg, "--revs-only")) {
revs_only = 1; filter &= ~DO_NOREV;
continue; continue;
} }
if (!strcmp(arg, "--no-revs")) { if (!strcmp(arg, "--no-revs")) {
no_revs = 1; filter &= ~DO_REVS;
continue; continue;
} }
if (!strcmp(arg, "--flags")) { if (!strcmp(arg, "--flags")) {
flags_only = 1; filter &= ~DO_NONFLAGS;
continue; continue;
} }
if (!strcmp(arg, "--no-flags")) { if (!strcmp(arg, "--no-flags")) {
no_flags = 1; filter &= ~DO_FLAGS;
continue; continue;
} }
if (!strcmp(arg, "--verify")) { if (!strcmp(arg, "--verify")) {
revs_only = 1; filter &= ~(DO_FLAGS|DO_NOREV);
do_rev_argument = 0; verify = 1;
single_rev = 1;
continue; continue;
} }
if (!strcmp(arg, "--sq")) { if (!strcmp(arg, "--sq")) {
@ -197,12 +187,17 @@ int main(int argc, char **argv)
continue; continue;
} }
if (!strcmp(arg, "--show-prefix")) { if (!strcmp(arg, "--show-prefix")) {
if (prefix)
puts(prefix); puts(prefix);
continue; continue;
} }
show_arg(arg); if (verify)
die("Needed a single revision");
show_flag(arg);
continue; continue;
} }
/* Not a flag argument */
dotdot = strstr(arg, ".."); dotdot = strstr(arg, "..");
if (dotdot) { if (dotdot) {
unsigned char end[20]; unsigned char end[20];
@ -212,9 +207,6 @@ int main(int argc, char **argv)
if (!*n) if (!*n)
n = "HEAD"; n = "HEAD";
if (!get_sha1(n, end)) { if (!get_sha1(n, end)) {
if (no_revs)
continue;
def = NULL;
show_rev(NORMAL, end, n); show_rev(NORMAL, end, n);
show_rev(REVERSED, sha1, arg); show_rev(REVERSED, sha1, arg);
continue; continue;
@ -223,26 +215,21 @@ int main(int argc, char **argv)
*dotdot = '.'; *dotdot = '.';
} }
if (!get_sha1(arg, sha1)) { if (!get_sha1(arg, sha1)) {
if (no_revs)
continue;
def = NULL;
show_rev(NORMAL, sha1, arg); show_rev(NORMAL, sha1, arg);
continue; continue;
} }
if (*arg == '^' && !get_sha1(arg+1, sha1)) { if (*arg == '^' && !get_sha1(arg+1, sha1)) {
if (no_revs)
continue;
def = NULL;
show_rev(REVERSED, sha1, arg+1); show_rev(REVERSED, sha1, arg+1);
continue; continue;
} }
show_default(); if (verify)
show_norev(arg); die("Needed a single revision");
if ((filter & (DO_NONFLAGS|DO_NOREV)) ==
(DO_NONFLAGS|DO_NOREV))
show(arg);
} }
show_default(); show_default();
if (single_rev && output_revs != 1) { if (verify && revs_count != 1)
fprintf(stderr, "Needed a single revision\n"); die("Needed a single revision");
exit(1);
}
return 0; return 0;
} }

View File

@ -206,7 +206,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
/* This part determines what can overwrite what. /* This part determines what can overwrite what.
* The rules are: * The rules are:
* *
* (0) you can always use --force. * (0) you can always use --force or +A:B notation to
* selectively force individual ref pairs.
* *
* (1) if the old thing does not exist, it is OK. * (1) if the old thing does not exist, it is OK.
* *
@ -218,16 +219,19 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
* descendant of old, it is OK. * descendant of old, it is OK.
*/ */
if (!force_update && !is_zero_sha1(ref->old_sha1)) { if (!force_update &&
!is_zero_sha1(ref->old_sha1) &&
!ref->force) {
if (!has_sha1_file(ref->old_sha1)) { if (!has_sha1_file(ref->old_sha1)) {
error("remote '%s' object %s does not " error("remote '%s' object %s does not "
"exist on local", "exist on local",
ref->name, sha1_to_hex(ref->old_sha1)); ref->name, sha1_to_hex(ref->old_sha1));
continue; continue;
} }
/* We assume that local is fsck-clean. Otherwise /* We assume that local is fsck-clean. Otherwise
* you _could_ have a old tag which points at * you _could_ have an old tag which points at
* something you do not have which may or may not * something you do not have, which may or may not
* be a commit. * be a commit.
*/ */
if (!ref_newer(ref->peer_ref->new_sha1, if (!ref_newer(ref->peer_ref->new_sha1,

1
templates/remotes-- Normal file
View File

@ -0,0 +1 @@
: this is just to ensure the directory exists.