Skip to content

Commit c72112e

Browse files
author
Junio C Hamano
committed
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>
1 parent 40e907b commit c72112e

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

git-clone.sh

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ Perhaps git-update-server-info needs to be run there?"
5252
git-http-fetch -v -a -w "$tname" "$name" "$1/" || exit 1
5353
done <"$clone_tmp/refs"
5454
rm -fr "$clone_tmp"
55-
http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD"
55+
http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" ||
56+
rm -f "$GIT_DIR/REMOTE_HEAD"
5657
}
5758

5859
# Read git-fetch-pack -k output and store the remote branches.
@@ -324,30 +325,33 @@ test -d "$GIT_DIR/refs/reference-tmp" && rm -fr "$GIT_DIR/refs/reference-tmp"
324325

325326
if test -f "$GIT_DIR/CLONE_HEAD"
326327
then
327-
# Figure out where the remote HEAD points at.
328+
# Read git-fetch-pack -k output and store the remote branches.
328329
perl -e "$copy_refs" "$GIT_DIR" "$use_separate_remote" "$origin"
329330
fi
330331

331332
cd "$D" || exit
332333

333334
if test -z "$bare" && test -f "$GIT_DIR/REMOTE_HEAD"
334335
then
335-
head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
336336
# Figure out which remote branch HEAD points at.
337337
case "$use_separate_remote" in
338338
'') remote_top=refs/heads ;;
339339
*) remote_top="refs/remotes/$origin" ;;
340340
esac
341341

342-
# What to use to track the remote primary branch
343-
if test -n "$use_separate_remote"
344-
then
345-
origin_tracking="remotes/$origin/master"
346-
else
347-
origin_tracking="heads/$origin"
348-
fi
342+
head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
343+
case "$head_sha1" in
344+
'ref: refs/'*)
345+
# Uh-oh, the remote told us (http transport done against
346+
# new style repository with a symref HEAD).
347+
# Ideally we should skip the guesswork but for now
348+
# opt for minimum change.
349+
head_sha1=`expr "$head_sha1" : 'ref: refs/heads/\(.*\)'`
350+
head_sha1=`cat "$GIT_DIR/$remote_top/$head_sha1"`
351+
;;
352+
esac
349353

350-
# The name under $remote_top the remote HEAD seems to point at
354+
# The name under $remote_top the remote HEAD seems to point at.
351355
head_points_at=$(
352356
(
353357
echo "master"
@@ -368,23 +372,28 @@ then
368372
)
369373
)
370374

371-
# Write out remotes/$origin file.
375+
# Write out remotes/$origin file, and update our "$head_points_at".
372376
case "$head_points_at" in
373377
?*)
374378
mkdir -p "$GIT_DIR/remotes" &&
375-
echo >"$GIT_DIR/remotes/$origin" \
376-
"URL: $repo
377-
Pull: refs/heads/$head_points_at:refs/$origin_tracking" &&
379+
git-symbolic-ref HEAD "refs/heads/$head_points_at" &&
378380
case "$use_separate_remote" in
379-
t) git-update-ref HEAD "$head_sha1" ;;
380-
*) git-update-ref "refs/heads/$origin" $(git-rev-parse HEAD) ;;
381+
t) origin_track="$remote_top/$head_points_at"
382+
git-update-ref HEAD "$head_sha1" ;;
383+
*) origin_track="$remote_top/$origin"
384+
git-update-ref "refs/heads/$origin" "$head_sha1" ;;
381385
esac &&
386+
echo >"$GIT_DIR/remotes/$origin" \
387+
"URL: $repo
388+
Pull: refs/heads/$head_points_at:$origin_track" &&
382389
(cd "$GIT_DIR/$remote_top" && find . -type f -print) |
383390
while read dotslref
384391
do
385392
name=`expr "$dotslref" : './\(.*\)'` &&
386-
test "$head_points_at" = "$name" ||
387-
test "$origin" = "$name" ||
393+
test "$use_separate_remote" = '' && {
394+
test "$head_points_at" = "$name" ||
395+
test "$origin" = "$name"
396+
} ||
388397
echo "Pull: refs/heads/${name}:$remote_top/${name}"
389398
done >>"$GIT_DIR/remotes/$origin" &&
390399
case "$use_separate_remote" in

0 commit comments

Comments
 (0)