CtrlK
BlogDocsLog inGet started
Tessl Logo

odyssey4me/gerrit

Submit, amend, and review Gerrit changes using git-review CLI. Use when asked to submit a patchset, download a change, rebase a change request, check CR status, or manage code reviews in Gerrit.

94

Quality

94%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Skills
Evals
Files

common-workflows.mdreferences/

Common Gerrit Workflows with git-review

This document provides practical examples of common Gerrit code review workflows using git-review.

Table of Contents

  • Getting Started
  • Submitting Changes
  • Reviewing Changes
  • Working with Patchsets
  • Topics and Dependencies
  • Advanced Workflows
  • SSH Commands
  • Automation Examples

Getting Started

Initial Repository Setup

# Clone repository
git clone ssh://review.example.com:29418/myproject
cd myproject

# Setup git-review (one-time)
git review -s

# Verify setup
cat .gitreview

Configure Commit Hook

# Install commit-msg hook for Change-Id generation
git review -s

# Verify hook is installed
ls -l .git/hooks/commit-msg

# Test with a commit
git commit --allow-empty -m "test: verify Change-Id generation"
git log -1
# Should see "Change-Id: I..." in commit message

Submitting Changes

Basic Submission Workflow

# Create feature branch
git checkout -b feature/new-api
git checkout main

# Make changes
vim api/endpoints.py

# Commit with descriptive message
git commit -m "Add new API endpoint for user profiles

This adds a REST endpoint that returns user profile data.

Change-Id: Ixxx  # Auto-generated by commit hook
"

# Submit for review
git review

Submit with Topic

# Group related changes under a topic
git commit -m "Part 1: Add user model"
git review -t user-profile-feature

# Additional changes in same topic
git checkout main
git checkout -b feature/user-api
# ... make changes ...
git commit -m "Part 2: Add user API"
git review -t user-profile-feature

Submit with Reviewers

# Add reviewers when submitting
git review --reviewers alice@example.com,bob@example.com

# Add reviewers for specific areas
git review \
  --reviewers backend-team@example.com \
  --reviewers security-team@example.com

Submit Draft/WIP Changes

# Submit as work-in-progress
git review -D

# Later, publish the change via Gerrit web UI
# or use SSH:
ssh -p 29418 review.example.com gerrit review 12345 --publish

Dry-Run Before Submitting

# See what would be submitted
git review -n

# Review the output, then submit
git review

Reviewing Changes

Download Change for Review

# Download specific change
git review -d 12345

# This creates branch: review/username/topic
git branch
# * review/alice/user-api
#   main

# Review the code
git log -p HEAD^..HEAD
git diff main..HEAD

# Test the change
make test
python -m pytest

# Return to main
git checkout main

Download Specific Patchset

# Download patchset 3 of change 12345
git review -d 12345,3

# Compare patchsets
git review -d 12345,2
PATCHSET_2=$(git rev-parse HEAD)
git review -d 12345,3
git diff $PATCHSET_2..HEAD

Cherry-pick for Quick Testing

# Apply change without creating branch
git checkout main
git review -x 12345

# Now the change is on main (don't push!)
# Test it
make test

# Discard when done
git reset --hard origin/main

Compare Changes

# Compare your local work to remote change
git review -m 12345

# Shows diff between your changes and the review

Working with Patchsets

Update Your Change

# Download your change
git review -d 12345

# Make requested changes
vim api/endpoints.py

# Amend the commit (preserves Change-Id)
git commit --amend

# Upload new patchset
git review

Rebase on Latest Main

# Download your change
git review -d 12345

# Rebase on latest main
git fetch origin
git rebase origin/main

# Upload rebased patchset
git review

Submit Without Rebase

# Submit exactly as-is (no rebase)
git review -R

# Useful when you've carefully tested specific commits

Split a Change

# Download the change
git review -d 12345

# Reset to split commits
git reset HEAD^

# Create first commit
git add file1.py
git commit -m "Part 1: Add data model"
git review -t feature-name

# Create second commit
git add file2.py
git commit -m "Part 2: Add API endpoint"
git review -t feature-name

Squash Multiple Commits

# If you have multiple commits that should be one
git rebase -i HEAD~3

# In editor, change:
#   pick abc123 commit 1
#   pick def456 commit 2
#   pick ghi789 commit 3
# To:
#   pick abc123 commit 1
#   squash def456 commit 2
#   squash ghi789 commit 3

# Upload squashed change
git review

Topics and Dependencies

Create Topic Chain

# First change in series
git checkout main
git checkout -b feature/step1
# ... make changes ...
git commit -m "Step 1: Add database schema"
git review -t multi-step-feature

# Second change (depends on first)
git checkout -b feature/step2
# ... make changes ...
git commit -m "Step 2: Add API endpoint"
git review -t multi-step-feature

