{"thread":{"id":"62645","subject":"remote.<name>.push without dst doesn't behave as documented","startedAt":"2024-12-16T16:47:41Z","lastAt":"2024-12-19T03:48:29Z","messageCount":4,"participants":["Yuri Kanivetsky","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"509181","messageId":"CAMhVC3b+1TWLkKGYVb6VyBRyQjsDpbKRQQNT8SUXSmrWHfPnEQ@mail.gmail.com","threadId":"62645","inReplyTo":null,"subject":"remote.<name>.push without dst doesn't behave as documented","fromName":"Yuri Kanivetsky","fromEmail":"yuri.kanivetsky@gmail.com","sentAt":"2024-12-16T16:47:28Z","receivedAt":"2024-12-16T16:47:41Z","isPatch":false,"sender":{"key":"yuri.kanivetsky@gmail.com","avatar":"https://gravatar.com/avatar/e4d91cf41e555a0c340222a1898c6320f51ad5ab2f9638282cc2412abb450648?d=mp&s=160"},"body":"Hi,\n\n> 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>.\n\nhttps://git-scm.com/docs/git-push#Documentation/git-push.txt-ltrefspecgt82308203\n\nThe only case I can think of where refspec is not passed via command\nline and it updates a non-matching branch is when push.default =\nupstream. But with remote.<repository>.push without dst it starts\nupdating a matching branch. Either I don't understand what's meant, or\nit doesn't behave as documented.\n\nThe second test fails:\n\n@test \"normally a non-matching ref updates\" {\n    start_cloned_repo\n    git config push.default upstream\n    git checkout -b bb\n    git branch -u origin/ba\n    git commit --allow-empty -m b\n\n    git push\n\n    assert_equal_refs origin/ba bb\n}\n\n@test \"with remote.<name>.push without dst happens what happens normally\" {\n    start_cloned_repo\n    git config push.default upstream\n    git config remote.origin.push 'refs/heads/*'\n    git checkout -b bb\n    git branch -u origin/ba\n    git commit --allow-empty -m b\n\n    git push\n\n    assert_equal_refs origin/ba bb\n}\n\nstart_cloned_repo() {\n    (mkrepo)\n    cd \"$BATS_TEST_TMPDIR\"\n    git clone --bare a a.git\n    git clone a.git b\n    cd b\n    git config push.default upstream\n    git config user.email you@example.com\n    git config user.name \"Your Name\"\n}\n\nmkrepo() {\n    cd \"$BATS_TEST_TMPDIR\"\n    mkdir a\n    (cd a\n    git init\n    git branch -m ba\n    git config user.email you@example.com\n    git config user.name \"Your Name\"\n    git commit --allow-empty -m a)\n}\n\nMore details in a gist:\nhttps://gist.github.com/x-yuri/943fd13704b38551da36c8363d7852e1\n\nRegards,\nYuri\n"},{"id":"509182","messageId":"xmqqr0674hvq.fsf@gitster.g","threadId":"62645","inReplyTo":"CAMhVC3b+1TWLkKGYVb6VyBRyQjsDpbKRQQNT8SUXSmrWHfPnEQ@mail.gmail.com","subject":"Re: remote.<name>.push without dst doesn't behave as documented","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-12-16T18:12:09Z","receivedAt":"2024-12-16T18:12:12Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yuri Kanivetsky <yuri.kanivetsky@gmail.com> writes:\n\n>> If git push [<repository>] without any <refspec> argument is set\n>> to update some ref at the destination with <src> with\n>> remote.<repository>.push configuration variable, :<dst> part can\n>> be omitted—such a push will update a ref that <src> normally\n>> updates without any <refspec> on the command line. Otherwise,\n>> missing :<dst> means to update the same ref as the <src>.\n\nThis excerpt is for <refspec>... arguments that are given on the\ncommand line, e.g., the command line would look like\n\n    $ git push origin smart\n\nHowever, if we look at the command sequnce you gave,\n\n> ...\n> The second test fails:\n>\n> @test \"normally a non-matching ref updates\" {\n> ...\n>     git push\n> ...\n> }\n>\n> @test \"with remote.<name>.push without dst happens what happens normally\" {\n> ...\n>     git push\n> ...\n> }\n\nneither of the above \"git push\" invocations have <refspec>... on the\ncommand line.  So the rules you quoted would not apply to the above\ntwo \"git push\" invocations, wouldn't it?\n\nIn\n\n    $ git push origin smart\n\na <refspec> \"smart\" is given, but \"smart\" lacks \":<dst>\" part and\nonly has <src> that is \"smart\", typically local branch \"smart\", iow,\n\"refs/heads/smart\".\n\nThe paragraph you quoted describes what happens with that command is\ndesigned to be similar to what \"git push origin\" without any\n<refspec> arguments does wrt the given <src> ref.\n\nFor example, if\n\n    $ git push origin\n\nis set to update some ref on the other side with \"smart\", \"git push\norigin smart\" would update the same ref on the other side.  e.g., if\nyou have\n\n    [remote \"origin\"]\n\tpush = refs/heads/*:refs/remotes/satellite/*\n\nwhich would normally cause \"git push origin\" to use refs/heads/smart\nto update refs/remotes/satellite/smart, then\n\n    $ git push origin smart\n\nwould do the same thing, i.e. send \"refs/heads/smart\" to\n\"refs/remotes/satellite/smart\" on the other side.  If your \"git push\norigin\" is configured to do the matching push, \"git push origin\nmaster\" would update their \"refs/heads/master\" with ours, because\nthat is what \"git push origin\" would do to our \"master\".  That is\nwhat the paragraph you quoted describes, I think.\n\nNow, the command may behave differently from how we described in the\ndocumentation when you did give <refspec> from the command line, and\nin that case you may have found a bug.  But I do not think the @test \nthings you had in your report triggers the paragraph you quoted from\nthe documentation, so would not demonstrate a bug in there.\n\nThanks.\n"},{"id":"509207","messageId":"CAMhVC3byz89UP_DJq+c6UVUNoFW0oRRSwbR7v=uUBAdBMLwqMg@mail.gmail.com","threadId":"62645","inReplyTo":"xmqqr0674hvq.fsf@gitster.g","subject":"Re: remote.<name>.push without dst doesn't behave as documented","fromName":"Yuri Kanivetsky","fromEmail":"yuri.kanivetsky@gmail.com","sentAt":"2024-12-17T08:12:27Z","receivedAt":"2024-12-17T08:12:40Z","isPatch":false,"sender":{"key":"yuri.kanivetsky@gmail.com","avatar":"https://gravatar.com/avatar/e4d91cf41e555a0c340222a1898c6320f51ad5ab2f9638282cc2412abb450648?d=mp&s=160"},"body":"So it was your doing :) (no offense meant)\n\nhttps://github.com/git/git/commit/ca02465b41311fe7634acb9bb5b5c61975ef5f38\n\n> 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>.\n\nMy understanding of this was (the only phrasing that made some sense to me):\n\n> 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>.\n\nAs such I chose `push.default = upstream` because that's the only mode\nwhich allows non-matching refs. I expected it to allow me to\ndiscriminate between having and not having :dst in\nremote.<repository>.push. But without :dst in remote.<repository>.push\nit updated the matching ref (the second test failed).\n\nNow I understand that what was really meant:\n\n> 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.\n\nI believe the phrasing in the documentation calls for being changed.\n\nBut also I can't confirm the \"otherwise\" part. Below the last test\nfails. Either you have to (unless I'm missing something) say:\n\n> If remote.<repository>.push is not set, then it falls back to the `push.default` behavior.\n\nOr make it really push to the matching branch even if `push.default =\nupstream` and the upstream is a non-matching branch.\n\nRegards,\nYuri\n\n--\n\nThe whole file is in a gist:\nhttps://gist.github.com/x-yuri/943fd13704b38551da36c8363d7852e1#file-b-md\n\n# the state of the cloned repository (1 commit, 1 local branch ba)\n# a (HEAD -> ba, origin/ba)\n\n@test \"normally it acts according to push.default\" {\n    start_cloned_repo\n    git commit --allow-empty -m b\n\n    git push\n\n    assert_equal_refs origin/ba ba\n}\n\n@test \"but remote.<repository>.push changes the destination when the\nrefspec on the command line doesn't have :dst\" {\n    start_cloned_repo\n    git config remote.origin.push 'refs/heads/ba:refs/heads/bb'\n    git commit --allow-empty -m b\n\n    git push origin ba\n\n    assert_equal_refs origin/bb ba\n}\n\n@test \"specifying :dst overrides remote.<repository>.push\" {\n    start_cloned_repo\n    git config remote.origin.push 'refs/heads/*:refs/heads/*'\n    git commit --allow-empty -m b\n\n    git push origin ba:bb\n\n    assert_equal_refs origin/bb ba\n}\n\n@test \"if remote.<repository>.push is not set, it pushes to the\nmatching branch\" {\n    start_cloned_repo\n    git config push.default upstream\n    git push origin ba:bb\n    git branch -u origin/bb\n    git commit --allow-empty -m b\n\n    git push origin ba\n\n    assert_equal_refs origin/ba ba\n}\n\nstart_cloned_repo() {\n    (mkrepo)\n    cd \"$BATS_TEST_TMPDIR\"\n    git clone --bare a a.git\n    git clone a.git b\n    cd b\n    git config user.email you@example.com\n    git config user.name \"Your Name\"\n}\n\nmkrepo() {\n    cd \"$BATS_TEST_TMPDIR\"\n    mkdir a\n    (cd a\n    git init\n    git branch -m ba\n    git config user.email you@example.com\n    git config user.name \"Your Name\"\n    git commit --allow-empty -m a)\n}\n"},{"id":"509322","messageId":"CAMhVC3Zegt+GYXq5g04hLrzsUOqvX63OEPM+HB1syX-4cD2U4A@mail.gmail.com","threadId":"62645","inReplyTo":"CAMhVC3byz89UP_DJq+c6UVUNoFW0oRRSwbR7v=uUBAdBMLwqMg@mail.gmail.com","subject":"Re: remote.<name>.push without dst doesn't behave as documented","fromName":"Yuri Kanivetsky","fromEmail":"yuri.kanivetsky@gmail.com","sentAt":"2024-12-19T03:48:15Z","receivedAt":"2024-12-19T03:48:29Z","isPatch":false,"sender":{"key":"yuri.kanivetsky@gmail.com","avatar":"https://gravatar.com/avatar/e4d91cf41e555a0c340222a1898c6320f51ad5ab2f9638282cc2412abb450648?d=mp&s=160"},"body":"I guess I need to add, that I hoped that the beginning would be taken\nas a joke. If it wasn't the case, then sorry :( I didn't mean to\noffend anyone.\n\nRegards,\nYuri\n"}]}