fetch: make --prune configurable
Without "git fetch --prune", remote-tracking branches for a branch the other side already has removed will stay forever. Some people want to always run "git fetch --prune". To accommodate users who want to either prune always or when fetching from a particular remote, add two new configuration variables "fetch.prune" and "remote.<name>.prune": - "fetch.prune" allows to enable prune for all fetch operations. - "remote.<name>.prune" allows to change the behaviour per remote. The latter will naturally override the former, and the --[no-]prune option from the command line will override the configured default. Since --prune is a potentially destructive operation (Git doesn't keep reflogs for deleted references yet), we don't want to prune without users consent, so this configuration will not be on by default. Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Michael Schubert <mschub@elegosoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
edca415256
commit
737c5a9cde
@ -1049,6 +1049,10 @@ fetch.unpackLimit::
|
||||
especially on slow filesystems. If not set, the value of
|
||||
`transfer.unpackLimit` is used instead.
|
||||
|
||||
fetch.prune::
|
||||
If true, fetch will automatically behave as if the `--prune`
|
||||
option was given on the command line. See also `remote.<name>.prune`.
|
||||
|
||||
format.attach::
|
||||
Enable multipart/mixed attachments as the default for
|
||||
'format-patch'. The value can also be a double quoted string
|
||||
@ -1984,6 +1988,12 @@ remote.<name>.vcs::
|
||||
Setting this to a value <vcs> will cause Git to interact with
|
||||
the remote with the git-remote-<vcs> helper.
|
||||
|
||||
remote.<name>.prune::
|
||||
When set to true, fetching from this remote by default will also
|
||||
remove any remote-tracking branches which no longer exist on the
|
||||
remote (as if the `--prune` option was give on the command line).
|
||||
Overrides `fetch.prune` settings, if any.
|
||||
|
||||
remotes.<group>::
|
||||
The list of remotes which are fetched by "git remote update
|
||||
<group>". See linkgit:git-remote[1].
|
||||
|
@ -30,7 +30,11 @@ enum {
|
||||
TAGS_SET = 2
|
||||
};
|
||||
|
||||
static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
|
||||
static int fetch_prune_config = -1; /* unspecified */
|
||||
static int prune = -1; /* unspecified */
|
||||
#define PRUNE_BY_DEFAULT 0 /* do we prune by default? */
|
||||
|
||||
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
|
||||
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
|
||||
static int tags = TAGS_DEFAULT, unshallow;
|
||||
static const char *depth;
|
||||
@ -54,6 +58,15 @@ static int option_parse_recurse_submodules(const struct option *opt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_fetch_config(const char *k, const char *v, void *cb)
|
||||
{
|
||||
if (!strcmp(k, "fetch.prune")) {
|
||||
fetch_prune_config = git_config_bool(k, v);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct option builtin_fetch_options[] = {
|
||||
OPT__VERBOSITY(&verbosity),
|
||||
OPT_BOOLEAN(0, "all", &all,
|
||||
@ -69,8 +82,8 @@ static struct option builtin_fetch_options[] = {
|
||||
N_("fetch all tags and associated objects"), TAGS_SET),
|
||||
OPT_SET_INT('n', NULL, &tags,
|
||||
N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
|
||||
OPT_BOOLEAN('p', "prune", &prune,
|
||||
N_("prune remote-tracking branches no longer on remote")),
|
||||
OPT_BOOL('p', "prune", &prune,
|
||||
N_("prune remote-tracking branches no longer on remote")),
|
||||
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
|
||||
N_("control recursive fetching of submodules"),
|
||||
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
|
||||
@ -739,7 +752,10 @@ static int do_fetch(struct transport *transport,
|
||||
return 1;
|
||||
}
|
||||
if (prune) {
|
||||
/* If --tags was specified, pretend the user gave us the canonical tags refspec */
|
||||
/*
|
||||
* If --tags was specified, pretend that the user gave us
|
||||
* the canonical tags refspec
|
||||
*/
|
||||
if (tags == TAGS_SET) {
|
||||
const char *tags_str = "refs/tags/*:refs/tags/*";
|
||||
struct refspec *tags_refspec, *refspec;
|
||||
@ -848,7 +864,7 @@ static void add_options_to_argv(struct argv_array *argv)
|
||||
{
|
||||
if (dry_run)
|
||||
argv_array_push(argv, "--dry-run");
|
||||
if (prune)
|
||||
if (prune > 0)
|
||||
argv_array_push(argv, "--prune");
|
||||
if (update_head_ok)
|
||||
argv_array_push(argv, "--update-head-ok");
|
||||
@ -916,6 +932,17 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
|
||||
"remote name from which new revisions should be fetched."));
|
||||
|
||||
transport = transport_get(remote, NULL);
|
||||
|
||||
if (prune < 0) {
|
||||
/* no command line request */
|
||||
if (0 <= transport->remote->prune)
|
||||
prune = transport->remote->prune;
|
||||
else if (0 <= fetch_prune_config)
|
||||
prune = fetch_prune_config;
|
||||
else
|
||||
prune = PRUNE_BY_DEFAULT;
|
||||
}
|
||||
|
||||
transport_set_verbosity(transport, verbosity, progress);
|
||||
if (upload_pack)
|
||||
set_option(TRANS_OPT_UPLOADPACK, upload_pack);
|
||||
@ -973,6 +1000,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||
for (i = 1; i < argc; i++)
|
||||
strbuf_addf(&default_rla, " %s", argv[i]);
|
||||
|
||||
git_config(git_fetch_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, prefix,
|
||||
builtin_fetch_options, builtin_fetch_usage, 0);
|
||||
|
||||
|
3
remote.c
3
remote.c
@ -148,6 +148,7 @@ static struct remote *make_remote(const char *name, int len)
|
||||
}
|
||||
|
||||
ret = xcalloc(1, sizeof(struct remote));
|
||||
ret->prune = -1; /* unspecified */
|
||||
ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
|
||||
remotes[remotes_nr++] = ret;
|
||||
if (len)
|
||||
@ -419,6 +420,8 @@ static int handle_config(const char *key, const char *value, void *cb)
|
||||
remote->skip_default_update = git_config_bool(key, value);
|
||||
else if (!strcmp(subkey, ".skipfetchall"))
|
||||
remote->skip_default_update = git_config_bool(key, value);
|
||||
else if (!strcmp(subkey, ".prune"))
|
||||
remote->prune = git_config_bool(key, value);
|
||||
else if (!strcmp(subkey, ".url")) {
|
||||
const char *v;
|
||||
if (git_config_string(&v, key, value))
|
||||
|
1
remote.h
1
remote.h
@ -40,6 +40,7 @@ struct remote {
|
||||
int fetch_tags;
|
||||
int skip_default_update;
|
||||
int mirror;
|
||||
int prune;
|
||||
|
||||
const char *receivepack;
|
||||
const char *uploadpack;
|
||||
|
@ -471,6 +471,88 @@ test_expect_success "should be able to fetch with duplicate refspecs" '
|
||||
)
|
||||
'
|
||||
|
||||
# configured prune tests
|
||||
|
||||
set_config_tristate () {
|
||||
# var=$1 val=$2
|
||||
case "$2" in
|
||||
unset) test_unconfig "$1" ;;
|
||||
*) git config "$1" "$2" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
test_configured_prune () {
|
||||
fetch_prune=$1 remote_origin_prune=$2 cmdline=$3 expected=$4
|
||||
|
||||
test_expect_success "prune fetch.prune=$1 remote.origin.prune=$2${3:+ $3}; $4" '
|
||||
# make sure a newbranch is there in . and also in one
|
||||
git branch -f newbranch &&
|
||||
(
|
||||
cd one &&
|
||||
test_unconfig fetch.prune &&
|
||||
test_unconfig remote.origin.prune &&
|
||||
git fetch &&
|
||||
git rev-parse --verify refs/remotes/origin/newbranch
|
||||
)
|
||||
|
||||
# now remove it
|
||||
git branch -d newbranch &&
|
||||
|
||||
# then test
|
||||
(
|
||||
cd one &&
|
||||
set_config_tristate fetch.prune $fetch_prune &&
|
||||
set_config_tristate remote.origin.prune $remote_origin_prune &&
|
||||
|
||||
git fetch $cmdline &&
|
||||
case "$expected" in
|
||||
pruned)
|
||||
test_must_fail git rev-parse --verify refs/remotes/origin/newbranch
|
||||
;;
|
||||
kept)
|
||||
git rev-parse --verify refs/remotes/origin/newbranch
|
||||
;;
|
||||
esac
|
||||
)
|
||||
'
|
||||
}
|
||||
|
||||
test_configured_prune unset unset "" kept
|
||||
test_configured_prune unset unset "--no-prune" kept
|
||||
test_configured_prune unset unset "--prune" pruned
|
||||
|
||||
test_configured_prune false unset "" kept
|
||||
test_configured_prune false unset "--no-prune" kept
|
||||
test_configured_prune false unset "--prune" pruned
|
||||
|
||||
test_configured_prune true unset "" pruned
|
||||
test_configured_prune true unset "--prune" pruned
|
||||
test_configured_prune true unset "--no-prune" kept
|
||||
|
||||
test_configured_prune unset false "" kept
|
||||
test_configured_prune unset false "--no-prune" kept
|
||||
test_configured_prune unset false "--prune" pruned
|
||||
|
||||
test_configured_prune false false "" kept
|
||||
test_configured_prune false false "--no-prune" kept
|
||||
test_configured_prune false false "--prune" pruned
|
||||
|
||||
test_configured_prune true false "" kept
|
||||
test_configured_prune true false "--prune" pruned
|
||||
test_configured_prune true false "--no-prune" kept
|
||||
|
||||
test_configured_prune unset true "" pruned
|
||||
test_configured_prune unset true "--no-prune" kept
|
||||
test_configured_prune unset true "--prune" pruned
|
||||
|
||||
test_configured_prune false true "" pruned
|
||||
test_configured_prune false true "--no-prune" kept
|
||||
test_configured_prune false true "--prune" pruned
|
||||
|
||||
test_configured_prune true true "" pruned
|
||||
test_configured_prune true true "--prune" pruned
|
||||
test_configured_prune true true "--no-prune" kept
|
||||
|
||||
test_expect_success 'all boundary commits are excluded' '
|
||||
test_commit base &&
|
||||
test_commit oneside &&
|
||||
|
Loading…
Reference in New Issue
Block a user