git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* remote.<name>.push without dst doesn't behave as documented
@ 2024-12-16 16:47 Yuri Kanivetsky
  2024-12-16 18:12 ` Junio C Hamano
  0 siblings, 1 reply; 4+ messages in thread
From: Yuri Kanivetsky @ 2024-12-16 16:47 UTC (permalink / raw)
  To: Git Mailing List

Hi,

> If git push [<repository>] without any <refspec> argument is set to update some ref at the destination with <src> with remote.<repository>.push configuration variable, :<dst> part can be omitted—such a push will update a ref that <src> normally updates without any <refspec> on the command line. Otherwise, missing :<dst> means to update the same ref as the <src>.

https://git-scm.com/docs/git-push#Documentation/git-push.txt-ltrefspecgt82308203

The only case I can think of where refspec is not passed via command
line and it updates a non-matching branch is when push.default =
upstream. But with remote.<repository>.push without dst it starts
updating a matching branch. Either I don't understand what's meant, or
it doesn't behave as documented.

The second test fails:

@test "normally a non-matching ref updates" {
    start_cloned_repo
    git config push.default upstream
    git checkout -b bb
    git branch -u origin/ba
    git commit --allow-empty -m b

    git push

    assert_equal_refs origin/ba bb
}

@test "with remote.<name>.push without dst happens what happens normally" {
    start_cloned_repo
    git config push.default upstream
    git config remote.origin.push 'refs/heads/*'
    git checkout -b bb
    git branch -u origin/ba
    git commit --allow-empty -m b

    git push

    assert_equal_refs origin/ba bb
}

start_cloned_repo() {
    (mkrepo)
    cd "$BATS_TEST_TMPDIR"
    git clone --bare a a.git
    git clone a.git b
    cd b
    git config push.default upstream
    git config user.email you@example.com
    git config user.name "Your Name"
}

mkrepo() {
    cd "$BATS_TEST_TMPDIR"
    mkdir a
    (cd a
    git init
    git branch -m ba
    git config user.email you@example.com
    git config user.name "Your Name"
    git commit --allow-empty -m a)
}

More details in a gist:
https://gist.github.com/x-yuri/943fd13704b38551da36c8363d7852e1

Regards,
Yuri

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: remote.<name>.push without dst doesn't behave as documented
  2024-12-16 16:47 remote.<name>.push without dst doesn't behave as documented Yuri Kanivetsky
@ 2024-12-16 18:12 ` Junio C Hamano
  2024-12-17  8:12   ` Yuri Kanivetsky
  0 siblings, 1 reply; 4+ messages in thread
From: Junio C Hamano @ 2024-12-16 18:12 UTC (permalink / raw)
  To: Yuri Kanivetsky; +Cc: Git Mailing List

Yuri Kanivetsky <yuri.kanivetsky@gmail.com> writes:

>> If git push [<repository>] without any <refspec> argument is set
>> to update some ref at the destination with <src> with
>> remote.<repository>.push configuration variable, :<dst> part can
>> be omitted—such a push will update a ref that <src> normally
>> updates without any <refspec> on the command line. Otherwise,
>> missing :<dst> means to update the same ref as the <src>.

This excerpt is for <refspec>... arguments that are given on the
command line, e.g., the command line would look like

    $ git push origin smart

However, if we look at the command sequnce you gave,

> ...
> The second test fails:
>
> @test "normally a non-matching ref updates" {
> ...
>     git push
> ...
> }
>
> @test "with remote.<name>.push without dst happens what happens normally" {
> ...
>     git push
> ...
> }

neither of the above "git push" invocations have <refspec>... on the
command line.  So the rules you quoted would not apply to the above
two "git push" invocations, wouldn't it?

In

    $ git push origin smart

a <refspec> "smart" is given, but "smart" lacks ":<dst>" part and
only has <src> that is "smart", typically local branch "smart", iow,
"refs/heads/smart".

The paragraph you quoted describes what happens with that command is
designed to be similar to what "git push origin" without any
<refspec> arguments does wrt the given <src> ref.

For example, if

    $ git push origin

is set to update some ref on the other side with "smart", "git push
origin smart" would update the same ref on the other side.  e.g., if
you have

    [remote "origin"]
	push = refs/heads/*:refs/remotes/satellite/*

which would normally cause "git push origin" to use refs/heads/smart
to update refs/remotes/satellite/smart, then

    $ git push origin smart

would do the same thing, i.e. send "refs/heads/smart" to
"refs/remotes/satellite/smart" on the other side.  If your "git push
origin" is configured to do the matching push, "git push origin
master" would update their "refs/heads/master" with ours, because
that is what "git push origin" would do to our "master".  That is
what the paragraph you quoted describes, I think.

Now, the command may behave differently from how we described in the
documentation when you did give <refspec> from the command line, and
in that case you may have found a bug.  But I do not think the @test 
things you had in your report triggers the paragraph you quoted from
the documentation, so would not demonstrate a bug in there.

Thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: remote.<name>.push without dst doesn't behave as documented
  2024-12-16 18:12 ` Junio C Hamano