# Third change
git checkout -b feature/step3
# ... make changes ...
git commit -m "Step 3: Add UI components"
git review -t multi-step-feature

Update Change in Chain

# Download the middle change
git review -d 12346

# Make updates
git commit --amend

# Rebase dependent changes
git review

# Update dependent changes too
git review -d 12347
git rebase review/user/step2
git review

View All Changes in Topic

# Query changes by topic
ssh -p 29418 review.example.com \
  gerrit query topic:multi-step-feature status:open

# Or via web:
# https://review.example.com/#/q/topic:multi-step-feature

Advanced Workflows

Work on Multiple Changes

# Create multiple independent changes
git checkout main
git checkout -b feature/change1
# ... work ...
git commit -m "Add feature 1"
git review

git checkout main
git checkout -b feature/change2
# ... work ...
git commit -m "Add feature 2"
git review

# List local review branches
git branch | grep review/

Recover from Mistakes

# Forgot to amend, created new change instead
# Download the wrong new change
git review -d 12347

# Check both commits
git log -2 --oneline

# Squash them
git rebase -i HEAD~2
# Mark second commit as 'squash'

# Upload corrected change
git review

Backport to Release Branch

# Download change from main
git review -d 12345

# Create backport branch
git checkout -b backport/stable-2.1 origin/stable/2.1

# Cherry-pick the change
git cherry-pick review/user/feature

# Resolve conflicts if needed
# ... fix conflicts ...
git add .
git cherry-pick --continue

# Submit to stable branch
git review

Finish and Clean Up

# Submit and clean up local branch
git review -f

# This does:
# 1. Submits the change
# 2. Deletes local branch
# 3. Switches back to main

SSH Commands

Query Changes

# List open changes
ssh -p 29418 review.example.com gerrit query status:open

# List your changes
ssh -p 29418 review.example.com gerrit query owner:self status:open

# Find changes by topic
ssh -p 29418 review.example.com gerrit query topic:feature-name

# Complex query
ssh -p 29418 review.example.com gerrit query \
  'project:myproject AND status:open AND -age:7d'

# Get JSON output
ssh -p 29418 review.example.com gerrit query \
  --format=JSON status:open project:myproject

Review from Command Line

# Approve change
ssh -p 29418 review.example.com gerrit review \
  12345,3 --verified +1 --code-review +2 --message "'LGTM!'"

# Request changes
ssh -p 29418 review.example.com gerrit review \
  12345,3 --code-review -1 --message "'Please fix the error handling'"

# Submit change
ssh -p 29418 review.example.com gerrit review \
  12345,3 --submit

Abandon/Restore Changes

# Abandon change
ssh -p 29418 review.example.com gerrit review \
  12345 --abandon --message "'No longer needed'"

# Restore change
ssh -p 29418 review.example.com gerrit review \
  12345 --restore --message "'Actually still needed'"

Manage Topics

# Set topic
ssh -p 29418 review.example.com gerrit set-topic \
  12345 feature-name

# Remove topic
ssh -p 29418 review.example.com gerrit set-topic \
  12345 ""

Automation Examples

Daily Review Queue

#!/bin/bash
# Check your review queue each morning

echo "=== Changes Waiting for Your Review ==="
ssh -p 29418 review.example.com gerrit query \
  --format=JSON \
  'status:open AND reviewer:self -owner:self' | \
  jq -r 'select(.number != null) | "  #\(.number): \(.subject) (@\(.owner.username))"'

echo -e "\n=== Your Changes Needing Attention ==="
ssh -p 29418 review.example.com gerrit query \
  --format=JSON \
  'status:open AND owner:self' | \
  jq -r 'select(.number != null) | "  #\(.number): \(.subject) (Score: \(.currentPatchSet.approvals[0].value // "not reviewed"))"'

Auto-sync with Latest Changes

#!/bin/bash
# Update all local review branches

for branch in $(git branch | grep review/); do
  echo "Updating $branch..."
  git checkout $branch

  # Fetch latest patchset
  CHANGE_NUM=$(git log -1 --format=%B | grep -oP 'Change-Id: I\K[a-f0-9]+' | head -1)

  if [ -n "$CHANGE_NUM" ]; then
    # Find change number from Change-Id
    NUM=$(ssh -p 29418 review.example.com gerrit query \
      --format=JSON change:I$CHANGE_NUM | \
      jq -r 'select(.number != null) | .number')

    if [ -n "$NUM" ]; then
      git review -d $NUM
    fi
  fi
done

git checkout main

Submit Change Chain

#!/bin/bash
# Submit multiple changes in order

TOPIC="feature-name"

