From: "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: jrnieder@gmail.com, peff@peff.net,
Derrick Stolee <dstolee@microsoft.com>,
Derrick Stolee <dstolee@microsoft.com>
Subject: [PATCH] fetch: add --no-update-remote-refs
Date: Fri, 17 Jan 2020 15:28:59 +0000 [thread overview]
Message-ID: <pull.532.git.1579274939431.gitgitgadget@gmail.com> (raw)
From: Derrick Stolee <dstolee@microsoft.com>
To prevent long blocking time during a 'git fetch' call, a user
may want to set up a schedule for background 'git fetch' processes.
However, these runs will update the refs/remotes branches, and
hence the user will not notice when remote refs are updated during
their foreground fetches. In fact, they may _want_ those refs to
stay put so they can work with the refs from their last foreground
fetch call.
Add a --[no-]update-remote-refs option to 'git fetch' which defaults
to the existing behavior of updating the remote refs. This allows
a user to run
git fetch <remote> --no-update-remote-refs +refs/heads/*:refs/hidden/*
to populate a custom ref space and download a pack of the new
reachable objects. This kind of call allows a few things to happen:
1. We download a new pack if refs have updated.
2. Since the refs/hidden branches exist, GC will not remove the
newly-downloaded data.
3. With fetch.writeCommitGraph enabled, the refs/hidden refs are
used to update the commit-graph file.
To avoid the refs/hidden directory from filling without bound, the
--prune option can be included. When providing a refspec like this,
the --prune option does not delete remote refs and instead only
deletes refs in the target refspace.
Note: with the default refpsec, the --prune option will override
the --no-update-remote-refs option and will delete the refs that
do not exist on the remote.
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
---
fetch: add --no-update-remote-refs
Here is a new feature for git fetch that hopefully is useful to some
users. We've been using a patch like this in microsoft/git for about a
month now, and I've been testing it locally using the custom refspec
mentioned in the commit message. It's quite refreshing to run git fetch
--all in my Git repo and see all the branch updates but not actually
wait for any pack downloads.
There is one question about how --prune and --no-update-remote-refs
should interact. Since --prune is not the default, and it works the way
I'd like with a non-default refspec, I'm currently proposing allowing it
to delete remote refs even if --no-update-remote-refs is provided.
Thanks, -Stolee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-532%2Fderrickstolee%2Ffetch-no-update-remote-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-532/derrickstolee/fetch-no-update-remote-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/532
Documentation/fetch-options.txt | 7 +++++++
builtin/fetch.c | 6 ++++++
t/t5510-fetch.sh | 24 ++++++++++++++++++++++++
3 files changed, 37 insertions(+)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index a2f78624a2..0939642dce 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -254,6 +254,13 @@ endif::git-pull[]
'git-pull' the --ff-only option will still check for forced updates
before attempting a fast-forward update. See linkgit:git-config[1].
+--no-update-remote-refs::
+ By default, git updates the `refs/remotes/` refspace with the refs
+ advertised by the remotes during a `git fetch` command. With this
+ option, those refs will be ignored. If the `--prune` option is
+ specified and the default refpsec is used, then a ref that does not
+ appear in the remote will still be deleted from refs/remotes.
+
-4::
--ipv4::
Use IPv4 addresses only, ignoring IPv6 addresses.
diff --git a/builtin/fetch.c b/builtin/fetch.c
index b4c6d921d0..bf8000adaf 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -78,6 +78,7 @@ static struct list_objects_filter_options filter_options;
static struct string_list server_options = STRING_LIST_INIT_DUP;
static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
static int fetch_write_commit_graph = -1;
+static int update_remote_refs = 1;
static int git_fetch_config(const char *k, const char *v, void *cb)
{
@@ -201,6 +202,8 @@ static struct option builtin_fetch_options[] = {
N_("check for forced-updates on all updated branches")),
OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph,
N_("write the commit-graph after fetching")),
+ OPT_BOOL(0, "update-remote-refs", &update_remote_refs,
+ N_("update the refs/remotes/ refspace")),
OPT_END()
};
@@ -746,6 +749,9 @@ static int update_local_ref(struct ref *ref,
const char *pretty_ref = prettify_refname(ref->name);
int fast_forward = 0;
+ if (!update_remote_refs && starts_with(ref->name, "refs/remotes/"))
+ return 0;
+
type = oid_object_info(the_repository, &ref->new_oid, NULL);
if (type < 0)
die(_("object %s not found"), oid_to_hex(&ref->new_oid));
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 4b60282689..35b50b2047 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -174,6 +174,30 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec'
git rev-parse sometag
'
+test_expect_success 'fetch --no-update-remote-refs keeps existing refs' '
+ cd "$TRASH_DIRECTORY" &&
+ git clone "$D" remote-refs &&
+ git -C remote-refs rev-parse remotes/origin/master >old &&
+ git -C remote-refs update-ref refs/remotes/origin/master master~1 &&
+ git -C remote-refs rev-parse remotes/origin/master >new &&
+ git -C remote-refs fetch --no-update-remote-refs origin &&
+ git -C remote-refs rev-parse remotes/origin/master >actual &&
+ test_cmp new actual &&
+ git -C remote-refs fetch origin &&
+ git -C remote-refs rev-parse remotes/origin/master >actual &&
+ test_cmp old actual
+'
+
+test_expect_success 'fetch --no-update-remote-refs --prune with refspec' '
+ git -C remote-refs update-ref refs/remotes/origin/foo/otherbranch master &&
+ git -C remote-refs update-ref refs/hidden/foo/otherbranch master &&
+ git -C remote-refs fetch --prune --no-update-remote-refs origin +refs/heads/*:refs/hidden/* &&
+ git -C remote-refs rev-parse remotes/origin/foo/otherbranch &&
+ test_must_fail git -C remote-refs rev-parse refs/hidden/foo/otherbranch &&
+ git -C remote-refs fetch --prune --no-update-remote-refs origin &&
+ test_must_fail git -C remote-refs rev-parse remotes/origin/foo/otherbranch
+'
+
test_expect_success 'fetch tags when there is no tags' '
cd "$D" &&
base-commit: d0654dc308b0ba76dd8ed7bbb33c8d8f7aacd783
--
gitgitgadget
next reply other threads:[~2020-01-17 15:29 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-17 15:28 Derrick Stolee via GitGitGadget [this message]
2020-01-17 16:23 ` [PATCH] fetch: add --no-update-remote-refs Eric Sunshine
2020-01-17 19:13 ` Junio C Hamano
2020-01-17 19:26 ` Jeff King
2020-01-20 14:44 ` Derrick Stolee
2020-01-17 19:20 ` Jeff King
2020-01-21 0:57 ` Derrick Stolee
2020-01-21 1:38 ` [PATCH v2] fetch: document and test --refmap="" Derrick Stolee via GitGitGadget
2020-01-21 16:24 ` Jeff King
2020-01-21 18:01 ` Derrick Stolee
2020-01-21 19:06 ` Jeff King
2020-01-21 18:22 ` Junio C Hamano
2020-01-21 18:24 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.532.git.1579274939431.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=dstolee@microsoft.com \
--cc=git@vger.kernel.org \
--cc=jrnieder@gmail.com \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.