git push -> code review only current change (remote.origin.push overrides push.default)
Asked Answered
A

1

6

My team is using gerrit code review, essentially this means the default push behaviour bypasses the standard workflow so instead we need to use git push origin HEAD:refs/for/feature to correctly push our code to get reviewed.

The default push behaviour looks like this:

user$ git push --dry-run
To https://gerrit.company.url/project
   83fa2a5..aca3a22  feature -> feature

This would bypass the review process which is undesired.

When I set the push ref-spec (reference here) to be refs/heads/*:refs/for/* this takes a step in the right direction:

user $ git config remote.origin.push refs/heads/*:refs/for/*
user$ git push --dry-run
To https://gerrit.company.url/project
 * [new branch]      master -> refs/for/master
 * [new branch]      old_stuff -> refs/for/old_stuff
 * [new branch]      feature -> refs/for/feature

Now it is trying to push feature to refs/for/feature which is what I want but it's also trying to push all my branches to origin. Gerrit rejects more than one request so I get an output like this:

user$ git push
....
To https://gerrit.company.url/project
 ! [remote rejected] master -> refs/for/master (no new changes)
 ! [remote rejected] old_stuff -> refs/for/old_stuff (duplicate request)
 ! [remote rejected] feature -> refs/for/feature (duplicate request)

but I found that if I name the current branch it does what I'm expecting:

user $ git push origin feature --dry-run
To https://gerrit.company.url/project
 * [new branch]      feature -> refs/for/feature

This is great and I will be able to use this but I'd like to narrow it more. I figured if I set push.default to current it will mean that git push will only push the current branch in this way, but to my disappointment:

user$ git config push.default current
user$ git push origin --dry-run
To https://gerrit.company.url/project
 * [new branch]      master -> refs/for/master
 * [new branch]      old_stuff -> refs/for/old_stuff
 * [new branch]      feature -> refs/for/feature

This seems to be ignoring the push.default setting, From the git config documentation:

push.default

Defines the action git push should take if no refspec is explicitly given

So the remote.origin.push config gets interpreted as an explicit ref spec? Even when setting the default push behaviour to nothing it still tries to push all branches:

user$ git config push.default nothing
user$ git push
fatal: You didn't specify any refspecs to push, and push.default is "nothing".
user$ git config remote.origin.push refs/heads/*:refs/for/*
user$ git push origin --dry-run
To https://gerrit.company.url/project
 * [new branch]      master -> refs/for/master
 * [new branch]      old_stuff -> refs/for/old_stuff
 * [new branch]      feature -> refs/for/feature

What am I missing here? How do I get git push to only push the current branch like feature -> refs/for/feature?

Autocrat answered 18/10, 2018 at 16:10 Comment(2)
Instead of current try using simple Solution : git config --global push.default simpleInclement
@poojapatil when remote.origin.push is defined then it doesn't make any difference what push.default is set to, I demonstrate that in the last example.Autocrat
S
3

I don't believe what you want to do can be done with just git currently.

I've been able to narrow it down one level further by defining remote server aliases in my config file like below, one for each branch I might want to push, but this is obviously tedious and obnoxious, and I still have to type something like git push masterrev.

    [remote "origin"]
        url = ssh://gerritserver/product
        fetch = +refs/heads/*:refs/remotes/origin/*
    [remote "masterrev"]
        url = ssh://gerritserver/product
        fetch = +refs/heads/*:refs/remotes/origin/*
        push = HEAD:refs/for/master

The only equivalent I know to provide your original goal is with 3rd party tools like the git-review tool that the OpenStack developers put together for their own use. It might be worth it if your team is planning to use gerrit, since it provides other functionality like easy access to cherry-picking or checkout of reviews.

As an aside, I believe the push.default setting of "current" means just to assume that the local branch name(s) should be pushed through the remote.*.push modification even if they aren't already known to exist on the server. It does not limit which branches are pushed to just the "current" one, but rather to use the "current" name(s).

Semasiology answered 22/10, 2018 at 14:46 Comment(5)
I did consider changing the push behaviour to only push the necessary branch but hadn't considered using a separate remote. That would fix several of the issues I had with that approach... I will see how this works and get back to you.Autocrat
Unfortunately the url contains each employees id in it (to log into the server) and the branch to push to will change every release since we don't use a master branch. So the config file would be different for each member and the branch to push to would change every release. Thanks for the info and I will look into git-review.Autocrat
Mild warning: the initial setup instructions for git-review imply you have to put it's settings in a .gitreview config file, but you can also put them in your git config, which may be better for your usage, depending on whether you want the config to be part of the repo or not.Semasiology
I didn't get the seamless simple solution I was hoping for but I guess that's a pretty good indication it doesn't exist (or at least isn't that simple). Thank you for your answer, it wasn't what I was hoping for but "can't be done with just git currently" is what I got.Autocrat
What I finalized on is to add a remote called 'gerrit' which only defines url and push as HEAD:refs/for/VERSION which will work for my team, thanks for suggesting separate remote, git push gerrit works great!Autocrat

© 2022 - 2024 — McMap. All rights reserved.