# Get all changes in topic, sorted by number
ssh -p 29418 review.example.com gerrit query \
  --format=JSON topic:$TOPIC status:open | \
  jq -r 'select(.number != null) | .number' | \
  sort -n | \
  while read num; do
    echo "Reviewing change $num..."

    # Download and test
    git review -d $num

    # Run tests
    if make test; then
      echo "Tests passed for $num"

      # Approve via SSH
      ssh -p 29418 review.example.com gerrit review \
        $num --verified +1 --message "'Automated verification passed'"
    else
      echo "Tests failed for $num - stopping"
      break
    fi
  done

git checkout main

Monitor Change Status

#!/bin/bash
# Monitor specific change for updates

CHANGE_NUM=$1
INTERVAL=${2:-60}  # Check every 60 seconds

echo "Monitoring change $CHANGE_NUM..."

LAST_UPDATED=""
while true; do
  INFO=$(ssh -p 29418 review.example.com gerrit query \
    --format=JSON $CHANGE_NUM)

  UPDATED=$(echo "$INFO" | jq -r '.lastUpdated')
  STATUS=$(echo "$INFO" | jq -r '.status')

  if [ "$UPDATED" != "$LAST_UPDATED" ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Change $CHANGE_NUM updated - Status: $STATUS"

    # Show latest comments
    echo "$INFO" | jq -r '.comments[]? | "  \(.reviewer.username): \(.message)"'

    LAST_UPDATED=$UPDATED

    # Exit if merged or abandoned
    if [ "$STATUS" = "MERGED" ] || [ "$STATUS" = "ABANDONED" ]; then
      echo "Change $STATUS - exiting monitor"
      break
    fi
  fi

  sleep $INTERVAL
done

Generate Weekly Report

#!/bin/bash
# Weekly activity report

WEEK_AGO=$(date -d '7 days ago' '+%Y-%m-%d')

echo "=== Gerrit Activity Report (last 7 days) ==="

echo -e "\nChanges Merged:"
ssh -p 29418 review.example.com gerrit query \
  --format=JSON \
  "status:merged AND after:$WEEK_AGO" | \
  jq -r 'select(.number != null) | "  #\(.number): \(.subject) (@\(.owner.username))"'

echo -e "\nChanges Abandoned:"
ssh -p 29418 review.example.com gerrit query \
  --format=JSON \
  "status:abandoned AND after:$WEEK_AGO" | \
  jq -r 'select(.number != null) | "  #\(.number): \(.subject) (@\(.owner.username))"'

echo -e "\nActive Changes (still open):"
ssh -p 29418 review.example.com gerrit query \
  --format=JSON \
  "status:open AND after:$WEEK_AGO" | \
  jq -r 'select(.number != null) | "  #\(.number): \(.subject) (@\(.owner.username))"'

Tips for Efficient Workflows

Git Aliases

Add to ~/.gitconfig:

[alias]
    # git-review shortcuts
    gr = review
    grd = review -d
    grx = review -x
    grf = review -f
    grn = review -n

Usage:

git gr              # Submit review
git grd 12345       # Download change
git grx 12345       # Cherry-pick change
git grf             # Submit and finish

Bash Functions

Add to ~/.bashrc:

# Download and checkout Gerrit change
gr() {
  git review -d "$1"
}

# Query Gerrit changes
gq() {
  ssh -p 29418 review.example.com gerrit query "$@"
}

# Review from command line
gapprove() {
  ssh -p 29418 review.example.com gerrit review \
    "$1" --verified +1 --code-review +2 --message "'$2'"
}

# List my open changes
mychanges() {
  ssh -p 29418 review.example.com gerrit query \
    --format=JSON 'owner:self status:open' | \
    jq -r 'select(.number != null) | "\(.number)\t\(.subject)"'
}

Environment Variables

# Set Gerrit username
export GERRIT_USER=myusername

# Create wrapper for SSH
gerrit() {
  ssh -p 29418 $GERRIT_USER@review.example.com gerrit "$@"
}

# Usage:
gerrit query status:open
gerrit review 12345 --code-review +2

Pre-push Hook

Validate before pushing to Gerrit:

# .git/hooks/pre-push
#!/bin/bash

# Check for Change-Id
if ! git log -1 --format=%B | grep -q '^Change-Id:'; then
  echo "Error: Missing Change-Id in commit message"
  echo "Run: git review -s (to install commit-msg hook)"
  exit 1
fi

# Run tests
if ! make test; then
  echo "Error: Tests failed"
  exit 1
fi

exit 0
chmod +x .git/hooks/pre-push

Additional Resources

Install with Tessl CLI

npx tessl i odyssey4me/gerrit

references

advanced-usage.md

common-workflows.md

permissions.md

troubleshooting.md

SKILL.md

tile.json