Updates. I seem to have a reliable reproduction script, for this issue. After rebuilding your git with the following patch, running the test script ./t000.sh would exhibit that "no common refs" while following the tag. Then rebuild your git with "#if 0" part enabled, and run the test again, to see the problem fixed. This adds --autofollow option which is _purely_ for debugging this issue. The command named by the option is executed after the command finishes the main transfer but before it starts the second transfer to auto follow the tags. The test prepares two repositories (src0.git and src1.git) to simulate DNS round robin server side. src0.git grows, src1.git mirrors it with a bit of lag. src.git is a symlink that is used to simulate DNS round robin. Initially it points at src0.git (more up-to-date one) and a clone to Len (dst.git) is made. After src0.git grows history while src1.git mirrors it with a lag, Len fetches again, first from src0.git but autofollowing connection goes to src1.git. While I was futzing with the test script, I also observed another error message "fatal: not our ref", but that was before I fixed the commit traversal order by giving them the test_tick timestamps. It won't reproduce with the attached test script, but the patch also seemed to fix it. --- builtin-fetch.c | 12 +++++++ t000.sh | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 0 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index ac335f2..79359ac 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -28,6 +28,7 @@ static const char *depth; static const char *upload_pack; static struct strbuf default_rla = STRBUF_INIT; static struct transport *transport; +static char *autofollow; static struct option builtin_fetch_options[] = { OPT__QUIET(&quiet), @@ -45,6 +46,8 @@ static struct option builtin_fetch_options[] = { "allow updating of HEAD ref"), OPT_STRING(0, "depth", &depth, "DEPTH", "deepen history of shallow clone"), + OPT_STRING(0, "autofollow", &autofollow, "COMMAND", + "call the command just before autofollowing"), OPT_END() }; @@ -547,6 +550,15 @@ static int do_fetch(struct transport *transport, /* if neither --no-tags nor --tags was specified, do automated tag * following ... */ if (tags == TAGS_DEFAULT && autotags) { + if (autofollow) + system(autofollow); +#if 0 + if (transport->remote_refs) { + struct ref *stale = (struct ref *)transport->remote_refs; + free_refs(stale); + transport->remote_refs = NULL; + } +#endif ref_map = find_non_local_tags(transport, fetch_map); if (ref_map) { transport_set_option(transport, TRANS_OPT_DEPTH, "0"); diff --git a/t000.sh b/t000.sh new file mode 100644 index 0000000..e2c35d1 --- /dev/null +++ b/t000.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +GIT_EXEC_PATH=`pwd` +PATH=`pwd`:/usr/bin:/bin +GITPERLLIB=`pwd`/perl/blib/lib +export GIT_EXEC_PATH PATH GITPERLLIB + +testdir=/var/tmp/fetch-test +mkdir -p "$testdir" + +cd "$testdir" || exit +test_tick=1112911993 + +grow () { + j_bottom="$1" j_top="$2" i_top="$3" tagit="$4" + j="$j_bottom" + while test "$j" -le "$j_top" + do + i=1 + while test "$i" -le "$i_top" + do + echo "$j.$i" >f + git add f + test_tick=$(($test_tick + 60)) + GIT_COMMITTER_DATE="$test_tick -0700" \ + git commit -q -m "$j.$i" + i=$(($i + 1)) + done + if test -n "$tagit" + then + git tag -a -m "Tag $j" v$j + fi + j=$(($j + 1)) + done +} + +rm -fr src0.git src1.git dst.git + +# Prepare the very original. Pretend this is Linus +mkdir src0.git +cd src0.git +git init +grow 1 5 4 1 +cd .. + +# Prepare a "mirror" that slightly lags behind. +mkdir src1.git +cd src1.git +GIT_DIR=. git init +git remote add -f --mirror origin ../src0.git/ +cd .. + +# Prepare canonical symlink +rm -f src.git && ln -s src0.git src.git + +# Len clones and works +git clone file://$testdir/src.git/ dst.git +cd dst.git +grow 1 1 200 +cd .. + +# Linus works more. +cd src0.git +grow 6 7 4 1 +cd .. + +# Mirror it out +cd src1.git +git fetch +cd .. + +# Linus works further. +cd src0.git +grow 8 8 1 +cd .. + +# Prepare "switch" script +echo >auto-switch.sh '#!/bin/sh +cd "'$testdir'" +case "$(ls -l src.git)" in +*src0.git*) new=src1.git ;; +*src1.git*) new=src0.git ;; +esac +echo "Auto switching to $new" +rm -f src.git && ln -s "$new" src.git' +chmod +x auto-switch.sh + +# Now Len fetches; the first goes to src0 (up-to-date one) but +# the autofollow goes to src1 (more stale one) + +rm -f src.git && ln -s src0.git src.git + +cd dst.git +git-fetch -v --autofollow="$testdir/auto-switch.sh" + - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html