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

From mediawiki.org

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

How to work effectively with git/gerrit[edit]

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[edit]

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[edit]

  • 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[edit]

Start work on a local branch for some new feature

(Assuming your local master has the latest changes, see later.)

git checkout master
git pull --ff-only
git checkout -b my/newawesome -t gerrit/master

This creates a new my/newawesome work branch that tracks gerrit/master, and checks it out.

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_stuffif you're l33t) and create a new local branch my/fixthing just for that.

Several times a day get the latest changes from gerrit

git commit your local work, then

git checkout master
git pull --ff-only           # means fast-foward changes only.

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.

git rebase master your work branch periodically

gerrit[edit]

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:

git checkout master
git checkout -b feature/newawesome -t origin/master
git merge --squash my/newawesome

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[edit]

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,

git checkout feature/newawesome
git merge --squash my/newawesome
git commit --amend

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[edit]

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[edit]

  • 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.
git checkout master
git branch --delete my/newawesome
git branch --delete feature/newawesome

git will warn if the local branch "is not fully merged", so this is safe to do.

Editorial[edit]

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[edit]

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 defaultbranch=bigfeature, and commit - review - +2 this change to the branch.