You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tags are auto-followed when no refspec stores anything (git fetch origin main) #7436
git follows tags only when the fetch stores something. get_ref_map enables tag auto-following only if one of the refspecs (given, or configured) has a destination. So git fetch origin main writes FETCH_HEAD and creates no tags, and neither does a fetch of a URL's HEAD.
With the default GIT_REMOTE_DOWNLOAD_TAGS_AUTO, libgit2 follows tags whatever the refspecs are. git_remote_fetch(remote, ["main"], …) creates every tag that points into the fetched history as a local tag.
This is the opposite case from #3870 (tags git follows that libgit2 misses).
Reproduction steps
fetchrepro.c is the program from #7435. With refspec arguments it calls git_remote_fetch(remote, &refspecs, &opts, NULL).
fetchrepro.c
/* * Fetch from "origin" as `git fetch [--prune] origin [<refspec>...]` * would: git_remote_fetch() with the given refspecs, or with NULL (the * remote's configured refspecs) when there are none. * * usage: fetchrepro <repository> [--prune] [<refspec>...] */#include<stdio.h>#include<string.h>#include<git2.h>staticintcheck(interror, constchar*what)
{
if (error<0) {
constgit_error*e=git_error_last();
fprintf(stderr, "%s: %s\n", what, e ? e->message : "unknown error");
return1;
}
return0;
}
intmain(intargc, char**argv)
{
git_repository*repo=NULL;
git_remote*remote=NULL;
git_fetch_optionsopts=GIT_FETCH_OPTIONS_INIT;
git_strarrayrefspecs= { NULL, 0 };
intfirst=2, failed;
if (argc<2) {
fprintf(stderr, "usage: %s <repository> [--prune] [<refspec>...]\n", argv[0]);
return2;
}
if (argc>2&& !strcmp(argv[2], "--prune")) {
opts.prune=GIT_FETCH_PRUNE;
first=3;
}
refspecs.strings=argv+first;
refspecs.count= (size_t)(argc-first);
git_libgit2_init();
failed=check(git_repository_open(&repo, argv[1]), "open") ||check(git_remote_lookup(&remote, repo, "origin"), "lookup") ||check(git_remote_fetch(remote, refspecs.count ? &refspecs : NULL, &opts, NULL), "fetch");
git_remote_free(remote);
git_repository_free(repo);
git_libgit2_shutdown();
returnfailed;
}
#!/bin/sh# Tag auto-following in libgit2: `git fetch origin main` vs# git_remote_fetch(remote, ["main"]) (./fetchrepro) on identical clones.set -e
FETCH=${FETCH:-./fetchrepro}export GIT_CONFIG_GLOBAL=/dev/null GIT_AUTHOR_NAME=a GIT_AUTHOR_EMAIL=a@b \
GIT_COMMITTER_NAME=a GIT_COMMITTER_EMAIL=a@b
rm -rf src git libgit2
git init -q -b main src
git -C src commit -q --allow-empty -m one
git clone -q src git
git clone -q src libgit2
git -C src commit -q --allow-empty -m two
git -C src tag v1 # points at the commit being fetched
git -C git fetch -q origin main # FETCH_HEAD only: no refspec stores anything$FETCH libgit2 main
forrin git libgit2;doecho"--- $r: tags"
git -C $r tag -l
done
Expected behavior
As with git 2.54, no tags are created: the fetch only updates FETCH_HEAD.
Actual behavior
--- git: tags
--- libgit2: tags
v1
libgit2 creates refs/tags/v1.
Version of libgit2 (release number or SHA1)
v1.9.4. The tag handling (update_one_tip's autotag path, download_tags) is unchanged in v1.9.7 and on main (42a89d7).
Operating system(s) tested
macOS 27 (arm64)
For reference, GitKit works around this (Cocoanetics/GitKit#46). When the remote's tag mode is AUTO and none of the fetch's refspecs (given, or else configured) has a destination, it sets download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE. A remote with tagOpt = --tags keeps fetching all tags, as in git.
Activity
Merge feat/refspec-sets; refused lines show the source as typed