@ 2024-12-17  8:12   ` Yuri Kanivetsky
  2024-12-19  3:48     ` Yuri Kanivetsky
  0 siblings, 1 reply; 4+ messages in thread
From: Yuri Kanivetsky @ 2024-12-17  8:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List

So it was your doing :) (no offense meant)

https://github.com/git/git/commit/ca02465b41311fe7634acb9bb5b5c61975ef5f38

> If git push [<repository>] without any <refspec> argument is set to update some ref at the destination with <src> with remote.<repository>.push configuration variable, :<dst> part can be omitted—such a push will update a ref that <src> normally updates without any <refspec> on the command line. Otherwise, missing :<dst> means to update the same ref as the <src>.

My understanding of this was (the only phrasing that made some sense to me):

> If git push [<repository>] without any <refspec> argument __is invoked__ to update some ref at the destination with <src> __and remote.<repository>.push is set__, :<dst> part can be omitted __in remote.<repository>.push__ -- such a push will update a ref that <src> normally updates without any <refspec> on the command line. Otherwise, missing :<dst> means to update the same ref as the <src>.

As such I chose `push.default = upstream` because that's the only mode
which allows non-matching refs. I expected it to allow me to
discriminate between having and not having :dst in
remote.<repository>.push. But without :dst in remote.<repository>.push
it updated the matching ref (the second test failed).

Now I understand that what was really meant:

> If remote.<repository>.push is set and the refspec on the command line doesn't have the :dst part, then the former (remote.<repository>.push) is used as a refmap. Otherwise (if remote.<repository>.push is not set), then missing :dst makes it push to the matching branch.

I believe the phrasing in the documentation calls for being changed.

But also I can't confirm the "otherwise" part. Below the last test
fails. Either you have to (unless I'm missing something) say:

> If remote.<repository>.push is not set, then it falls back to the `push.default` behavior.

Or make it really push to the matching branch even if `push.default =
upstream` and the upstream is a non-matching branch.

Regards,
Yuri

--

The whole file is in a gist:
https://gist.github.com/x-yuri/943fd13704b38551da36c8363d7852e1#file-b-md

# the state of the cloned repository (1 commit, 1 local branch ba)
# a (HEAD -> ba, origin/ba)

@test "normally it acts according to push.default" {
    start_cloned_repo
    git commit --allow-empty -m b

    git push

    assert_equal_refs origin/ba ba
}

@test "but remote.<repository>.push changes the destination when the
refspec on the command line doesn't have :dst" {
    start_cloned_repo
    git config remote.origin.push 'refs/heads/ba:refs/heads/bb'
    git commit --allow-empty -m b

    git push origin ba

    assert_equal_refs origin/bb ba
}

@test "specifying :dst overrides remote.<repository>.push" {
    start_cloned_repo
    git config remote.origin.push 'refs/heads/*:refs/heads/*'
    git commit --allow-empty -m b

    git push origin ba:bb

    assert_equal_refs origin/bb ba
}

@test "if remote.<repository>.push is not set, it pushes to the
matching branch" {
    start_cloned_repo
    git config push.default upstream
    git push origin ba:bb
    git branch -u origin/bb
    git commit --allow-empty -m b

    git push origin ba

    assert_equal_refs origin/ba ba
}

start_cloned_repo() {
    (mkrepo)
    cd "$BATS_TEST_TMPDIR"
    git clone --bare a a.git
    git clone a.git b
    cd b
    git config user.email you@example.com
    git config user.name "Your Name"
}

mkrepo() {
    cd "$BATS_TEST_TMPDIR"
    mkdir a
    (cd a
    git init
    git branch -m ba
    git config user.email you@example.com
    git config user.name "Your Name"
    git commit --allow-empty -m a)
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: remote.<name>.push without dst doesn't behave as documented
  2024-12-17  8:12   ` Yuri Kanivetsky
@ 2024-12-19  3:48     ` Yuri Kanivetsky
  0 siblings, 0 replies; 4+ messages in thread
From: Yuri Kanivetsky @ 2024-12-19  3:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List

I guess I need to add, that I hoped that the beginning would be taken
as a joke. If it wasn't the case, then sorry :( I didn't mean to
offend anyone.

Regards,
Yuri

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-12-19  3:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-16 16:47 remote.<name>.push without dst doesn't behave as documented Yuri Kanivetsky
2024-12-16 18:12 ` Junio C Hamano
2024-12-17  8:12   ` Yuri Kanivetsky
2024-12-19  3:48     ` Yuri Kanivetsky

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).