2005-06-23 09:49:43 +08:00
|
|
|
#!/bin/sh
|
2005-07-07 04:04:21 +08:00
|
|
|
#
|
|
|
|
# Copyright (c) 2005, Linus Torvalds
|
|
|
|
# Copyright (c) 2005, Junio C Hamano
|
2007-06-07 15:04:01 +08:00
|
|
|
#
|
2005-07-07 04:04:21 +08:00
|
|
|
# Clone a repository into a different directory that does not yet exist.
|
|
|
|
|
2005-09-13 10:47:07 +08:00
|
|
|
# See git-sh-setup why.
|
|
|
|
unset CDPATH
|
|
|
|
|
2006-10-21 03:38:31 +08:00
|
|
|
die() {
|
|
|
|
echo >&2 "$@"
|
2005-07-07 04:04:21 +08:00
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
2006-10-21 03:38:31 +08:00
|
|
|
usage() {
|
2006-12-27 18:43:46 +08:00
|
|
|
die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]"
|
2006-10-21 03:38:31 +08:00
|
|
|
}
|
|
|
|
|
2005-07-09 06:46:33 +08:00
|
|
|
get_repo_base() {
|
2007-05-10 08:11:15 +08:00
|
|
|
(
|
|
|
|
cd "`/bin/pwd`" &&
|
2007-06-07 07:39:05 +08:00
|
|
|
cd "$1" || cd "$1.git" &&
|
2007-05-10 08:11:15 +08:00
|
|
|
{
|
2007-05-15 05:24:02 +08:00
|
|
|
cd .git
|
2007-05-10 08:11:15 +08:00
|
|
|
pwd
|
|
|
|
}
|
2007-05-15 05:24:02 +08:00
|
|
|
) 2>/dev/null
|
2005-07-09 06:46:33 +08:00
|
|
|
}
|
|
|
|
|
2005-09-05 15:47:39 +08:00
|
|
|
if [ -n "$GIT_SSL_NO_VERIFY" ]; then
|
|
|
|
curl_extra_args="-k"
|
|
|
|
fi
|
|
|
|
|
|
|
|
http_fetch () {
|
|
|
|
# $1 = Remote, $2 = Local
|
2005-11-10 21:12:19 +08:00
|
|
|
curl -nsfL $curl_extra_args "$1" >"$2"
|
2005-09-05 15:47:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
clone_dumb_http () {
|
|
|
|
# $1 - remote, $2 - local
|
|
|
|
cd "$2" &&
|
2006-06-10 16:12:50 +08:00
|
|
|
clone_tmp="$GIT_DIR/clone-tmp" &&
|
2005-09-05 15:47:39 +08:00
|
|
|
mkdir -p "$clone_tmp" || exit 1
|
2006-09-29 08:10:44 +08:00
|
|
|
if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
|
2007-01-29 08:16:53 +08:00
|
|
|
"`git-config --bool http.noEPSV`" = true ]; then
|
2006-09-29 08:10:44 +08:00
|
|
|
curl_extra_args="${curl_extra_args} --disable-epsv"
|
|
|
|
fi
|
2006-10-21 03:38:31 +08:00
|
|
|
http_fetch "$1/info/refs" "$clone_tmp/refs" ||
|
|
|
|
die "Cannot get remote repository information.
|
2005-09-05 15:47:39 +08:00
|
|
|
Perhaps git-update-server-info needs to be run there?"
|
2007-03-20 10:18:18 +08:00
|
|
|
test "z$quiet" = z && v=-v || v=
|
2005-09-05 15:47:39 +08:00
|
|
|
while read sha1 refname
|
|
|
|
do
|
2006-04-14 06:01:24 +08:00
|
|
|
name=`expr "z$refname" : 'zrefs/\(.*\)'` &&
|
2005-10-18 12:47:06 +08:00
|
|
|
case "$name" in
|
2006-03-20 16:21:10 +08:00
|
|
|
*^*) continue;;
|
2005-10-18 12:47:06 +08:00
|
|
|
esac
|
2006-11-25 11:07:24 +08:00
|
|
|
case "$bare,$name" in
|
|
|
|
yes,* | ,heads/* | ,tags/*) ;;
|
|
|
|
*) continue ;;
|
|
|
|
esac
|
2006-03-20 16:21:10 +08:00
|
|
|
if test -n "$use_separate_remote" &&
|
2006-04-14 06:01:24 +08:00
|
|
|
branch_name=`expr "z$name" : 'zheads/\(.*\)'`
|
2006-03-20 16:21:10 +08:00
|
|
|
then
|
2006-03-21 17:58:26 +08:00
|
|
|
tname="remotes/$origin/$branch_name"
|
2006-03-20 16:21:10 +08:00
|
|
|
else
|
|
|
|
tname=$name
|
|
|
|
fi
|
2007-04-21 08:25:27 +08:00
|
|
|
git-http-fetch $v -a -w "$tname" "$sha1" "$1" || exit 1
|
2005-09-05 15:47:39 +08:00
|
|
|
done <"$clone_tmp/refs"
|
|
|
|
rm -fr "$clone_tmp"
|
git-clone: fix handling of upsteram whose HEAD does not point at master.
When cloning from a remote repository that has master, main, and
origin branches _and_ with the HEAD pointing at main branch, we
did quite confused things during clone. So this cleans things
up. The behaviour is a bit different between separate remotes/
layout and the mixed branches layout.
The newer layout with $GIT_DIR/refs/remotes/$origin/, things are
simpler and more transparent:
- remote branches are copied to refs/remotes/$origin/.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches, and merge the branch HEAD pointed at at the time of
the cloning.
Everything-in-refs/heads layout was the more confused one, but
cleaned up like this:
- remote branches are copied to refs/heads, but the branch
"$origin" is not copied, instead a copy of the branch the
remote HEAD points at is created there.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches except "$origin", and merge the branch HEAD pointed
at at the time of the cloning.
With this, the remote has master, main and origin, and its HEAD
points at main, you could:
git clone $URL --origin upstream
to use refs/heads/upstream as the tracking branch for remote
"main", and your primary working branch will also be "main".
"master" and "origin" are used to track the corresponding remote
branches and with this setup they do not have any special meaning.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-03 07:25:01 +08:00
|
|
|
http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" ||
|
|
|
|
rm -f "$GIT_DIR/REMOTE_HEAD"
|
2007-06-29 16:31:08 +08:00
|
|
|
if test -f "$GIT_DIR/REMOTE_HEAD"; then
|
|
|
|
head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
|
|
|
|
case "$head_sha1" in
|
|
|
|
'ref: refs/'*)
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
git-http-fetch $v -a "$head_sha1" "$1" ||
|
|
|
|
rm -f "$GIT_DIR/REMOTE_HEAD"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
fi
|
2006-03-20 16:21:10 +08:00
|
|
|
}
|
|
|
|
|
2005-07-10 01:52:35 +08:00
|
|
|
quiet=
|
2006-03-31 01:01:23 +08:00
|
|
|
local=no
|
2005-07-07 04:04:21 +08:00
|
|
|
use_local=no
|
2005-08-15 08:25:57 +08:00
|
|
|
local_shared=no
|
2006-05-29 01:14:38 +08:00
|
|
|
unset template
|
2005-09-27 08:17:09 +08:00
|
|
|
no_checkout=
|
2005-07-14 11:25:54 +08:00
|
|
|
upload_pack=
|
2006-01-23 09:24:22 +08:00
|
|
|
bare=
|
2006-03-20 16:21:10 +08:00
|
|
|
reference=
|
|
|
|
origin=
|
2006-01-23 09:28:49 +08:00
|
|
|
origin_override=
|
2006-11-24 06:58:35 +08:00
|
|
|
use_separate_remote=t
|
allow cloning a repository "shallowly"
By specifying a depth, you can now clone a repository such that
all fetched ancestor-chains' length is at most "depth". For example,
if the upstream repository has only 2 branches ("A" and "B"), which
are linear, and you specify depth 3, you will get A, A~1, A~2, A~3,
B, B~1, B~2, and B~3. The ends are automatically made shallow
commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-31 03:09:29 +08:00
|
|
|
depth=
|
2007-02-20 10:01:44 +08:00
|
|
|
no_progress=
|
|
|
|
test -t 1 || no_progress=--no-progress
|
2005-07-07 04:04:21 +08:00
|
|
|
while
|
|
|
|
case "$#,$1" in
|
|
|
|
0,*) break ;;
|
2006-01-15 08:00:32 +08:00
|
|
|
*,-n|*,--no|*,--no-|*,--no-c|*,--no-ch|*,--no-che|*,--no-chec|\
|
|
|
|
*,--no-check|*,--no-checko|*,--no-checkou|*,--no-checkout)
|
|
|
|
no_checkout=yes ;;
|
2006-01-23 09:24:22 +08:00
|
|
|
*,--na|*,--nak|*,--nake|*,--naked|\
|
|
|
|
*,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;;
|
2005-07-23 10:11:22 +08:00
|
|
|
*,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;
|
2007-06-07 15:04:01 +08:00
|
|
|
*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
|
2005-11-29 14:20:49 +08:00
|
|
|
local_shared=yes; use_local=yes ;;
|
2006-05-29 01:14:38 +08:00
|
|
|
1,--template) usage ;;
|
|
|
|
*,--template)
|
|
|
|
shift; template="--template=$1" ;;
|
|
|
|
*,--template=*)
|
|
|
|
template="$1" ;;
|
2005-07-10 01:52:35 +08:00
|
|
|
*,-q|*,--quiet) quiet=-q ;;
|
2006-12-16 17:53:10 +08:00
|
|
|
*,--use-separate-remote) ;;
|
2006-12-04 21:29:09 +08:00
|
|
|
*,--no-separate-remote)
|
2006-12-16 17:53:10 +08:00
|
|
|
die "clones are always made with separate-remote layout" ;;
|
2006-03-20 16:21:10 +08:00
|
|
|
1,--reference) usage ;;
|
|
|
|
*,--reference)
|
|
|
|
shift; reference="$1" ;;
|
|
|
|
*,--reference=*)
|
2006-06-28 00:54:26 +08:00
|
|
|
reference=`expr "z$1" : 'z--reference=\(.*\)'` ;;
|
2006-03-31 01:00:43 +08:00
|
|
|
*,-o|*,--or|*,--ori|*,--orig|*,--origi|*,--origin)
|
2006-03-21 16:14:13 +08:00
|
|
|
case "$2" in
|
2006-03-31 01:00:43 +08:00
|
|
|
'')
|
|
|
|
usage ;;
|
2006-03-21 16:14:13 +08:00
|
|
|
*/*)
|
2006-10-21 03:38:31 +08:00
|
|
|
die "'$2' is not suitable for an origin name"
|
2006-03-21 16:14:13 +08:00
|
|
|
esac
|
2006-10-21 03:38:31 +08:00
|
|
|
git-check-ref-format "heads/$2" ||
|
|
|
|
die "'$2' is not suitable for a branch name"
|
|
|
|
test -z "$origin_override" ||
|
|
|
|
die "Do not give more than one --origin options."
|
2006-01-23 09:28:49 +08:00
|
|
|
origin_override=yes
|
2005-12-23 06:37:24 +08:00
|
|
|
origin="$2"; shift
|
|
|
|
;;
|
2005-07-23 10:11:22 +08:00
|
|
|
1,-u|1,--upload-pack) usage ;;
|
2005-07-14 11:25:54 +08:00
|
|
|
*,-u|*,--upload-pack)
|
|
|
|
shift
|
2007-01-23 16:51:53 +08:00
|
|
|
upload_pack="--upload-pack=$1" ;;
|
|
|
|
*,--upload-pack=*)
|
2007-01-31 02:11:49 +08:00
|
|
|
upload_pack=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
|
allow cloning a repository "shallowly"
By specifying a depth, you can now clone a repository such that
all fetched ancestor-chains' length is at most "depth". For example,
if the upstream repository has only 2 branches ("A" and "B"), which
are linear, and you specify depth 3, you will get A, A~1, A~2, A~3,
B, B~1, B~2, and B~3. The ends are automatically made shallow
commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-31 03:09:29 +08:00
|
|
|
1,--depth) usage;;
|
|
|
|
*,--depth)
|
|
|
|
shift
|
|
|
|
depth="--depth=$1";;
|
2005-07-07 04:04:21 +08:00
|
|
|
*,-*) usage ;;
|
|
|
|
*) break ;;
|
|
|
|
esac
|
|
|
|
do
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2006-03-31 01:01:23 +08:00
|
|
|
repo="$1"
|
2006-10-21 03:38:31 +08:00
|
|
|
test -n "$repo" ||
|
|
|
|
die 'you must specify a repository to clone.'
|
2006-03-31 01:01:23 +08:00
|
|
|
|
2006-12-04 21:29:09 +08:00
|
|
|
# --bare implies --no-checkout and --no-separate-remote
|
2006-01-23 09:28:49 +08:00
|
|
|
if test yes = "$bare"
|
|
|
|
then
|
|
|
|
if test yes = "$origin_override"
|
|
|
|
then
|
2006-10-21 03:38:31 +08:00
|
|
|
die '--bare and --origin $origin options are incompatible.'
|
2006-01-23 09:28:49 +08:00
|
|
|
fi
|
|
|
|
no_checkout=yes
|
2006-11-24 06:58:35 +08:00
|
|
|
use_separate_remote=
|
2006-01-23 09:28:49 +08:00
|
|
|
fi
|
2006-01-15 08:00:32 +08:00
|
|
|
|
2006-03-21 16:14:13 +08:00
|
|
|
if test -z "$origin"
|
2006-03-20 16:21:10 +08:00
|
|
|
then
|
2006-03-21 16:14:13 +08:00
|
|
|
origin=origin
|
2006-03-20 16:21:10 +08:00
|
|
|
fi
|
|
|
|
|
2005-07-09 06:46:33 +08:00
|
|
|
# Turn the source into an absolute path if
|
|
|
|
# it is local
|
|
|
|
if base=$(get_repo_base "$repo"); then
|
|
|
|
repo="$base"
|
|
|
|
local=yes
|
|
|
|
fi
|
|
|
|
|
2005-06-23 09:49:43 +08:00
|
|
|
dir="$2"
|
2005-11-10 19:58:08 +08:00
|
|
|
# Try using "humanish" part of source repo if user didn't specify one
|
2006-01-20 14:47:39 +08:00
|
|
|
[ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
|
2006-10-21 03:38:31 +08:00
|
|
|
[ -e "$dir" ] && die "destination directory '$dir' already exists."
|
2005-11-10 19:58:08 +08:00
|
|
|
mkdir -p "$dir" &&
|
2006-01-15 08:00:32 +08:00
|
|
|
D=$(cd "$dir" && pwd) &&
|
2006-07-30 00:12:34 +08:00
|
|
|
trap 'err=$?; cd ..; rm -rf "$D"; exit $err' 0
|
2006-01-23 09:24:22 +08:00
|
|
|
case "$bare" in
|
2006-01-15 08:00:32 +08:00
|
|
|
yes)
|
|
|
|
GIT_DIR="$D" ;;
|
|
|
|
*)
|
|
|
|
GIT_DIR="$D/.git" ;;
|
2007-06-07 20:50:30 +08:00
|
|
|
esac && export GIT_DIR && git-init $quiet ${template+"$template"} || usage
|
2005-07-07 04:04:21 +08:00
|
|
|
|
2006-03-20 16:21:10 +08:00
|
|
|
if test -n "$reference"
|
|
|
|
then
|
2007-02-07 18:10:56 +08:00
|
|
|
ref_git=
|
2006-03-20 16:21:10 +08:00
|
|
|
if test -d "$reference"
|
|
|
|
then
|
|
|
|
if test -d "$reference/.git/objects"
|
|
|
|
then
|
2007-02-07 18:10:56 +08:00
|
|
|
ref_git="$reference/.git"
|
|
|
|
elif test -d "$reference/objects"
|
|
|
|
then
|
|
|
|
ref_git="$reference"
|
2006-03-20 16:21:10 +08:00
|
|
|
fi
|
2007-02-07 18:10:56 +08:00
|
|
|
fi
|
|
|
|
if test -n "$ref_git"
|
|
|
|
then
|
|
|
|
ref_git=$(cd "$ref_git" && pwd)
|
|
|
|
echo "$ref_git/objects" >"$GIT_DIR/objects/info/alternates"
|
|
|
|
(
|
|
|
|
GIT_DIR="$ref_git" git for-each-ref \
|
|
|
|
--format='%(objectname) %(*objectname)'
|
|
|
|
) |
|
|
|
|
while read a b
|
|
|
|
do
|
|
|
|
test -z "$a" ||
|
|
|
|
git update-ref "refs/reference-tmp/$a" "$a"
|
|
|
|
test -z "$b" ||
|
|
|
|
git update-ref "refs/reference-tmp/$b" "$b"
|
|
|
|
done
|
2006-03-20 16:21:10 +08:00
|
|
|
else
|
2006-10-21 03:38:31 +08:00
|
|
|
die "reference repository '$reference' is not a local directory."
|
2006-03-20 16:21:10 +08:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
rm -f "$GIT_DIR/CLONE_HEAD"
|
|
|
|
|
2005-07-07 04:04:21 +08:00
|
|
|
# We do local magic only when the user tells us to.
|
2005-07-09 06:46:33 +08:00
|
|
|
case "$local,$use_local" in
|
|
|
|
yes,yes)
|
2006-10-21 03:38:31 +08:00
|
|
|
( cd "$repo/objects" ) ||
|
|
|
|
die "-l flag seen but repository '$repo' is not local."
|
2005-07-07 04:04:21 +08:00
|
|
|
|
2005-08-15 08:25:57 +08:00
|
|
|
case "$local_shared" in
|
|
|
|
no)
|
|
|
|
# See if we can hardlink and drop "l" if not.
|
|
|
|
sample_file=$(cd "$repo" && \
|
|
|
|
find objects -type f -print | sed -e 1q)
|
2005-07-07 04:04:21 +08:00
|
|
|
|
2005-08-15 08:25:57 +08:00
|
|
|
# objects directory should not be empty since we are cloning!
|
|
|
|
test -f "$repo/$sample_file" || exit
|
2005-07-07 04:04:21 +08:00
|
|
|
|
2005-08-15 08:25:57 +08:00
|
|
|
l=
|
2006-01-15 08:00:32 +08:00
|
|
|
if ln "$repo/$sample_file" "$GIT_DIR/objects/sample" 2>/dev/null
|
2005-08-15 08:25:57 +08:00
|
|
|
then
|
|
|
|
l=l
|
|
|
|
fi &&
|
2006-01-15 08:00:32 +08:00
|
|
|
rm -f "$GIT_DIR/objects/sample" &&
|
2005-08-15 08:25:57 +08:00
|
|
|
cd "$repo" &&
|
2006-02-17 22:22:45 +08:00
|
|
|
find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1
|
2005-08-15 08:25:57 +08:00
|
|
|
;;
|
|
|
|
yes)
|
2006-01-15 08:00:32 +08:00
|
|
|
mkdir -p "$GIT_DIR/objects/info"
|
2006-05-08 02:19:33 +08:00
|
|
|
echo "$repo/objects" >> "$GIT_DIR/objects/info/alternates"
|
2005-08-15 08:25:57 +08:00
|
|
|
;;
|
|
|
|
esac
|
2006-07-10 18:34:34 +08:00
|
|
|
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
|
2005-07-09 08:07:12 +08:00
|
|
|
;;
|
|
|
|
*)
|
2005-07-23 10:11:22 +08:00
|
|
|
case "$repo" in
|
|
|
|
rsync://*)
|
allow cloning a repository "shallowly"
By specifying a depth, you can now clone a repository such that
all fetched ancestor-chains' length is at most "depth". For example,
if the upstream repository has only 2 branches ("A" and "B"), which
are linear, and you specify depth 3, you will get A, A~1, A~2, A~3,
B, B~1, B~2, and B~3. The ends are automatically made shallow
commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-31 03:09:29 +08:00
|
|
|
case "$depth" in
|
|
|
|
"") ;;
|
|
|
|
*) die "shallow over rsync not supported" ;;
|
|
|
|
esac
|
2005-09-18 02:56:41 +08:00
|
|
|
rsync $quiet -av --ignore-existing \
|
2006-03-20 16:21:10 +08:00
|
|
|
--exclude info "$repo/objects/" "$GIT_DIR/objects/" ||
|
|
|
|
exit
|
2005-09-18 02:56:41 +08:00
|
|
|
# Look at objects/info/alternates for rsync -- http will
|
|
|
|
# support it natively and git native ones will do it on the
|
|
|
|
# remote end. Not having that file is not a crime.
|
2005-09-20 14:52:33 +08:00
|
|
|
rsync -q "$repo/objects/info/alternates" \
|
2006-01-15 08:00:32 +08:00
|
|
|
"$GIT_DIR/TMP_ALT" 2>/dev/null ||
|
|
|
|
rm -f "$GIT_DIR/TMP_ALT"
|
|
|
|
if test -f "$GIT_DIR/TMP_ALT"
|
2005-09-18 02:56:41 +08:00
|
|
|
then
|
2005-11-11 13:19:04 +08:00
|
|
|
( cd "$D" &&
|
2005-09-18 02:56:41 +08:00
|
|
|
. git-parse-remote &&
|
2006-01-15 08:00:32 +08:00
|
|
|
resolve_alternates "$repo" <"$GIT_DIR/TMP_ALT" ) |
|
2005-09-18 02:56:41 +08:00
|
|
|
while read alt
|
|
|
|
do
|
|
|
|
case "$alt" in 'bad alternate: '*) die "$alt";; esac
|
|
|
|
case "$quiet" in
|
|
|
|
'') echo >&2 "Getting alternate: $alt" ;;
|
|
|
|
esac
|
|
|
|
rsync $quiet -av --ignore-existing \
|
2006-01-15 08:00:32 +08:00
|
|
|
--exclude info "$alt" "$GIT_DIR/objects" || exit
|
2005-09-18 02:56:41 +08:00
|
|
|
done
|
2006-01-15 08:00:32 +08:00
|
|
|
rm -f "$GIT_DIR/TMP_ALT"
|
2005-09-18 02:56:41 +08:00
|
|
|
fi
|
2006-07-10 18:34:34 +08:00
|
|
|
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
|
2005-07-23 10:11:22 +08:00
|
|
|
;;
|
2006-09-14 10:24:04 +08:00
|
|
|
https://*|http://*|ftp://*)
|
allow cloning a repository "shallowly"
By specifying a depth, you can now clone a repository such that
all fetched ancestor-chains' length is at most "depth". For example,
if the upstream repository has only 2 branches ("A" and "B"), which
are linear, and you specify depth 3, you will get A, A~1, A~2, A~3,
B, B~1, B~2, and B~3. The ends are automatically made shallow
commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-10-31 03:09:29 +08:00
|
|
|
case "$depth" in
|
|
|
|
"") ;;
|
|
|
|
*) die "shallow over http or ftp not supported" ;;
|
|
|
|
esac
|
2006-02-15 19:37:30 +08:00
|
|
|
if test -z "@@NO_CURL@@"
|
|
|
|
then
|
|
|
|
clone_dumb_http "$repo" "$D"
|
|
|
|
else
|
2006-10-21 03:38:31 +08:00
|
|
|
die "http transport not supported, rebuild Git with curl support"
|
2006-02-15 19:37:30 +08:00
|
|
|
fi
|
2005-07-23 10:11:22 +08:00
|
|
|
;;
|
|
|
|
*)
|
2006-10-14 20:02:51 +08:00
|
|
|
case "$upload_pack" in
|
2007-02-20 10:01:44 +08:00
|
|
|
'') git-fetch-pack --all -k $quiet $depth $no_progress "$repo";;
|
|
|
|
*) git-fetch-pack --all -k $quiet "$upload_pack" $depth $no_progress "$repo" ;;
|
2006-10-21 03:38:31 +08:00
|
|
|
esac >"$GIT_DIR/CLONE_HEAD" ||
|
|
|
|
die "fetch-pack from '$repo' failed."
|
2005-07-23 10:11:22 +08:00
|
|
|
;;
|
2005-07-14 11:25:54 +08:00
|
|
|
esac
|
2005-07-09 08:07:12 +08:00
|
|
|
;;
|
|
|
|
esac
|
2006-03-20 16:21:10 +08:00
|
|
|
test -d "$GIT_DIR/refs/reference-tmp" && rm -fr "$GIT_DIR/refs/reference-tmp"
|
|
|
|
|
|
|
|
if test -f "$GIT_DIR/CLONE_HEAD"
|
|
|
|
then
|
git-clone: fix handling of upsteram whose HEAD does not point at master.
When cloning from a remote repository that has master, main, and
origin branches _and_ with the HEAD pointing at main branch, we
did quite confused things during clone. So this cleans things
up. The behaviour is a bit different between separate remotes/
layout and the mixed branches layout.
The newer layout with $GIT_DIR/refs/remotes/$origin/, things are
simpler and more transparent:
- remote branches are copied to refs/remotes/$origin/.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches, and merge the branch HEAD pointed at at the time of
the cloning.
Everything-in-refs/heads layout was the more confused one, but
cleaned up like this:
- remote branches are copied to refs/heads, but the branch
"$origin" is not copied, instead a copy of the branch the
remote HEAD points at is created there.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches except "$origin", and merge the branch HEAD pointed
at at the time of the cloning.
With this, the remote has master, main and origin, and its HEAD
points at main, you could:
git clone $URL --origin upstream
to use refs/heads/upstream as the tracking branch for remote
"main", and your primary working branch will also be "main".
"master" and "origin" are used to track the corresponding remote
branches and with this setup they do not have any special meaning.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-03 07:25:01 +08:00
|
|
|
# Read git-fetch-pack -k output and store the remote branches.
|
2007-01-29 16:09:25 +08:00
|
|
|
if [ -n "$use_separate_remote" ]
|
|
|
|
then
|
|
|
|
branch_top="remotes/$origin"
|
|
|
|
else
|
|
|
|
branch_top="heads"
|
|
|
|
fi
|
|
|
|
tag_top="tags"
|
|
|
|
while read sha1 name
|
|
|
|
do
|
|
|
|
case "$name" in
|
|
|
|
*'^{}')
|
|
|
|
continue ;;
|
|
|
|
HEAD)
|
|
|
|
destname="REMOTE_HEAD" ;;
|
|
|
|
refs/heads/*)
|
|
|
|
destname="refs/$branch_top/${name#refs/heads/}" ;;
|
|
|
|
refs/tags/*)
|
|
|
|
destname="refs/$tag_top/${name#refs/tags/}" ;;
|
|
|
|
*)
|
|
|
|
continue ;;
|
|
|
|
esac
|
|
|
|
git-update-ref -m "clone: from $repo" "$destname" "$sha1" ""
|
|
|
|
done < "$GIT_DIR/CLONE_HEAD"
|
2006-03-20 16:21:10 +08:00
|
|
|
fi
|
2005-07-23 10:11:22 +08:00
|
|
|
|
2005-11-11 13:19:04 +08:00
|
|
|
cd "$D" || exit
|
2005-09-27 08:17:09 +08:00
|
|
|
|
2006-03-20 16:21:10 +08:00
|
|
|
if test -z "$bare" && test -f "$GIT_DIR/REMOTE_HEAD"
|
2005-09-27 08:17:09 +08:00
|
|
|
then
|
2006-12-16 17:53:10 +08:00
|
|
|
# a non-bare repository is always in separate-remote layout
|
|
|
|
remote_top="refs/remotes/$origin"
|
git-clone: fix handling of upsteram whose HEAD does not point at master.
When cloning from a remote repository that has master, main, and
origin branches _and_ with the HEAD pointing at main branch, we
did quite confused things during clone. So this cleans things
up. The behaviour is a bit different between separate remotes/
layout and the mixed branches layout.
The newer layout with $GIT_DIR/refs/remotes/$origin/, things are
simpler and more transparent:
- remote branches are copied to refs/remotes/$origin/.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches, and merge the branch HEAD pointed at at the time of
the cloning.
Everything-in-refs/heads layout was the more confused one, but
cleaned up like this:
- remote branches are copied to refs/heads, but the branch
"$origin" is not copied, instead a copy of the branch the
remote HEAD points at is created there.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches except "$origin", and merge the branch HEAD pointed
at at the time of the cloning.
With this, the remote has master, main and origin, and its HEAD
points at main, you could:
git clone $URL --origin upstream
to use refs/heads/upstream as the tracking branch for remote
"main", and your primary working branch will also be "main".
"master" and "origin" are used to track the corresponding remote
branches and with this setup they do not have any special meaning.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-03 07:25:01 +08:00
|
|
|
head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
|
|
|
|
case "$head_sha1" in
|
|
|
|
'ref: refs/'*)
|
|
|
|
# Uh-oh, the remote told us (http transport done against
|
|
|
|
# new style repository with a symref HEAD).
|
|
|
|
# Ideally we should skip the guesswork but for now
|
|
|
|
# opt for minimum change.
|
2006-04-14 06:01:24 +08:00
|
|
|
head_sha1=`expr "z$head_sha1" : 'zref: refs/heads/\(.*\)'`
|
git-clone: fix handling of upsteram whose HEAD does not point at master.
When cloning from a remote repository that has master, main, and
origin branches _and_ with the HEAD pointing at main branch, we
did quite confused things during clone. So this cleans things
up. The behaviour is a bit different between separate remotes/
layout and the mixed branches layout.
The newer layout with $GIT_DIR/refs/remotes/$origin/, things are
simpler and more transparent:
- remote branches are copied to refs/remotes/$origin/.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches, and merge the branch HEAD pointed at at the time of
the cloning.
Everything-in-refs/heads layout was the more confused one, but
cleaned up like this:
- remote branches are copied to refs/heads, but the branch
"$origin" is not copied, instead a copy of the branch the
remote HEAD points at is created there.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches except "$origin", and merge the branch HEAD pointed
at at the time of the cloning.
With this, the remote has master, main and origin, and its HEAD
points at main, you could:
git clone $URL --origin upstream
to use refs/heads/upstream as the tracking branch for remote
"main", and your primary working branch will also be "main".
"master" and "origin" are used to track the corresponding remote
branches and with this setup they do not have any special meaning.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-03 07:25:01 +08:00
|
|
|
head_sha1=`cat "$GIT_DIR/$remote_top/$head_sha1"`
|
|
|
|
;;
|
|
|
|
esac
|
2006-03-21 16:14:13 +08:00
|
|
|
|
git-clone: fix handling of upsteram whose HEAD does not point at master.
When cloning from a remote repository that has master, main, and
origin branches _and_ with the HEAD pointing at main branch, we
did quite confused things during clone. So this cleans things
up. The behaviour is a bit different between separate remotes/
layout and the mixed branches layout.
The newer layout with $GIT_DIR/refs/remotes/$origin/, things are
simpler and more transparent:
- remote branches are copied to refs/remotes/$origin/.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches, and merge the branch HEAD pointed at at the time of
the cloning.
Everything-in-refs/heads layout was the more confused one, but
cleaned up like this:
- remote branches are copied to refs/heads, but the branch
"$origin" is not copied, instead a copy of the branch the
remote HEAD points at is created there.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches except "$origin", and merge the branch HEAD pointed
at at the time of the cloning.
With this, the remote has master, main and origin, and its HEAD
points at main, you could:
git clone $URL --origin upstream
to use refs/heads/upstream as the tracking branch for remote
"main", and your primary working branch will also be "main".
"master" and "origin" are used to track the corresponding remote
branches and with this setup they do not have any special meaning.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-03 07:25:01 +08:00
|
|
|
# The name under $remote_top the remote HEAD seems to point at.
|
2006-03-20 16:21:10 +08:00
|
|
|
head_points_at=$(
|
|
|
|
(
|
2007-01-10 04:26:52 +08:00
|
|
|
test -f "$GIT_DIR/$remote_top/master" && echo "master"
|
2006-03-20 16:21:10 +08:00
|
|
|
cd "$GIT_DIR/$remote_top" &&
|
|
|
|
find . -type f -print | sed -e 's/^\.\///'
|
|
|
|
) | (
|
|
|
|
done=f
|
|
|
|
while read name
|
|
|
|
do
|
|
|
|
test t = $done && continue
|
|
|
|
branch_tip=`cat "$GIT_DIR/$remote_top/$name"`
|
|
|
|
if test "$head_sha1" = "$branch_tip"
|
|
|
|
then
|
|
|
|
echo "$name"
|
|
|
|
done=t
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
)
|
|
|
|
)
|
2006-03-21 16:14:13 +08:00
|
|
|
|
2007-06-17 06:26:08 +08:00
|
|
|
# Upstream URL
|
|
|
|
git-config remote."$origin".url "$repo" &&
|
|
|
|
|
|
|
|
# Set up the mappings to track the remote branches.
|
|
|
|
git-config remote."$origin".fetch \
|
|
|
|
"+refs/heads/*:$remote_top/*" '^$' &&
|
|
|
|
|
2006-12-16 17:14:39 +08:00
|
|
|
# Write out remote.$origin config, and update our "$head_points_at".
|
2005-11-02 14:19:36 +08:00
|
|
|
case "$head_points_at" in
|
2006-03-20 16:21:10 +08:00
|
|
|
?*)
|
2006-12-16 17:14:39 +08:00
|
|
|
# Local default branch
|
git-clone: fix handling of upsteram whose HEAD does not point at master.
When cloning from a remote repository that has master, main, and
origin branches _and_ with the HEAD pointing at main branch, we
did quite confused things during clone. So this cleans things
up. The behaviour is a bit different between separate remotes/
layout and the mixed branches layout.
The newer layout with $GIT_DIR/refs/remotes/$origin/, things are
simpler and more transparent:
- remote branches are copied to refs/remotes/$origin/.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches, and merge the branch HEAD pointed at at the time of
the cloning.
Everything-in-refs/heads layout was the more confused one, but
cleaned up like this:
- remote branches are copied to refs/heads, but the branch
"$origin" is not copied, instead a copy of the branch the
remote HEAD points at is created there.
- HEAD points at the branch with the same name as the remote
HEAD points at, and starts at where the remote HEAD points at.
- $GIT_DIR/remotes/$origin file is set up to fetch all remote
branches except "$origin", and merge the branch HEAD pointed
at at the time of the cloning.
With this, the remote has master, main and origin, and its HEAD
points at main, you could:
git clone $URL --origin upstream
to use refs/heads/upstream as the tracking branch for remote
"main", and your primary working branch will also be "main".
"master" and "origin" are used to track the corresponding remote
branches and with this setup they do not have any special meaning.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-03 07:25:01 +08:00
|
|
|
git-symbolic-ref HEAD "refs/heads/$head_points_at" &&
|
2006-12-16 17:14:39 +08:00
|
|
|
|
|
|
|
# Tracking branch for the primary branch at the remote.
|
2006-12-16 17:53:10 +08:00
|
|
|
git-update-ref HEAD "$head_sha1" &&
|
2006-12-16 17:14:39 +08:00
|
|
|
|
2006-12-16 17:53:10 +08:00
|
|
|
rm -f "refs/remotes/$origin/HEAD"
|
|
|
|
git-symbolic-ref "refs/remotes/$origin/HEAD" \
|
|
|
|
"refs/remotes/$origin/$head_points_at" &&
|
2006-12-16 17:14:39 +08:00
|
|
|
|
2007-01-29 08:16:53 +08:00
|
|
|
git-config branch."$head_points_at".remote "$origin" &&
|
|
|
|
git-config branch."$head_points_at".merge "refs/heads/$head_points_at"
|
2007-06-17 06:26:08 +08:00
|
|
|
;;
|
|
|
|
'')
|
|
|
|
# Source had detached HEAD pointing nowhere
|
|
|
|
git-update-ref --no-deref HEAD "$head_sha1" &&
|
|
|
|
rm -f "refs/remotes/$origin/HEAD"
|
|
|
|
;;
|
2005-11-02 14:19:36 +08:00
|
|
|
esac
|
|
|
|
|
2005-09-27 08:17:09 +08:00
|
|
|
case "$no_checkout" in
|
|
|
|
'')
|
2007-02-24 03:03:10 +08:00
|
|
|
test "z$quiet" = z -a "z$no_progress" = z && v=-v || v=
|
2006-10-23 21:59:48 +08:00
|
|
|
git-read-tree -m -u $v HEAD HEAD
|
2005-09-27 08:17:09 +08:00
|
|
|
esac
|
|
|
|
fi
|
2006-03-20 16:21:10 +08:00
|
|
|
rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD"
|
2006-02-18 05:33:24 +08:00
|
|
|
|
2006-05-23 03:34:00 +08:00
|
|
|
trap - 0
|