* `git fetch --refmap=<refspec>… <repository> <refspec>…` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
@ 2024-09-04 4:09 Han Jiang
2024-09-04 6:15 ` `git fetch --refmap=<refspec>… <repository> <refspec>… ` " Johannes Sixt
2024-09-04 14:34 ` `git fetch --refmap=<refspec>… <repository> <refspec>…` " Junio C Hamano
0 siblings, 2 replies; 8+ messages in thread
From: Han Jiang @ 2024-09-04 4:09 UTC (permalink / raw)
To: git
Thank you for filling out a Git bug report!
Please answer the following questions to help us understand your issue.
What did you do before the bug happened? (Steps to reproduce your issue)
cd '/'; cd '/'; rm --force --recursive -- './test_git'; mkdir "$_"; cd "$_";
mkdir --parents -- './server' './client';
git -C './server' init --bare './repo.git'
git --git-dir='./server/repo.git' --work-tree='.' commit --allow-empty
-m "$((++number))"
git -C './server/repo.git' branch branch1; git -C './server/repo.git'
branch branch2
git -C './client' init './repo'
git -C './client/repo' remote add server 'file://'"$(realpath
'./server/repo.git')"
git -C './client/repo' remote --verbose
git -C './client/repo' config list --local --show-scope --show-origin
git -C './client/repo' fetch --dry-run
git -C './client/repo' fetch --dry-run
--refmap='+refs/heads/*:refs/remotes/server/*' server branch1 branch2
git -C './client/repo' fetch --dry-run
--refmap='+refs/heads/branch*:refs/remotes/server/branch*' server
branch1 branch2
git -C './client/repo' fetch --dry-run
--refmap='+refs/heads/branch1:refs/remotes/server/branch1' server
branch1 branch2
git -C './client/repo' fetch
--refmap='+refs/heads/branch1:refs/remotes/server/branch1' server
branch1 branch2
git -C './client/repo' branch --list --all --verbose --verbose
What did you expect to happen? (Expected behavior)
In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
server branch1 branch2`,
`remote.server.fetch=+refs/heads/*:refs/remotes/server/*` merges with
`--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
so these should be what would be done:
branch1 -> server/branch1
branch2 -> server/branch2
What happened instead? (Actual behavior)
In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
server branch1 branch2`,
`remote.server.fetch=+refs/heads/*:refs/remotes/server/*` is replaced
by `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
so these are what would be done:
branch1 -> server/branch1
What's different between what you expected and what actually happened?
Anything else you want to add:
Please review the rest of the bug report below.
You can delete any lines you don't wish to share.
[System Info]
git version:
git version 2.46.0.windows.1
cpu: x86_64
built from commit: 2e6a859ffc0471f60f79c1256f766042b0d5d17d
sizeof-long: 4
sizeof-size_t: 8
shell-path: D:/git-sdk-64-build-installers/usr/bin/sh
feature: fsmonitor--daemon
libcurl: 8.9.0
OpenSSL: OpenSSL 3.2.2 4 Jun 2024
zlib: 1.3.1
uname: Windows 10.0 22631
compiler info: gnuc: 14.1
libc info: no libc information available
$SHELL (typically, interactive shell): C:\Program Files\Git\usr\bin\bash.exe
[Enabled Hooks]
not run from a git repository - no hooks to show
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>… ` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 4:09 `git fetch --refmap=<refspec>… <repository> <refspec>…` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs Han Jiang
@ 2024-09-04 6:15 ` Johannes Sixt
2024-09-04 11:12 ` Han Jiang
2024-09-04 14:34 ` `git fetch --refmap=<refspec>… <repository> <refspec>…` " Junio C Hamano
1 sibling, 1 reply; 8+ messages in thread
From: Johannes Sixt @ 2024-09-04 6:15 UTC (permalink / raw)
To: Han Jiang; +Cc: git
Am 04.09.24 um 06:09 schrieb Han Jiang:
> What did you expect to happen? (Expected behavior)
>
> In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
> server branch1 branch2`,
> `remote.server.fetch=+refs/heads/*:refs/remotes/server/*` merges with
> `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
The way I read the documentation of --refmap, I cannot infer any sort of
merging of refspec, only that a replacement occurs.
> so these should be what would be done:
> branch1 -> server/branch1
> branch2 -> server/branch2
>
> What happened instead? (Actual behavior)
>
> In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
> server branch1 branch2`,
> `remote.server.fetch=+refs/heads/*:refs/remotes/server/*` is replaced
> by `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
> so these are what would be done:
> branch1 -> server/branch1
So, this seems the correct output, because it is no longer specified how
branch2 should be stored locally.
-- Hannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>… ` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 6:15 ` `git fetch --refmap=<refspec>… <repository> <refspec>… ` " Johannes Sixt
@ 2024-09-04 11:12 ` Han Jiang
2024-09-04 16:38 ` Johannes Sixt
0 siblings, 1 reply; 8+ messages in thread
From: Han Jiang @ 2024-09-04 11:12 UTC (permalink / raw)
To: Johannes Sixt; +Cc: git
1. If the doc says "providing an empty <refspec> to the --refmap
option causes Git to ignore the configured refspecs and rely entirely
on the refspecs supplied as command-line arguments" then it's
reasonable to guess that "providing a non-empty <refspec> will not do
those". (Otherwise the doc could just say "providing a <refspec> will
do those" without the word "empty".) This is both logical fallacy and
common sense.
2. Searching "empty string" "empty value" in
https://git-scm.com/docs/git-config shows that using empty value to
clear lower priority configurations (and non-empty values just stack
up) is common behavior of multi-valued configuration variables.
On Wed, Sep 4, 2024 at 6:15 PM Johannes Sixt <j6t@kdbg.org> wrote:
>
> Am 04.09.24 um 06:09 schrieb Han Jiang:
> > What did you expect to happen? (Expected behavior)
> >
> > In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
> > server branch1 branch2`,
> > `remote.server.fetch=+refs/heads/*:refs/remotes/server/*` merges with
> > `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
>
> The way I read the documentation of --refmap, I cannot infer any sort of
> merging of refspec, only that a replacement occurs.
>
> > so these should be what would be done:
> > branch1 -> server/branch1
> > branch2 -> server/branch2
> >
> > What happened instead? (Actual behavior)
> >
> > In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
> > server branch1 branch2`,
> > `remote.server.fetch=+refs/heads/*:refs/remotes/server/*` is replaced
> > by `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
> > so these are what would be done:
> > branch1 -> server/branch1
>
> So, this seems the correct output, because it is no longer specified how
> branch2 should be stored locally.
>
> -- Hannes
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>…` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 4:09 `git fetch --refmap=<refspec>… <repository> <refspec>…` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs Han Jiang
2024-09-04 6:15 ` `git fetch --refmap=<refspec>… <repository> <refspec>… ` " Johannes Sixt
@ 2024-09-04 14:34 ` Junio C Hamano
2024-09-04 23:41 ` Han Jiang
1 sibling, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2024-09-04 14:34 UTC (permalink / raw)
To: Han Jiang; +Cc: git
Han Jiang <jhcarl0814@gmail.com> writes:
> What happened instead? (Actual behavior)
>
> In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
> server branch1 branch2`,
> `remote.server.fetch=+refs/heads/*:refs/remotes/server/*` is replaced
> by `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
> so these are what would be done:
> branch1 -> server/branch1
This is totally expected.
A refspec specifies "what to fetch" and "where to store locally what
we fetched" at the same time. A refmap only specifies the "where
the stuff is stored locally" part, and what to fetch is specified
separately. You asked branch1 and branch2 to be fetched (peek into
the .git/FETCH_HEAD file to see both objects are fetched) from the
command line arguments, and your refmap specified where to store
what you got from their refs/heads/branch1. As the refmap does not
say anything about any other branches, they are not stored anywhere
in your local refs/ namespace.
Typically --refmap is given with a glob, but the story is the same
there. If you fetched refs/notes/commits from that same server with
a refmap to map "refs/heads/*:refs/remotes/server/*", the notes commit
is not mapped to anywhere with the refmap, so nothing will happen to
it.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>… ` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 11:12 ` Han Jiang
@ 2024-09-04 16:38 ` Johannes Sixt
2024-09-04 16:47 ` Junio C Hamano
0 siblings, 1 reply; 8+ messages in thread
From: Johannes Sixt @ 2024-09-04 16:38 UTC (permalink / raw)
To: Han Jiang; +Cc: git
Am 04.09.24 um 13:12 schrieb Han Jiang:
> 1. If the doc says "providing an empty <refspec> to the --refmap
> option causes Git to ignore the configured refspecs and rely entirely
> on the refspecs supplied as command-line arguments" then it's
> reasonable to guess that "providing a non-empty <refspec> will not do
> those".
Fair enough. But then in section "Configured Remote-tracking Branches"
it is said that "The latter use of the remote.<repository>.fetch values
can be overridden by giving the --refmap=<refspec> parameter(s) on the
command line." So... I dunno. Just my 2c.
-- Hannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>… ` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 16:38 ` Johannes Sixt
@ 2024-09-04 16:47 ` Junio C Hamano
2024-09-04 23:52 ` Han Jiang
0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2024-09-04 16:47 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Han Jiang, git
Johannes Sixt <j6t@kdbg.org> writes:
> Am 04.09.24 um 13:12 schrieb Han Jiang:
>> 1. If the doc says "providing an empty <refspec> to the --refmap
>> option causes Git to ignore the configured refspecs and rely entirely
>> on the refspecs supplied as command-line arguments" then it's
>> reasonable to guess that "providing a non-empty <refspec> will not do
>> those".
>
> Fair enough. But then in section "Configured Remote-tracking Branches"
> it is said that "The latter use of the remote.<repository>.fetch values
> can be overridden by giving the --refmap=<refspec> parameter(s) on the
> command line." So... I dunno. Just my 2c.
This cuts both ways, I suspect. It is so unusual to say
git fetch --refmap="" foo bar baz
to use an empty string as <refspec> in "--refmap=<refspec>", simply
because you would not say
git fetch origin ""
and expect the empty string is a <refspec> in "git fetch origin <refspec>".
Any string other than an empty string, e.g.
git fetch --refmap="refs/heads/*:refs/prefetch/x/*" foo bar baz
would have an extra side effect of storing what gets fetched, when
your primary focus is "I want the command to ignore the configured
refspec".
For these reasons, I would actually say it is quite fair for the
documentation to single out the empty string case as an idiom that
may be hard for readers to figure out for themselves without being
told.
I would not be opposed to add a sentence or two to clarify what
happens when a non-empty <refspec> is used, though.
Thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>…` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 14:34 ` `git fetch --refmap=<refspec>… <repository> <refspec>…` " Junio C Hamano
@ 2024-09-04 23:41 ` Han Jiang
0 siblings, 0 replies; 8+ messages in thread
From: Han Jiang @ 2024-09-04 23:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
@Junio C Hamano Thank you for the explanation!
As you said, "refmap only specifies the where the stuff is stored
locally" (what to fetch is specified by last command line arguments),
but the issue with this report is a bit complicated because it's about
whether "only refmap specifies the where the stuff is stored locally".
After I search "empty value" or "empty string" in
https://git-scm.com/docs/git-config , the most intuitive behavior of
`git fetch --refmap` (for me) is:
`git fetch <remote> <branch>...` uses `remote.<remote>.fetch`;
`git fetch --refmap=<refspec> --refmap=<refspec> <remote> <branch>...`
uses `remote.<remote>.fetch` and all the `--refmap=<refspec>`s;
`git fetch --refmap='' --refmap=<refspec> --refmap=<refspec> <remote>
<branch>...` uses all the `--refmap=<refspec>`s;
I'll post an example of all of these being used at the same time to both of you.
On Thu, Sep 5, 2024 at 2:34 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Han Jiang <jhcarl0814@gmail.com> writes:
>
> > What happened instead? (Actual behavior)
> >
> > In `git fetch --refmap='+refs/heads/branch1:refs/remotes/server/branch1'
> > server branch1 branch2`,
> > `remote.server.fetch=+refs/heads/*:refs/remotes/server/*` is replaced
> > by `--refmap='+refs/heads/branch1:refs/remotes/server/branch1'`,
> > so these are what would be done:
> > branch1 -> server/branch1
>
> This is totally expected.
>
> A refspec specifies "what to fetch" and "where to store locally what
> we fetched" at the same time. A refmap only specifies the "where
> the stuff is stored locally" part, and what to fetch is specified
> separately. You asked branch1 and branch2 to be fetched (peek into
> the .git/FETCH_HEAD file to see both objects are fetched) from the
> command line arguments, and your refmap specified where to store
> what you got from their refs/heads/branch1. As the refmap does not
> say anything about any other branches, they are not stored anywhere
> in your local refs/ namespace.
>
> Typically --refmap is given with a glob, but the story is the same
> there. If you fetched refs/notes/commits from that same server with
> a refmap to map "refs/heads/*:refs/remotes/server/*", the notes commit
> is not mapped to anywhere with the refmap, so nothing will happen to
> it.
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `git fetch --refmap=<refspec>… <repository> <refspec>… ` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs
2024-09-04 16:47 ` Junio C Hamano
@ 2024-09-04 23:52 ` Han Jiang
0 siblings, 0 replies; 8+ messages in thread
From: Han Jiang @ 2024-09-04 23:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, git
> But then in section "Configured Remote-tracking Branches" it is said that
The problem with the doc is "how to override". From
https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---refmapltrefspecgt
it seems we need to `git fetch --refmap='' --refmap=<refspec>` to
really override configuration variables.
I guess the inner working is like this: first for-loop traverses
configuration variable `remote.<remote>.fetch` collecting <refspec>s
into a list, then second for-loop traverses `--refmap=<refspec>`s,
clears the list when an empty string is encountered, appends to the
list when a non-empty string is encountered. Maybe I'm just
daydreaming...
> git fetch --refmap="" foo bar baz
I think the correct use case of empty string, is to specify more
--refmap=<refspec>s after it (like in
https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushpushOption
), otherwise the mapping (to operate upon foo,bar and baz) would be
empty.
Sorry that I didn't use examples to express my intended use scenarios clearly!
After I searched "empty value" or "empty string" in
https://git-scm.com/docs/git-config yesterday, the most intuitive
behavior of `git fetch --refmap` (for me) was:
`git fetch <remote> <branch>...` uses `remote.<remote>.fetch`;
`git fetch --refmap=<refspec> --refmap=<refspec> <remote> <branch>...`
uses `remote.<remote>.fetch` and all the `--refmap=<refspec>`s;
`git fetch --refmap='' --refmap=<refspec> --refmap=<refspec> <remote>
<branch>...` uses all the `--refmap=<refspec>`s;
Here is an example of all of these being used at the same time.
1. Normally, user uses `fetch-safe` which uses `git fetch
--refmap=<refspec>` to use whatever mappings specified by
`remote.<remote>.fetch` and also let our backup logic sneak in.
2. Occasionally, upstream is rebased and our backup logic (refspec
without `+`) blocks the process because of `--atomic`.
2.1. When that happens, user uses `fetch-bak-current-time` which uses
`git fetch --refmap='' --refmap=<refspec>` to clear whatever mappings
specified by `remote.<remote>.fetch` and use our another backup logic
(refspec with `+`).
2.2. After old tips are saved, user uses `git fetch --force` to use
whatever mappings specified by `remote.<remote>.fetch`;
Currently [1.] is not working because --refmap=<not empty string!>
clears `remote.<remote>.fetch` instead of merging with it. Hence this
bug report.
cd '/'; cd '/'; rm --force --recursive -- './test_git2'; mkdir "$_"; cd "$_";
mkdir --parents -- './server' './client';
git -C './server' init --bare './repo.git'
git --git-dir='./server/repo.git' --work-tree='.' commit --allow-empty
-m "$((++number))"
git --git-dir='./server/repo.git' --work-tree='.' commit --allow-empty
-m "$((++number))"
git -C './server/repo.git' branch branch1; git -C './server/repo.git'
branch branch2
git -C './client' init './repo'
git -C './client/repo' config set --local 'alias.fetch-safe'
'!git_fetch_safe(){ server="$1"; shift; git fetch --atomic
--refmap='\''refs/*:refs/namespaces/'\''"$server"'\''_backup/refs/*'\''
"$server" "$@"; };git_fetch_safe'
git -C './client/repo' config set --local
'alias.fetch-bak-current-time' '!git_fetch_bak_current_time(){
server="$1"; shift; git -c
'\''remote.'\''"$server"'\''_backup.url=.'\''
--namespace="$server"'\''_backup'\'' fetch
--refmap='\''refs/*:refs/namespaces/'\''"$server"'\''_backup_'\''"$(date
+'%Y%m%d%H%M%S')"'\''/refs/*'\'' "$server"'_backup' "$@"; git fetch
--atomic --refmap='\'\''
--refmap='\''+refs/*:refs/namespaces/'\''"$server"'\''_backup/refs/*'\''
"$server" "$@"; };git_fetch_bak_current_time'
git -C './client/repo' remote add server 'file://'"$(realpath
'./server/repo.git')"
git -C './client/repo' remote --verbose
git -C './client/repo' config list --local --show-scope --show-origin
git -C './client/repo' fetch-safe server branch1 branch2
git -C './client/repo' show-ref
git -C './client/repo' lg --all --decorate-refs='*'
git --git-dir='./server/repo.git' --work-tree='.' commit --allow-empty
-m "$((++number))"
git -C './server/repo.git' branch --force branch1; git -C
'./server/repo.git' branch --force branch2
git -C './client/repo' fetch-safe server branch1 branch2
git -C './client/repo' show-ref
git -C './client/repo' lg --all --decorate-refs='*'
git --git-dir='./server/repo.git' --work-tree='.' commit --allow-empty
-m "$((++number))" --amend
git -C './server/repo.git' branch --force branch1; git -C
'./server/repo.git' branch --force branch2
git -C './client/repo' fetch-safe server branch1 branch2
git -C './client/repo' show-ref
git -C './client/repo' lg --all --decorate-refs='*'
git -C './client/repo' fetch-bak-current-time server branch1 branch2
git -C './client/repo' show-ref
git -C './client/repo' lg --all --decorate-refs='*'
git -C './client/repo' fetch --force server branch1 branch2
git -C './client/repo' show-ref
git -C './client/repo' lg --all --decorate-refs='*'
On Thu, Sep 5, 2024 at 4:47 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Johannes Sixt <j6t@kdbg.org> writes:
>
> > Am 04.09.24 um 13:12 schrieb Han Jiang:
> >> 1. If the doc says "providing an empty <refspec> to the --refmap
> >> option causes Git to ignore the configured refspecs and rely entirely
> >> on the refspecs supplied as command-line arguments" then it's
> >> reasonable to guess that "providing a non-empty <refspec> will not do
> >> those".
> >
> > Fair enough. But then in section "Configured Remote-tracking Branches"
> > it is said that "The latter use of the remote.<repository>.fetch values
> > can be overridden by giving the --refmap=<refspec> parameter(s) on the
> > command line." So... I dunno. Just my 2c.
>
> This cuts both ways, I suspect. It is so unusual to say
>
> git fetch --refmap="" foo bar baz
>
> to use an empty string as <refspec> in "--refmap=<refspec>", simply
> because you would not say
>
> git fetch origin ""
>
> and expect the empty string is a <refspec> in "git fetch origin <refspec>".
>
> Any string other than an empty string, e.g.
>
> git fetch --refmap="refs/heads/*:refs/prefetch/x/*" foo bar baz
>
> would have an extra side effect of storing what gets fetched, when
> your primary focus is "I want the command to ignore the configured
> refspec".
>
> For these reasons, I would actually say it is quite fair for the
> documentation to single out the empty string case as an idiom that
> may be hard for readers to figure out for themselves without being
> told.
>
> I would not be opposed to add a sentence or two to clarify what
> happens when a non-empty <refspec> is used, though.
>
> Thanks.
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-09-04 23:52 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-04 4:09 `git fetch --refmap=<refspec>… <repository> <refspec>…` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs Han Jiang
2024-09-04 6:15 ` `git fetch --refmap=<refspec>… <repository> <refspec>… ` " Johannes Sixt
2024-09-04 11:12 ` Han Jiang
2024-09-04 16:38 ` Johannes Sixt
2024-09-04 16:47 ` Junio C Hamano
2024-09-04 23:52 ` Han Jiang
2024-09-04 14:34 ` `git fetch --refmap=<refspec>… <repository> <refspec>…` " Junio C Hamano
2024-09-04 23:41 ` Han Jiang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).