User:SPage (WMF)/Git & gerrit day-to-day

This should be a subpage of Git. TODO: get saper, sumanah, etc. to agree

How to work effectively with git/gerrit
You've gone through Git/Tutorial, you've read Git/Workflow (and stumbled over all the places they disagree or are subtly different), you've made a commit and maybe even got it through git review. But MediaWiki's combination of git and gerrit still causes much confusion. This document is an opinionated guide to avoiding these problems.

Reminders

 * Follow Gerrit/Workflow to set up the gerrit ssh shortcuts, and ensure that the "origin" remote is gerrit
 * Follow Gerrit/Workflow
 * Set up git review with git review -s and be sure to follow Gerrit/Tutorial so you don't wind up with two remotes "origin" and "gerrit".

Change your shell prompt to show your current branch and its state. I use a hacked http://briancarper.net/blog/570/git-info-in-your-zsh-prompt, but I use zsh not bash.

Principles

 * never work on local master
 * Always have local branches tracking gerrit/master
 * Work in local work branches, committing all the time.
 * For git review, either squash your local commits into one clean one, or create a new branch just for your fix and squash your local changes to it.

day-to-day git
(Assuming your local master has the latest changes, see later.) This creates a new my/newawesome work branch that tracks gerrit/master, and checks it out.
 * Start work on a local branch for some new feature

Now make changes. git commit each piece of progress. Don't worry about commit message formatting rules, because you're going to write a proper commit message for the beautiful orderly single change you'll submit to gerrit (see later).

If you see an unrelated change, resist the urge to fix it in my/newawesome. Instead git commit your work (or git stash save some_stuff if you're l33t) and create a new local branch my/fixthing just for that.

git commit your local work, then Don't do a bare "pull", you should assert your master can be fast-forwarded (see git-merge(1)) because you never do local work on master. The above is equivalent to the separate steps git fetch gerrit, git merge -ff-only.
 * Several times a day get the latest changes from gerrit


 * git rebase master your work branch periodically

gerrit
If you were so fortunate that the work in "my/newawesome" work branch only took a single commit, you can `git review`.

It's more likely that your "my/newawesome" work branch has lots of commits. But gerrit wants a single commit. You can run git rebase -i to squash all your changes together into one commit, then do git review. This has the downside of losing the history of your individual commits. (They'll exist for a while in your local repo, but you won't be able to find them unless you remember their SHA-1s.)

A way to keep your history is to start a new branch just to hold the one change for gerrit, and merge all your changes to it: That last step should merge your local work into this feature/newawesome as one commit, and then you can `git review` it.

The name before the / is just a convention. "my/" = local work branch, "feature/" = branch for pushing patches to gerrit.

next gerrit change
You'll probably get lots of feedback on your gerrit change that will require a Patch Set #2 (and #3, and #4).

The trick is, gerrit wants your new patch to be the same commit that you started with. Hence the instructions to use git commit --amend

Go back to your my/newawesome branch to make changes and commit often. When you're ready, This last command should bring up your previous commit to gerrit, with the change ID at the bottom that identifies it to gerrit.

Update the commit message with any significant changes you made in the new patch. Make sure the last line of the patch has the same Change ID as your first patch.

then do git review -R


 * need details
 * should I rebase locally or use the [Rebase] button

Telling reviewers what's changed in a patch
To let reviewers know what's different in a patch, you can self-review it in gerrit with +0 review and+0 verified, and in your comment explain what you changed. Reviewers can see this cover comment.

next master change
git will warn if the local branch "is not fully merged", so this is safe to do.
 * Once your gerrit change is approved, it will show up in master when you next checkout master and git pull -ff-only. So you can retire your local branches for the feature.

Editorial
It is sad that this workflow isn't clearly explained anywhere. The problem is the git experts disagree on the details (is it gerrit or origin or review that you work from? do you use pull or separate steps?) and so no shit gets clearly explained, you're just in a maze of copy-pasted best practices

Long-lived branch
Something like
 * in gerrit create bigfeature branch for your project
 * git fetch origin
 * git checkout bigfeature, recent git should automatically track it against origin
 * To ensure that when others make changes on this branch they also end up on the bigfeature branch in gerrit, edit .gitreview and set, and commit - review - +2 this change to the branch.