Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make git push -u without arguments set up the upstream remote by default #1061

Open
pasky opened this issue Oct 17, 2021 · 9 comments
Open

Comments

@pasky
Copy link

pasky commented Oct 17, 2021

A common workflow with the very popular workflow of topic branches is to create a branch, commit, then push it upstream. This invariably devolves to calling git push, receiving the hint

fatal: The current branch pasky-auth-token has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin pasky-auth-token

and copy-pasting that to actually do the first push of the topic branch.

Ideally, just calling git push -u should do the same thing as this copy-paste (the hint is always correct in typical situations).

@phil-blain
Copy link

phil-blain commented Nov 13, 2021

An alternative would be to use remote.pushDefault = origin and push.default = current. That would make a simple git push push your current branch (here pasky-auth-token) to a branch with the same name on the remote origin.

Granted , it does not set up upstream information, so you can't then use i.e. git pull, git merge and git rebase without arguments, as would be the case if the upstream information was configured.

You might want to have a look at that blog post :)


Note also that you can also use git push origin HEAD to push your current branch to a branch with the same name on the remote origin (again, this does not set up upstream info).

@Abhra303
Copy link

Hello @pasky and @phil-blain , I had made a similar patch request on git mailing list and after some discussions, I found that the current behaviour is better. If no argument is provided to git push, the behaviour of this command depends on the push.default value.

Here is the link - https://lore.kernel.org/git/[email protected]/

Actually, I didn't think deeply while commiting the changes. Today,
I think about it deeply and I realized the following points.

* if push.default='simple' or unspecified then it should not create
  a new branch on the remote. So, my proposed change of 'git push -u'
  for push.default='simple' is badly affecting the reason why
  push.default='simple' was built for.

* if push.default='nothing', It should throw error if no <refspec> is
  provided. Again, my proposed change is hurting it.

* For push.default=upstream, If an upstream is already defined then
  'git push -u' should only set that branch as the upstream of the
  local branch. This already works in git. But if an upstream is not
  provied, it should throw error. So, I am not sure whether 'git push
  -u' (with no upstream information) should create a new branch with
  the same name or not. What do you think about that?

* For push.default=matching, 'git push -u' should set all the existing
  matching branches as upstream of their respective matching local
  branches. It also already works. Same for 'push.default'=current also.

So, to put all in a nutshell, I think that the current behaviour of
'git push -u' is okay. It also seems that he/she who built the
setup_default_push_refspecs() was aware of this.

Note: git push -u (i.e. no arguments provided) already works if push.default is set to one of current, matching . By default, (As of now) the default value for push.default is simple (this configuration doesn't let git push -u to create a new remote branch). This is the reason that git push -u doesn't work with push.default=simple. So, if you want to use git push -u to always push the current branch and set that branch as the upstream - change push.default to current by this git command - git config push.default current.

So, I think this issue should be closed :)

@pasky
Copy link
Author

pasky commented Feb 11, 2022

@Abhra303 ok, but what's your argument for push.default=simple not creating a new remote branch? I'm sorry, I couldn't pinpoint that in your post.

Junio says "I think erring on the side of caution is more sensible than blindly assuming that the user wants a new branch with the same name" - I guess I simply disagree with that since the friction this adds feels more harmful to me than the (moreover easily reversible / undoable) risk it introduces.

@Abhra303
Copy link

Hello @pasky,

but what's your argument for push.default=simple not creating a new remote branch? I'm sorry, I couldn't pinpoint that in your post.

If you see the docs of push.default=simple, it already gave the reason -

simple - pushes the current branch with the same name on the remote.

If you are working on a centralized workflow (pushing to the same repository you pull from, which is typically origin), then you need to configure an upstream branch with the same name.

This mode is the default since Git 2.0, and is the safest option suited for beginners.

The push.default configuration defines the behaviour that git should follow for argument-less git push. There are mainly 5 values that it can take - simple, current, matching, upstream and nothing.

There are some devs who do not want to create a new branch while running argument-less git push command. push.default=simple is a good option for them. It pushes all the refs (i.e. current branch's refs) to the remote branch (with same name of current branch) if the remote branch already exists - else it throws error.

People ( most probably you're also in this category) who want git push to always push to a remote branch (with the same name of the current branch) irrespective of their existence in the remote, can use push.default=current. It creates a remote branch (if it doesn't exist before) and then pushes the refs to it.

You can check the docs to know about other values.

Junio says "I think erring on the side of caution is more sensible than blindly assuming that the user wants a new branch with the same name"

It was for push.default=upstream. Setting push.default to upstream means, you want git push(argument less) to always push to the upstream branch. If no upstream branch is found, it will throw error.

I guess I simply disagree with that since the friction this adds feels more harmful to me than the (moreover easily reversible / undoable) risk it introduces.

That's why I am sure push.default=current configuration is ideal for you :)

@pasky
Copy link
Author

pasky commented Feb 12, 2022

Oh, I see what you are saying - I'm not necessarily saying that the push.default modes semantics should change.

There are two aspects:

  • push.default=simple behavior and its documentation. The description "work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one" is cryptic and explains nothing (unless you try really hard to find some meaning, assume NULLs etc.) about what happens when the upstream branch does not exist yet.
  • I suppose you could rephrase my suggestion that push.default=current is a way saner default than push.default=simple in terms of convenience in typical git usage nowadays, if push.default=current in fact behaves the way I suggested.

(A weaker version of this suggestion could be that the error message when there is no upstream branch should suggest push.default=current to make it more discoverable.)

@Abhra303
Copy link

push.default=simple behavior and its documentation. The description "work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one" is cryptic and explains nothing (unless you try really hard to find some meaning, assume NULLs etc.) about what happens when the upstream branch does not exist yet.

Honestly, I also think that the docs for push.default values need more explanation/improvements (such as simple doesn't create new branches on the remote etc.).

I suppose you could rephrase my suggestion that push.default=current is a way saner default than push.default=simple in terms of convenience in typical git usage nowadays, if push.default=current in fact behaves the way I suggested.

I myself personally use current for my daily works. So, personally I would be happy if default mode is set to current. But, I don't know if most of the developers (especially beginners) will like it or not. Moreover, untill git 2.0, matching was the default value. After a lot of discussions, community decided to make simple as the default value for push.default.

@phil-blain
Copy link

With Git 2.37.0, you can configure Git to setup tracking when a new branch is first pushed:

git config --global push.autoSetupRemote true

This works with both push.default=simple and push.default=current. See f49c478.

@TaoK
Copy link

TaoK commented Aug 31, 2023

Ideally, just calling git push -u should do the same thing as this copy-paste (the hint is always correct in typical situations)

As @phil-blain noted, the new config option push.autoSetupRemote does it slightly differently: it doesn't require -u, and therefore doesn't need you to differentiate between "this is the first time I'm pushing" and the more general "I'm pushing".

This is not (yet?) a change in git's default behavior, but the "new" option is also hinted at when you get the classic error you noted above.

@pasky , @dscho, does this address this project idea, or do you believe we should also make the change in behavior proposed here, omitting the need for push.autoSetupRemote for a first-push to succeed, if -u is specified?

@dscho
Copy link
Member

dscho commented Aug 31, 2023

I'm not @pasky but for me, this has been addressed. Thank you @TaoK for staying on top of things!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants