git/git-clone.sh

416 строки
9.7 KiB
Bash
Исходник Обычный вид История

#!/bin/sh
#
# Copyright (c) 2005, Linus Torvalds
# Copyright (c) 2005, Junio C Hamano
#
# Clone a repository into a different directory that does not yet exist.
# See git-sh-setup why.
unset CDPATH
usage() {
echo >&2 "Usage: $0 [--use-separate-remote] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [-n] <repo> [<dir>]"
exit 1
}
get_repo_base() {
(cd "$1" && (cd .git ; pwd)) 2> /dev/null
}
if [ -n "$GIT_SSL_NO_VERIFY" ]; then
curl_extra_args="-k"
fi
http_fetch () {
# $1 = Remote, $2 = Local
curl -nsfL $curl_extra_args "$1" >"$2"
}
clone_dumb_http () {
# $1 - remote, $2 - local
cd "$2" &&
clone_tmp='.git/clone-tmp' &&
mkdir -p "$clone_tmp" || exit 1
http_fetch "$1/info/refs" "$clone_tmp/refs" || {
echo >&2 "Cannot get remote repository information.
Perhaps git-update-server-info needs to be run there?"
exit 1;
}
while read sha1 refname
do
name=`expr "z$refname" : 'zrefs/\(.*\)'` &&
case "$name" in
*^*) continue;;
esac
if test -n "$use_separate_remote" &&
branch_name=`expr "z$name" : 'zheads/\(.*\)'`
then
tname="remotes/$origin/$branch_name"
else
tname=$name
fi
git-http-fetch -v -a -w "$tname" "$name" "$1/" || exit 1
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 03:25:01 +04:00
http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" ||
rm -f "$GIT_DIR/REMOTE_HEAD"
}
# Read git-fetch-pack -k output and store the remote branches.
copy_refs='
use File::Path qw(mkpath);
use File::Basename qw(dirname);
my $git_dir = $ARGV[0];
my $use_separate_remote = $ARGV[1];
my $origin = $ARGV[2];
my $branch_top = ($use_separate_remote ? "remotes/$origin" : "heads");
my $tag_top = "tags";
sub store {
my ($sha1, $name, $top) = @_;
$name = "$git_dir/refs/$top/$name";
mkpath(dirname($name));
open O, ">", "$name";
print O "$sha1\n";
close O;
}
open FH, "<", "$git_dir/CLONE_HEAD";
while (<FH>) {
my ($sha1, $name) = /^([0-9a-f]{40})\s(.*)$/;
next if ($name =~ /\^\173/);
if ($name eq "HEAD") {
open O, ">", "$git_dir/REMOTE_HEAD";
print O "$sha1\n";
close O;
next;
}
if ($name =~ s/^refs\/heads\///) {
store($sha1, $name, $branch_top);
next;
}
if ($name =~ s/^refs\/tags\///) {
store($sha1, $name, $tag_top);
next;
}
}
close FH;
'
quiet=
local=no
use_local=no
local_shared=no
no_checkout=
upload_pack=
bare=
reference=
origin=
origin_override=
use_separate_remote=
while
case "$#,$1" in
0,*) break ;;
*,-n|*,--no|*,--no-|*,--no-c|*,--no-ch|*,--no-che|*,--no-chec|\
*,--no-check|*,--no-checko|*,--no-checkou|*,--no-checkout)
no_checkout=yes ;;
*,--na|*,--nak|*,--nake|*,--naked|\
*,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;;
*,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;
*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
local_shared=yes; use_local=yes ;;
*,-q|*,--quiet) quiet=-q ;;
*,--use-separate-remote)
use_separate_remote=t ;;
1,--reference) usage ;;
*,--reference)
shift; reference="$1" ;;
*,--reference=*)
reference=`expr "$1" : '--reference=\(.*\)'` ;;
*,-o|*,--or|*,--ori|*,--orig|*,--origi|*,--origin)
case "$2" in
'')
usage ;;
*/*)
echo >&2 "'$2' is not suitable for an origin name"
exit 1
esac
git-check-ref-format "heads/$2" || {
echo >&2 "'$2' is not suitable for a branch name"
exit 1
}
test -z "$origin_override" || {
echo >&2 "Do not give more than one --origin options."
exit 1
}
origin_override=yes
origin="$2"; shift
;;
1,-u|1,--upload-pack) usage ;;
*,-u|*,--upload-pack)
shift
upload_pack="--exec=$1" ;;
*,-*) usage ;;
*) break ;;
esac
do
shift
done
repo="$1"
if test -z "$repo"
then
echo >&2 'you must specify a repository to clone.'
exit 1
fi
# --bare implies --no-checkout
if test yes = "$bare"
then
if test yes = "$origin_override"
then
echo >&2 '--bare and --origin $origin options are incompatible.'
exit 1
fi
if test t = "$use_separate_remote"
then
echo >&2 '--bare and --use-separate-remote options are incompatible.'
exit 1
fi
no_checkout=yes
fi
if test -z "$origin"
then
origin=origin
fi
# Turn the source into an absolute path if
# it is local
if base=$(get_repo_base "$repo"); then
repo="$base"
local=yes
fi
dir="$2"
# Try using "humanish" part of source repo if user didn't specify one
[ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
[ -e "$dir" ] && echo "$dir already exists." && usage
mkdir -p "$dir" &&
D=$(cd "$dir" && pwd) &&
trap 'err=$?; cd ..; rm -r "$D"; exit $err' exit
case "$bare" in
yes) GIT_DIR="$D" ;;
*) GIT_DIR="$D/.git" ;;
esac && export GIT_DIR && git-init-db || usage
case "$bare" in
yes)
GIT_DIR="$D" ;;
*)
GIT_DIR="$D/.git" ;;
esac
if test -n "$reference"
then
if test -d "$reference"
then
if test -d "$reference/.git/objects"
then
reference="$reference/.git"
fi
reference=$(cd "$reference" && pwd)
echo "$reference/objects" >"$GIT_DIR/objects/info/alternates"
(cd "$reference" && tar cf - refs) |
(cd "$GIT_DIR/refs" &&
mkdir reference-tmp &&
cd reference-tmp &&
tar xf -)
else
echo >&2 "$reference: not a local directory." && usage
fi
fi
rm -f "$GIT_DIR/CLONE_HEAD"
# We do local magic only when the user tells us to.
case "$local,$use_local" in
yes,yes)
( cd "$repo/objects" ) || {
echo >&2 "-l flag seen but $repo is not local."
exit 1
}
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)
# objects directory should not be empty since we are cloning!
test -f "$repo/$sample_file" || exit
l=
if ln "$repo/$sample_file" "$GIT_DIR/objects/sample" 2>/dev/null
then
l=l
fi &&
rm -f "$GIT_DIR/objects/sample" &&
cd "$repo" &&
find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1
;;
yes)
mkdir -p "$GIT_DIR/objects/info"
{
test -f "$repo/objects/info/alternates" &&
cat "$repo/objects/info/alternates";
echo "$repo/objects"
} >"$GIT_DIR/objects/info/alternates"
;;
esac
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
;;
*)
case "$repo" in
rsync://*)
rsync $quiet -av --ignore-existing \
--exclude info "$repo/objects/" "$GIT_DIR/objects/" ||
exit
# 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.
rsync -q "$repo/objects/info/alternates" \
"$GIT_DIR/TMP_ALT" 2>/dev/null ||
rm -f "$GIT_DIR/TMP_ALT"
if test -f "$GIT_DIR/TMP_ALT"
then
( cd "$D" &&
. git-parse-remote &&
resolve_alternates "$repo" <"$GIT_DIR/TMP_ALT" ) |
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 \
--exclude info "$alt" "$GIT_DIR/objects" || exit
done
rm -f "$GIT_DIR/TMP_ALT"
fi
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
;;
http://*)
if test -z "@@NO_CURL@@"
then
clone_dumb_http "$repo" "$D"
else
echo >&2 "http transport not supported, rebuild Git with curl support"
exit 1
fi
;;
*)
cd "$D" && case "$upload_pack" in
'') git-fetch-pack --all -k $quiet "$repo" ;;
*) git-fetch-pack --all -k $quiet "$upload_pack" "$repo" ;;
esac >"$GIT_DIR/CLONE_HEAD" || {
echo >&2 "fetch-pack from '$repo' failed."
exit 1
}
;;
esac
;;
esac
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 03:25:01 +04:00
# Read git-fetch-pack -k output and store the remote branches.
perl -e "$copy_refs" "$GIT_DIR" "$use_separate_remote" "$origin"
fi
cd "$D" || exit
if test -z "$bare" && test -f "$GIT_DIR/REMOTE_HEAD"
then
# Figure out which remote branch HEAD points at.
case "$use_separate_remote" in
'') remote_top=refs/heads ;;
*) remote_top="refs/remotes/$origin" ;;
esac
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 03:25:01 +04: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.
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 03:25:01 +04:00
head_sha1=`cat "$GIT_DIR/$remote_top/$head_sha1"`
;;
esac
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 03:25:01 +04:00
# The name under $remote_top the remote HEAD seems to point at.
head_points_at=$(
(
echo "master"
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
)
)
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 03:25:01 +04:00
# Write out remotes/$origin file, and update our "$head_points_at".
case "$head_points_at" in
?*)
mkdir -p "$GIT_DIR/remotes" &&
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 03:25:01 +04:00
git-symbolic-ref HEAD "refs/heads/$head_points_at" &&
case "$use_separate_remote" in
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 03:25:01 +04:00
t) origin_track="$remote_top/$head_points_at"
git-update-ref HEAD "$head_sha1" ;;
*) origin_track="$remote_top/$origin"
git-update-ref "refs/heads/$origin" "$head_sha1" ;;
esac &&
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 03:25:01 +04:00
echo >"$GIT_DIR/remotes/$origin" \
"URL: $repo
Pull: refs/heads/$head_points_at:$origin_track" &&
(cd "$GIT_DIR/$remote_top" && find . -type f -print) |
while read dotslref
do
name=`expr "$dotslref" : './\(.*\)'` &&
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 03:25:01 +04:00
test "$use_separate_remote" = '' && {
test "$head_points_at" = "$name" ||
test "$origin" = "$name"
} ||
echo "Pull: refs/heads/${name}:$remote_top/${name}"
done >>"$GIT_DIR/remotes/$origin" &&
case "$use_separate_remote" in
t)
rm -f "refs/remotes/$origin/HEAD"
git-symbolic-ref "refs/remotes/$origin/HEAD" \
"refs/remotes/$origin/$head_points_at"
esac
esac
case "$no_checkout" in
'')
git-read-tree -m -u -v HEAD HEAD
esac
fi
rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD"
trap - exit