git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: `git fetch --refmap=<refspec>… <repository> <refspec>… ` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs

From
Han Jiang <jhcarl0814@gmail.com>
Date
Sep 4, 2024, 23:52 UTC
Message-ID
<CANrWfmQCBwjzydyBFJ5OTE7E7EJFFmht-Qz54hin0UZd1LKXCQ@mail.gmail.com>
In-Reply-To
<xmqq5xrbbc36.fsf@gitster.g>
> 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:
Show 44 quoted lines
>
> 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.
>
Previous: Junio C HamanoNext: Junio C Hamano
Message 6 of 8 in “`git fetch --refmap=<refspec>… <repository> <refspec>…​` providing NON-empty <refspec> to the --refmap ALSO causes Git to ignore the configured refspecs”
  1. Han JiangSep 4, 2024
  2. Johannes SixtSep 4, 2024
  3. Han JiangSep 4, 2024
  4. Johannes SixtSep 4, 2024
  5. Junio C HamanoSep 4, 2024
  6. Han JiangSep 4, 2024
  7. Junio C HamanoSep 4, 2024
  8. Han JiangSep 4, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.