checkout: --track=fetch#2281
Conversation
9ed416b to
e2fa50f
Compare
|
/submit |
|
Submitted as pull.2281.git.git.1777024991531.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
|
Ramsay Jones wrote on the Git mailing list (how to reply to this email): On 24/04/2026 11:03 am, Harald Nordgren via GitGitGadget wrote:
> From: Harald Nordgren <haraldnordgren@gmail.com>
>
> Add a --fetch option to git checkout and git switch, plus a
> checkout.autoFetch config to enable it by default. When set and the
> start-point argument names a configured remote (either bare, like
> "origin", or prefixed, like "origin/foo"), fetch that remote before
> resolving the ref. Aborts the checkout if the fetch fails.
>
> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
> ---
[snip]
>
> diff --git a/t/t7201-co.sh b/t/t7201-co.sh
> index 9bcf7c0b40..60ddebd9c3 100755
> --- a/t/t7201-co.sh
> +++ b/t/t7201-co.sh
> @@ -801,4 +801,55 @@ test_expect_success 'tracking info copied with autoSetupMerge=inherit' '
> test_cmp_config "" --default "" branch.main2.merge
> '
>
> +test_expect_success 'setup upstream for --fetch tests' '
> + git checkout main &&
> + git init fetch_upstream &&
> + test_commit -C fetch_upstream u_main &&
> + git remote add fetch_upstream fetch_upstream &&
> + git fetch fetch_upstream &&
> + git -C fetch_upstream checkout -b fetch_new &&
> + test_commit -C fetch_upstream u_new
> +'
> +
> +test_expect_success 'checkout --fetch -b picks up branch created upstream after clone' '
> + git checkout main &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_new &&
> + git checkout --fetch -b local_new fetch_upstream/fetch_new &&
> + test_cmp_rev refs/remotes/fetch_upstream/fetch_new HEAD
> +'
> +
> +test_expect_success 'checkout --fetch with bare remote name fetches the remote' '
> + git checkout main &&
> + git -C fetch_upstream checkout -b fetch_new2 &&
> + test_commit -C fetch_upstream u_new2 &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_new2 &&
> + git checkout --fetch -b local_from_remote fetch_upstream &&
> + git rev-parse --verify refs/remotes/fetch_upstream/fetch_new2
> +'
> +
> +test_expect_success 'checkout --fetch aborts and does not create branch on fetch failure' '
> + git checkout main &&
> + test_might_fail git branch -D bogus &&
> + test_must_fail git checkout --fetch -b bogus fetch_upstream/does_not_exist &&
> + test_must_fail git rev-parse --verify refs/heads/bogus
> +'
> +
> +test_expect_success 'checkout.autoFetch=true enables fetching without --fetch' '
> + git checkout main &&
> + git -C fetch_upstream checkout -b fetch_cfg &&
> + test_commit -C fetch_upstream u_cfg &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_cfg &&
> + git -c checkout.autoFetch=true checkout -b local_cfg fetch_upstream/fetch_cfg &&
> + test_cmp_rev refs/remotes/fetch_upstream/fetch_cfg HEAD
> +'
> +
> +test_expect_success 'switch --fetch -c picks up branch created upstream after clone' '
> + git checkout main &&
> + git -C fetch_upstream checkout -b fetch_switch &&
> + test_commit -C fetch_upstream u_switch &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_switch &&
> + git switch --fetch -c local_switch fetch_upstream/fetch_switch &&
> + test_cmp_rev refs/remotes/fetch_upstream/fetch_switch HEAD
> +'
> +
I was just skimming the list (so if this is not appropriate, please just ignore) and,
although I think '--no-fetch' will probably countermand the autoFetch config, I do not
see a test that confirms it.
Thanks.
ATB,
Ramsay Jones
|
|
User |
|
"D. Ben Knoble" wrote on the Git mailing list (how to reply to this email): On Fri, Apr 24, 2026 at 6:08 AM Harald Nordgren via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> From: Harald Nordgren <haraldnordgren@gmail.com>
>
> Add a --fetch option to git checkout and git switch, plus a
> checkout.autoFetch config to enable it by default. When set and the
> start-point argument names a configured remote (either bare, like
> "origin", or prefixed, like "origin/foo"), fetch that remote before
> resolving the ref. Aborts the checkout if the fetch fails.
>
> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
> ---
> checkout: add --fetch to fetch remote before resolving start-point
>
> A workflow I run several times a day looks like:
>
> git fetch origin
> git checkout -b new_branch origin/some-branch
>
>
> The first command exists purely to make the second one see an up-to-date
> view of the remote. If I forget it, origin/some-branch points at a stale
> commit, and I end up creating a local branch from the wrong starting
> point.
When you realize this, "git pull --rebase" should help correct it.
>
> This series teaches git checkout (and git switch) a new --fetch flag
> that folds the two steps into one:
>
> git checkout --fetch -b new_branch origin/some-branch
>
>
> When the start-point argument names a configured remote — either bare
> (origin, which resolves to the remote's default branch) or in / form —
> git fetch is run before the start-point is resolved. If the fetch fails,
> the checkout aborts and no local branch is created.
>
> A new checkout.autoFetch config option enables the same behavior by
> default, for users who always want it.
I could certainly see this being convenient. (I don't have any comment
on the code at this time.) |
|
User |
|
"Kristoffer Haugsbakk" wrote on the Git mailing list (how to reply to this email): On Fri, Apr 24, 2026, at 12:03, Harald Nordgren via GitGitGadget wrote:
> From: Harald Nordgren <haraldnordgren@gmail.com>
>
> Add a --fetch option to git checkout and git switch, plus a
> checkout.autoFetch config to enable it by default. When set and the
Why is the config not `checkout.config`? So it’s named the same as the
option (modulo snake case/camel case which is not relevant here).
> start-point argument names a configured remote (either bare, like
> "origin", or prefixed, like "origin/foo"),
It’s great that it only fetches when you have a remote-tracking branch
or alias for `<remote>/HEAD`. Doing a fetch on every <start-point> would
have been bad.
> fetch that remote before
> resolving the ref. Aborts the checkout if the fetch fails.
>
> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
> ---
> checkout: add --fetch to fetch remote before resolving start-point
>
> A workflow I run several times a day looks like:
>
> git fetch origin
> git checkout -b new_branch origin/some-branch
>
>
> The first command exists purely to make the second one see an up-to-date
> view of the remote. If I forget it, origin/some-branch points at a stale
> commit, and I end up creating a local branch from the wrong starting
> point.
>
> This series teaches git checkout (and git switch) a new --fetch flag
> that folds the two steps into one:
>
> git checkout --fetch -b new_branch origin/some-branch
The motivation for why this is being proposed maybe might as well go in
the commit message. Maybe that’s just me.
The commit message just says that “this thing is added”. Not why.
>
>
> When the start-point argument names a configured remote — either bare
> (origin, which resolves to the remote's default branch) or in / form —
> git fetch is run before the start-point is resolved. If the fetch fails,
> the checkout aborts and no local branch is created.
>
> A new checkout.autoFetch config option enables the same behavior by
> default, for users who always want it.
>
> Published-As:
> https://github.com/gitgitgadget/git/releases/tag/pr-git-2281%2FHaraldNordgren%2Fcheckout-fetch-start-point-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git
> pr-git-2281/HaraldNordgren/checkout-fetch-start-point-v1
> Pull-Request: https://github.com/git/git/pull/2281
>
> builtin/checkout.c | 48 ++++++++++++++++++++++++++++++++++++++--
> t/t7201-co.sh | 51 +++++++++++++++++++++++++++++++++++++++++++
> t/t9902-completion.sh | 1 +
> 3 files changed, 98 insertions(+), 2 deletions(-)
I guess a later version will have the changes to the documentation.
>
> diff --git a/builtin/checkout.c b/builtin/checkout.c
>[snip]
> argv += n;
> argc -= n;
> } else if (!opts->accept_ref && opts->from_treeish) {
> @@ -2052,6 +2092,8 @@ int cmd_checkout(int argc,
> OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode
> (default)")),
> OPT_BOOL(0, "auto-advance", &opts.auto_advance,
> N_("auto advance to the next file when selecting hunks
> interactively")),
> + OPT_BOOL(0, "fetch", &opts.auto_fetch,
> + N_("fetch from the remote first if <start-point> is a remote-tracking ref")),
s/remote-tracking ref/remote-tracking branch/ ?
git(1) doesn’t have a namespace for tracking refs in general.
> OPT_END()
> };
>
> @@ -2102,6 +2144,8 @@ int cmd_switch(int argc,
> N_("second guess 'git switch <no-such-branch>'")),
> OPT_BOOL(0, "discard-changes", &opts.discard_changes,
> N_("throw away local modifications")),
> + OPT_BOOL(0, "fetch", &opts.auto_fetch,
> + N_("fetch from the remote first if <start-point> is a remote-tracking ref")),
Ditto.
> OPT_END()
> };
>[snip] |
|
User |
|
Marc Branchaud wrote on the Git mailing list (how to reply to this email): On 2026-04-24 04:03, Harald Nordgren via GitGitGadget wrote:
> From: Harald Nordgren <haraldnordgren@gmail.com>
> > Add a --fetch option to git checkout and git switch, plus a
> checkout.autoFetch config to enable it by default. When set and the
> start-point argument names a configured remote (either bare, like
> "origin", or prefixed, like "origin/foo"), fetch that remote before
> resolving the ref. Aborts the checkout if the fetch fails.
Why tie the behaviour to the nature of the start-point? That seems over-designed and prone to tripping people up. Are you trying to cater to users who have multiple remotes?
I can imagine people who just want to do a checkout of anything after fetching -- maybe they want to checkout a new tag, or some other detached HEAD, or just an already-existing local branch. They see that checkout has this nifty --fetch option so they think they can combine
git fetch; git checkout
into a single command ... but no, only if they checkout something in a remote's namespace.
I don't personally feel the need for this new option, but I think you'll have a much easier time implementing and maintaining it if you just make --fetch do a plain fetch without caring about what the starting-point is.
M.
> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
> ---
> checkout: add --fetch to fetch remote before resolving start-point
> > A workflow I run several times a day looks like:
> > git fetch origin
> git checkout -b new_branch origin/some-branch
> > > The first command exists purely to make the second one see an up-to-date
> view of the remote. If I forget it, origin/some-branch points at a stale
> commit, and I end up creating a local branch from the wrong starting
> point.
> > This series teaches git checkout (and git switch) a new --fetch flag
> that folds the two steps into one:
> > git checkout --fetch -b new_branch origin/some-branch
> > > When the start-point argument names a configured remote — either bare
> (origin, which resolves to the remote's default branch) or in / form —
> git fetch is run before the start-point is resolved. If the fetch fails,
> the checkout aborts and no local branch is created.
> > A new checkout.autoFetch config option enables the same behavior by
> default, for users who always want it.
> > Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2281%2FHaraldNordgren%2Fcheckout-fetch-start-point-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2281/HaraldNordgren/checkout-fetch-start-point-v1
> Pull-Request: https://github.com/git/git/pull/2281
> > builtin/checkout.c | 48 ++++++++++++++++++++++++++++++++++++++--
> t/t7201-co.sh | 51 +++++++++++++++++++++++++++++++++++++++++++
> t/t9902-completion.sh | 1 +
> 3 files changed, 98 insertions(+), 2 deletions(-)
> > diff --git a/builtin/checkout.c b/builtin/checkout.c
> index e031e61886..c8fbc4923b 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -30,7 +30,9 @@
> #include "repo-settings.h"
> #include "resolve-undo.h"
> #include "revision.h"
> +#include "run-command.h"
> #include "setup.h"
> +#include "strvec.h"
> #include "submodule.h"
> #include "symlinks.h"
> #include "trace2.h"
> @@ -61,6 +63,7 @@ struct checkout_opts {
> int count_checkout_paths;
> int overlay_mode;
> int dwim_new_local_branch;
> + int auto_fetch;
> int discard_changes;
> int accept_ref;
> int accept_pathspec;
> @@ -112,6 +115,34 @@ struct branch_info {
> char *checkout;
> };
> > +static void fetch_remote_for_start_point(const char *arg)
> +{
> + const char *slash;
> + char *remote_name;
> + struct remote *remote;
> + struct child_process cmd = CHILD_PROCESS_INIT;
> +
> + if (!arg || !*arg)
> + return;
> +
> + slash = strchr(arg, '/');
> + if (slash == arg)
> + return;
> + remote_name = slash ? xstrndup(arg, slash - arg) : xstrdup(arg);
> +
> + remote = remote_get(remote_name);
> + if (!remote || !remote_is_configured(remote, 1)) {
> + free(remote_name);
> + return;
> + }
> +
> + strvec_pushl(&cmd.args, "fetch", remote_name, NULL);
> + cmd.git_cmd = 1;
> + free(remote_name);
> + if (run_command(&cmd))
> + die(_("failed to fetch start-point '%s'"), arg);
> +}
> +
> static void branch_info_release(struct branch_info *info)
> {
> free(info->name);
> @@ -1237,6 +1268,10 @@ static int git_checkout_config(const char *var, const char *value,
> opts->dwim_new_local_branch = git_config_bool(var, value);
> return 0;
> }
> + if (!strcmp(var, "checkout.autofetch")) {
> + opts->auto_fetch = git_config_bool(var, value);
> + return 0;
> + }
> > if (starts_with(var, "submodule."))
> return git_default_submodule_config(var, value, NULL);
> @@ -1942,8 +1977,13 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
> opts->dwim_new_local_branch &&
> opts->track == BRANCH_TRACK_UNSPECIFIED &&
> !opts->new_branch;
> - int n = parse_branchname_arg(argc, argv, dwim_ok, which_command,
> - &new_branch_info, opts, &rev);
> + int n;
> +
> + if (opts->auto_fetch)
> + fetch_remote_for_start_point(argv[0]);
> +
> + n = parse_branchname_arg(argc, argv, dwim_ok, which_command,
> + &new_branch_info, opts, &rev);
> argv += n;
> argc -= n;
> } else if (!opts->accept_ref && opts->from_treeish) {
> @@ -2052,6 +2092,8 @@ int cmd_checkout(int argc,
> OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode (default)")),
> OPT_BOOL(0, "auto-advance", &opts.auto_advance,
> N_("auto advance to the next file when selecting hunks interactively")),
> + OPT_BOOL(0, "fetch", &opts.auto_fetch,
> + N_("fetch from the remote first if <start-point> is a remote-tracking ref")),
> OPT_END()
> };
> > @@ -2102,6 +2144,8 @@ int cmd_switch(int argc,
> N_("second guess 'git switch <no-such-branch>'")),
> OPT_BOOL(0, "discard-changes", &opts.discard_changes,
> N_("throw away local modifications")),
> + OPT_BOOL(0, "fetch", &opts.auto_fetch,
> + N_("fetch from the remote first if <start-point> is a remote-tracking ref")),
> OPT_END()
> };
> > diff --git a/t/t7201-co.sh b/t/t7201-co.sh
> index 9bcf7c0b40..60ddebd9c3 100755
> --- a/t/t7201-co.sh
> +++ b/t/t7201-co.sh
> @@ -801,4 +801,55 @@ test_expect_success 'tracking info copied with autoSetupMerge=inherit' '
> test_cmp_config "" --default "" branch.main2.merge
> '
> > +test_expect_success 'setup upstream for --fetch tests' '
> + git checkout main &&
> + git init fetch_upstream &&
> + test_commit -C fetch_upstream u_main &&
> + git remote add fetch_upstream fetch_upstream &&
> + git fetch fetch_upstream &&
> + git -C fetch_upstream checkout -b fetch_new &&
> + test_commit -C fetch_upstream u_new
> +'
> +
> +test_expect_success 'checkout --fetch -b picks up branch created upstream after clone' '
> + git checkout main &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_new &&
> + git checkout --fetch -b local_new fetch_upstream/fetch_new &&
> + test_cmp_rev refs/remotes/fetch_upstream/fetch_new HEAD
> +'
> +
> +test_expect_success 'checkout --fetch with bare remote name fetches the remote' '
> + git checkout main &&
> + git -C fetch_upstream checkout -b fetch_new2 &&
> + test_commit -C fetch_upstream u_new2 &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_new2 &&
> + git checkout --fetch -b local_from_remote fetch_upstream &&
> + git rev-parse --verify refs/remotes/fetch_upstream/fetch_new2
> +'
> +
> +test_expect_success 'checkout --fetch aborts and does not create branch on fetch failure' '
> + git checkout main &&
> + test_might_fail git branch -D bogus &&
> + test_must_fail git checkout --fetch -b bogus fetch_upstream/does_not_exist &&
> + test_must_fail git rev-parse --verify refs/heads/bogus
> +'
> +
> +test_expect_success 'checkout.autoFetch=true enables fetching without --fetch' '
> + git checkout main &&
> + git -C fetch_upstream checkout -b fetch_cfg &&
> + test_commit -C fetch_upstream u_cfg &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_cfg &&
> + git -c checkout.autoFetch=true checkout -b local_cfg fetch_upstream/fetch_cfg &&
> + test_cmp_rev refs/remotes/fetch_upstream/fetch_cfg HEAD
> +'
> +
> +test_expect_success 'switch --fetch -c picks up branch created upstream after clone' '
> + git checkout main &&
> + git -C fetch_upstream checkout -b fetch_switch &&
> + test_commit -C fetch_upstream u_switch &&
> + test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_switch &&
> + git switch --fetch -c local_switch fetch_upstream/fetch_switch &&
> + test_cmp_rev refs/remotes/fetch_upstream/fetch_switch HEAD
> +'
> +
> test_done
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 2f9a597ec7..dc1d63669f 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2602,6 +2602,7 @@ test_expect_success 'double dash "git checkout"' '
> --ignore-other-worktrees Z
> --recurse-submodules Z
> --auto-advance Z
> + --fetch Z
> --progress Z
> --guess Z
> --no-guess Z
> > base-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0 |
|
User |
|
Junio C Hamano wrote on the Git mailing list (how to reply to this email): "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Harald Nordgren <haraldnordgren@gmail.com>
>
> Add a --fetch option to git checkout and git switch, plus a
> checkout.autoFetch config to enable it by default. When set and the
> start-point argument names a configured remote (either bare, like
> "origin", or prefixed, like "origin/foo"), fetch that remote before
> resolving the ref. Aborts the checkout if the fetch fails.
>
> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
> ---
It is true that "checkout" does funny things to special case the
remote-tracking branches, like setting up the branch.<name>.merge
configuration or even inferring the name of the local branch to be
created.
But I have to say that this one, especially the configuration
variable, goes way too far. The usual uses of remote-tracking
branch names, e.g.,
git log -1 origin/master
git grep frotz origin/master
git rev-list --count origin/maint..origin/master
to name a specific object all assume and rely on the stability of
them. Should the configuration cause a fetch to happen before any
of these uses of remote-tracking branches for consistency? |
|
Junio C Hamano wrote on the Git mailing list (how to reply to this email): Junio C Hamano <gitster@pobox.com> writes:
> "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> From: Harald Nordgren <haraldnordgren@gmail.com>
>>
>> Add a --fetch option to git checkout and git switch, plus a
>> checkout.autoFetch config to enable it by default. When set and the
>> start-point argument names a configured remote (either bare, like
>> "origin", or prefixed, like "origin/foo"), fetch that remote before
>> resolving the ref. Aborts the checkout if the fetch fails.
>>
>> Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
>> ---
>
> It is true that "checkout" does funny things to special case the
> remote-tracking branches, like setting up the branch.<name>.merge
> configuration or even inferring the name of the local branch to be
> created.
> ...
> ... Should the configuration cause a fetch to happen before any
> of these uses of remote-tracking branches for consistency?
The last one was a rhetorical question. I do not want to see such a
configuration variable to implicitly trigger fetching at all.
I am somewhat sympathetic to the desire "I want to be sure that I
start the new branch in a state as fresh as possible". It is tied
to the "--track" option of "git checkout -b topic --track
origin/main". If you are merely starting at a single arbitrary
commit, instead of anticipating to having to repeatedly sync with
the remote-tracking branch that will subsequently move, there is no
point jumping to a "freshest" commit that you haven't even seen let
alone inspected (i.e., you do not even know if it is a good base to
build on).
So instead of introducing a totally new option that can only be used
only when "--track" is given, it might make more sense to introduce
this as a variant of "--track", perhaps "--track=fetch,[in]direct"
or something like that. And extend branch.autosetup{Merge,Rebase}
that controls what happens when a branch is created with "checkout
-t -b" or "branch --track" so that the remote-tracking branch gets
updated, perhaps.
As to "git checkout origin/main" (nothing else on the command line),
it has "magic" compared to "git checkout origin/main~0" already by
treating the parameter not just as a SHA-1 expression that names a
commit object but as a remote-tracking branch (this is necessary for
"-t"). So I am not fundamentally opposed to the idea to give an
option to treat that form specifically.
Having said all that, quite honestly, I prefer not to see any of the
above changes, including the original patch. It leaves too many
usability questions unaddressed. For a starter, if you interact
with a repository with two or more branches, should
$ git checkout --track=fetch -b topic origin/main
update an unrelated remote-tracking branch origin/maint from the
same remote? As I already said, most Git tools _depend_ on the
stability of remote-tracking branches---the desire to update the
origin/main when a new branch that builds on origin/main is created
may be a valid one, but it is unclear if that warrants updating
other remote-tracking branches only because they come from the same
remote repository. There may be a dozen other UI/usability issues
that will be introduced if we start to "fetch from remote"
automatically, but I won't even try to be exhaustive while I am
still on a leave ;-)
|
1e61ed1 to
13074c9
Compare
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): > When you realize this, "git pull --rebase" should help correct it.
Sure. I always run with
```
git config --global pull.rebase=true
```
I love rebasing and recomdend it to all colleagues that will listen, but
it still sucks to expose yourself to a possible merge conflict when you
realize you worked hours on top of a stale main branch.
> I could certainly see this being convenient.
🙌🏻
Harald |
|
/submit |
|
Submitted as pull.2281.v2.git.git.1777140755373.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): > > Add a --fetch option to git checkout and git switch, plus a
> > checkout.autoFetch config to enable it by default. When set and the
>
> Why is the config not `checkout.config`? So it’s named the same as the
> option (modulo snake case/camel case which is not relevant here).
Will rename the config to 'checkout.fetch'.
> The motivation for why this is being proposed maybe might as well go in
> the commit message. Maybe that’s just me.
>
> The commit message just says that “this thing is added”. Not why.
I will update it.
> I guess a later version will have the changes to the documentation.
I forgot that, will add it!
> s/remote-tracking ref/remote-tracking branch/ ?
>
> git(1) doesn’t have a namespace for tracking refs in general.
👍
Harald |
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): I know you are not Ben. Forgot to change the subject line from a previous message.
Harald |
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): I know you are not Ben. Forgot to change the subject line from a previous message.
Harald |
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): I know you are not Ben. Forgot to change the subject line from a previous message.
Harald |
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): > The last one was a rhetorical question. I do not want to see such a
> configuration variable to implicitly trigger fetching at all.
🤣
Good to clarify that when working with me so that I don't go ahead and
implement that!
> If you are merely starting at a single arbitrary
> commit, instead of anticipating to having to repeatedly sync with
> the remote-tracking branch that will subsequently move, there is no
> point jumping to a "freshest" commit that you haven't even seen let
> alone inspected (i.e., you do not even know if it is a good base to
> build on).
Not sure I understand this sentiment. For better or worse, the latest
commit will decide what you have to work with -- unless we expect it to be
reverted or forced pushed over.
What better starting point is there?
> For a starter, if you interact
> with a repository with two or more branches, should
>
> $ git checkout --track=fetch -b topic origin/main
>
> update an unrelated remote-tracking branch origin/maint from the
> same remote? As I already said, most Git tools _depend_ on the
> stability of remote-tracking branches
This is an interesting question, and it's very likely that I am missing
some nuance here. However, with that said what option does the developer
have, you have to accept that the upstream changes constantly when others
are working on it. What good does it do to keep the "head in the sand" any
longer than necessary?
I'm not sure there is a way to fetch only 'origin/main' and avoid
'origin/maint'? Maybe, maybe, if that exists it could be useful here.
> still on a leave
Enjoy your vacation! I don't expect any response from you until you're back!
Harald |
|
Ben Knoble wrote on the Git mailing list (how to reply to this email): > Le 25 avr. 2026 à 13:58, Harald Nordgren <haraldnordgren@gmail.com> a écrit :
>
>
>>
>> The last one was a rhetorical question. I do not want to see such a
>> configuration variable to implicitly trigger fetching at all.
>
> 🤣
>
> Good to clarify that when working with me so that I don't go ahead and
> implement that!
>
>> If you are merely starting at a single arbitrary
>> commit, instead of anticipating to having to repeatedly sync with
>> the remote-tracking branch that will subsequently move, there is no
>> point jumping to a "freshest" commit that you haven't even seen let
>> alone inspected (i.e., you do not even know if it is a good base to
>> build on).
>
> Not sure I understand this sentiment. For better or worse, the latest
> commit will decide what you have to work with -- unless we expect it to be
> reverted or forced pushed over.
>
> What better starting point is there?
>
>> For a starter, if you interact
>> with a repository with two or more branches, should
>>
>> $ git checkout --track=fetch -b topic origin/main
>>
>> update an unrelated remote-tracking branch origin/maint from the
>> same remote? As I already said, most Git tools _depend_ on the
>> stability of remote-tracking branches
>
> This is an interesting question, and it's very likely that I am missing
> some nuance here. However, with that said what option does the developer
> have, you have to accept that the upstream changes constantly when others
> are working on it. What good does it do to keep the "head in the sand" any
> longer than necessary?
>
> I'm not sure there is a way to fetch only 'origin/main' and avoid
> 'origin/maint'? Maybe, maybe, if that exists it could be useful here.
Isn’t that exactly what
git fetch origin main
does? (Might need to expand the refspec.)
>
>> still on a leave
>
> Enjoy your vacation! I don't expect any response from you until you're back!
>
>
> Harald
> |
13074c9 to
df7b638
Compare
c7a106a to
4b88748
Compare
|
This patch series was integrated into seen via 068b6c7. |
|
This patch series was integrated into seen via a516f69. |
a5f2e8f to
bcd034d
Compare
|
/submit |
|
Submitted as pull.2281.v12.git.git.1779358803652.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
bcd034d to
413230c
Compare
The remote-lookup that setup_tracking() does is useful outside branch.c too; for example, deciding which remote to "git fetch" from given a remote-tracking ref. Move 'struct tracking' to branch.h and add two helpers backed by the existing for_each_remote walk: find_tracking_remote_for_ref() and advise_ambiguous_fetch_refspec(). setup_tracking() uses both. No behavior change. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Add a "fetch" mode to the "--track" option of "git checkout" / "git
switch" that refreshes <start-point> before checking it out:
git checkout -b new_branch --track=fetch origin/some-branch
is shorthand for
git fetch origin some-branch
git checkout -b new_branch --track origin/some-branch
Identify the remote whose configured fetch refspec maps to
<start-point> using find_tracking_remote_for_ref() (the same lookup
"--track" uses to pick which remote to record in
branch.<name>.remote), then run "git fetch <remote> <src-ref>" for
just that ref so other remote-tracking branches are left untouched.
When <start-point> is a bare <remote> (e.g. "origin"), follow
refs/remotes/<remote>/HEAD to learn which branch to refresh. If
"git fetch" fails but the remote-tracking ref already exists locally,
warn and proceed from the existing tip; otherwise abort.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
413230c to
60adf0e
Compare
|
Phillip Wood wrote on the Git mailing list (how to reply to this email): On 19/05/2026 11:34, Junio C Hamano wrote:
> "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> >> checkout: --track=fetch
>> >> * Find the right remote by checking which remote's fetch refspec maps
>> to the user's start-point, instead of assuming the start-point begins
>> with the remote's name. This fixes cases where the user has a custom
>> refspec mapping into a namespace whose name differs from the remote
>> (e.g. fetching from origin into refs/remotes/upstream/*).
> > This comment is even before looking at the patch text. After
> getting one issue pointed out, I'd expect you to think about related
> issues before sending a new round out.
> > One. Have you considered the case where the remote-tracking refs
> are overlapping, e.g., where "origin" and "upstream" point at
> different URLs but they both store in "refs/remotes/upstream/*"?
> Perhaps their URLs may textually be different but are pointing
> logically at the same place (e.g., one ssh:// the other https:// for
> example).
> > What should happen? What does happen after you apply this patch?
It would be worth looking at what "git checkout --track" does in that case and seeing if we can share the code.
Thanks
Phillip
> >> * For a bare namespace name, follow <namespace>/HEAD first to figure
>> out which branch to fetch.
> > What should happen if HEAD does not exist? What does happen after
> you apply this patch?
> > Thanks.
> |
|
Harald Nordgren wrote on the Git mailing list (how to reply to this email): Interesting idea! I will think about it.
Harald
On Thu, May 21, 2026 at 11:49 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> On 19/05/2026 11:34, Junio C Hamano wrote:
> > "Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> >
> >> checkout: --track=fetch
> >>
> >> * Find the right remote by checking which remote's fetch refspec maps
> >> to the user's start-point, instead of assuming the start-point begins
> >> with the remote's name. This fixes cases where the user has a custom
> >> refspec mapping into a namespace whose name differs from the remote
> >> (e.g. fetching from origin into refs/remotes/upstream/*).
> >
> > This comment is even before looking at the patch text. After
> > getting one issue pointed out, I'd expect you to think about related
> > issues before sending a new round out.
> >
> > One. Have you considered the case where the remote-tracking refs
> > are overlapping, e.g., where "origin" and "upstream" point at
> > different URLs but they both store in "refs/remotes/upstream/*"?
> > Perhaps their URLs may textually be different but are pointing
> > logically at the same place (e.g., one ssh:// the other https:// for
> > example).
> >
> > What should happen? What does happen after you apply this patch?
>
> It would be worth looking at what "git checkout --track" does in that
> case and seeing if we can share the code.
>
> Thanks
>
> Phillip
>
> >
> >> * For a bare namespace name, follow <namespace>/HEAD first to figure
> >> out which branch to fetch.
> >
> > What should happen if HEAD does not exist? What does happen after
> > you apply this patch?
> >
> > Thanks.
> >
> |
|
Junio C Hamano wrote on the Git mailing list (how to reply to this email): Phillip Wood <phillip.wood123@gmail.com> writes:
>> One. Have you considered the case where the remote-tracking refs
>> are overlapping, e.g., where "origin" and "upstream" point at
>> different URLs but they both store in "refs/remotes/upstream/*"?
>> Perhaps their URLs may textually be different but are pointing
>> logically at the same place (e.g., one ssh:// the other https:// for
>> example).
>>
>> What should happen? What does happen after you apply this patch?
>
> It would be worth looking at what "git checkout --track" does in that
> case and seeing if we can share the code.
It always is a good idea to think how we can share code for
different purposes to solve a new problem, but in this particular
one, I am not sure if "git checkout -t -b topic upstream/main"
codepath has much to offer to solve what the new "before the
checkout, update from the remote" feature wants to do. To the
former, it does not matter how refs/remotes/upstream/* are updated
and by fetching which remote at all. The only thing it cares about
is to leave the record that this new "topic" branch works with
refs/remotes/upstrea/main. But the latter needs to be able to
compute which remote it should fetch from. It is a problem that
existing code had no need to solve.
|
|
Phillip Wood wrote on the Git mailing list (how to reply to this email): On 21/05/2026 13:58, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> >>> One. Have you considered the case where the remote-tracking refs
>>> are overlapping, e.g., where "origin" and "upstream" point at
>>> different URLs but they both store in "refs/remotes/upstream/*"?
>>> Perhaps their URLs may textually be different but are pointing
>>> logically at the same place (e.g., one ssh:// the other https:// for
>>> example).
>>>
>>> What should happen? What does happen after you apply this patch?
>>
>> It would be worth looking at what "git checkout --track" does in that
>> case and seeing if we can share the code.
> > It always is a good idea to think how we can share code for
> different purposes to solve a new problem, but in this particular
> one, I am not sure if "git checkout -t -b topic upstream/main"
> codepath has much to offer to solve what the new "before the
> checkout, update from the remote" feature wants to do. To the
> former, it does not matter how refs/remotes/upstream/* are updated
> and by fetching which remote at all.
Don't we want to avoid creating a branch with an ambiguous upstream so that a subsequent "git pull" works though? Looking at branch.c:setup_tracking() it seems to reject upstream branches that match more than one remote.
Thanks
Phillip
> The only thing it cares about
> is to leave the record that this new "topic" branch works with
> refs/remotes/upstrea/main. But the latter needs to be able to
> compute which remote it should fetch from. It is a problem that
> existing code had no need to solve.
> |
|
Junio C Hamano wrote on the Git mailing list (how to reply to this email): Phillip Wood <phillip.wood123@gmail.com> writes:
> Don't we want to avoid creating a branch with an ambiguous upstream so
> that a subsequent "git pull" works though? Looking at
> branch.c:setup_tracking() it seems to reject upstream branches that
> match more than one remote.
Yes. We may try to avoid creating misconfigured branches in the
first place, but we'd want to make sure other parts of the system
that consumes existing branches to behave as sensible as possible,
no?
Thanks. |
|
This patch series was integrated into seen via 3505be4. |
|
There was a status update in the "Cooking" section about the branch "git checkout --track=..." learned to optionally fetch the branch from the remote the new branch will work with. Comments? source: <pull.2281.v12.git.git.1779358803652.gitgitgadget@gmail.com> |
|
/submit |
|
Submitted as pull.2281.v13.git.git.1779565714.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
find_tracking_remote_for_ref()andadvise_ambiguous_fetch_refspec()frombranch.c, socheckoutcan reuse the same lookupgit branch --trackuses.advise_ambiguous_fetch_refspec()for the "multiple remotes match" case, so the wording matchesgit branch --track.cc: Ramsay Jones ramsay@ramsayjones.plus.com
cc: "D. Ben Knoble" ben.knoble@gmail.com
cc: "Kristoffer Haugsbakk" kristofferhaugsbakk@fastmail.com
cc: Marc Branchaud marcnarc@gmail.com
cc: Phillip Wood phillip.wood123@gmail.com