I'm setting up Git with Gerrit Code Review and am looking for a way to make the necessary Git commands relatively straightforward for users who might be new to Git.
The commands I currently have for starting a new feature branch are essentially (assuming Gerrit is origin
):
git checkout baseline
git pull
git checkout -b work1234
git push -u origin work1234
This starts a new work package work1234
branched from some baseline
, and the final push creates the branch in Gerrit and sets the upstream. So .git/config
looks something like:
[branch "work1234"]
remote = origin
merge = refs/heads/work1234
Now, Gerrit wants new commits for review to be pushed to a special refspec, refs/for/work1234
for example. I can do this manually with:
git push origin work1234:refs/for/work1234
What I would like to do is find some way to set up .git/config
so that a plain git push
will push the current branch to the refspec on the remote that Gerrit requires. I have looked at the following git config
areas:
branch.<name>.*
- doesn't seem to have any specific option for setting the push refspec
push.default
- I sort of want upstream
here
remote.<name>.push
- I tried refs/heads/*:refs/for/*
here but git push
always wants to push all local branches in this case, while I just want the current branch
If I can't make Git do this by itself, I'll write a small wrapper script that fully specifies the refspecs. However, it would be better if Git could push to the right place natively.
I ended up writing a new git-submit
script:
#!/bin/sh -e
if [ -z "$1" ]; then
REMOTE=origin
else
REMOTE=$1
fi
BRANCH=`git symbolic-ref HEAD`
case $BRANCH in
refs/heads/*)
BRANCH=`basename $BRANCH`
;;
*)
echo "I can't figure out which branch you are on."
exit 1
;;
esac
git push $REMOTE HEAD:refs/for/$BRANCH
I put this script in /usr/local/libexec/git-core/git-submit
and now there's one command to submit new code to Gerrit for review:
$ git submit
If Gerrit is not the origin
remote, then use git submit <remote>
as appropriate.
Two options I've found:
1) Check out a project I made, ggh: https://github.com/hobbs/ggh
2) You can configure the default push refspec in your remote. I've only figured out how to do this with a hardcoded remote branch, still trying to figure out how to wildcard the remote refspec so that it always pushes to the remote you're tracking:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = ssh://gerrit/repo
push = HEAD:refs/for/master
Here is an improvement of Greg Hewgill answer.
Create a script somewhere on the path, like on your profile bin folder (create one if necessary, even on Windows):
$ mkdir ~/bin
$ vi ~/bin/git-submit
With the following content:
#!/bin/sh -e
if [ -z "$1" ]; then
REMOTE=origin
else
REMOTE=$1
fi
BRANCH=`git symbolic-ref HEAD`
case $BRANCH in
refs/heads/*)
BRANCH=`basename $BRANCH`
;;
*)
echo "I can't figure out which branch you are on."
exit 1
;;
esac
REMOTE_BRANCH=`git config --get "branch.$BRANCH.merge"`
if [ -z $REMOTE_BRANCH ]
then
echo "There is no tracking information for the current branch."
echo "If you wish to set tracking information for this branch you can do so with:"
echo ""
echo " git branch --set-upstream $BRANCH <remote>/<branch>"
echo ""
exit 1
fi
git push $REMOTE HEAD:refs/for/$REMOTE_BRANCH
Supposing you create a remote tracking branch like:
$ git checkout -b MyBranch origin/master
You can simply call:
$ git submit
... to push to refs/for/master
in this case.
git config push.default upstream
git config branch.work1234.merge refs/for/work1234
git config branch.work1234.remote origin
or .git/config:
[push]
default = upstream
[branch "work1234"]
merge = refs/for/work1234
remote = origin
I'm not sure if there's a way to put a wildcard in there anywhere to make it work for all branches.