Git Practices

Version control workflows and conventions

Modified

February 1, 2026

Intermediate 12 min read Git Phase 3: Workflows

Overview

Git is essential for collaborative research. This guide covers:

  1. Commits - Saving snapshots of your work
  2. Branches - Working on features in isolation
  3. Issues - Tracking tasks, bugs, and ideas
  4. Pull Requests - Proposing and reviewing changes

Branch Protection Policy

ImportantPRs Required for Lab Documentation

The lab-handbook repository has branch protection enabled. You cannot push directly to main. All changes must go through a pull request with at least one approval.

This applies to Computing guides, Learning materials, and all other documentation.

Why PRs for Documentation?

  1. Quality control - Another set of eyes catches errors and unclear writing
  2. Learning opportunity - Review feedback helps improve technical writing
  3. Transparency - Changes are visible and discussed before merging
  4. Reversibility - Easy to track what changed and why

Quick Workflow for Documentation Changes

# 1. Create a branch for your changes
git checkout main
git pull origin main
git checkout -b docs/update-computing-guide

# 2. Make your edits
# ... edit files ...

# 3. Commit your changes
git add computing/index.qmd
git commit -m "docs: clarify Slurm partition guidelines"

# 4. Push and create PR
git push -u origin docs/update-computing-guide
gh pr create --title "Clarify Slurm partition guidelines" --body "
## Summary
Added clearer guidance on when to use each Slurm partition.

## Changes
- Added decision flowchart for partition selection
- Clarified memory limits for bigmem partition
"

Then request review from Dr. Rashid or another lab member. Once approved, merge via GitHub.

Issues vs Pull Requests

Understanding the difference between issues and pull requests is crucial for effective collaboration.

Issues: Planning and Discussion

Issues are for planning, discussion, and tracking work before or independent of code changes.

Use issues to:

  • Report bugs (“The power calculation returns NA when n < 10”)
  • Request features (“Add support for competing risks”)
  • Ask questions (“Should we use Weibull or exponential?”)
  • Track tasks (“Implement Section 3 simulations”)
  • Document decisions (“We decided to use LHS over Sobol”)

Issue lifecycle:

Open → Discussion → Assigned → In Progress → Closed (by PR or manually)

Example issue:

## Bug: Confidence intervals incorrect for small samples

### Description
When sample size is < 20, the confidence interval calculation
in `calculate_ci()` returns intervals that don't contain the
point estimate.

### Steps to Reproduce
1. Run `calculate_ci(data[1:15, ])`
2. Observe that `lower > estimate`

### Expected Behavior
Lower bound should always be ≤ estimate ≤ upper bound.

### Environment
- R 4.3.0
- Package version: 0.2.1

Pull Requests: Proposing Code Changes

Pull requests (PRs) are for proposing specific code changes and getting them reviewed before merging.

Use PRs to:

  • Submit new features for review
  • Fix bugs (often linked to an issue)
  • Update documentation
  • Refactor code

PR lifecycle:

Create Branch → Make Changes → Open PR → Review → Revise → Approve → Merge

Key difference: Issues are conversations about work. PRs are the work itself ready for review.

When to Use Which

Scenario Use
“I found a bug” Issue
“Here’s the fix for that bug” Pull Request
“We should add feature X” Issue (for discussion)
“I implemented feature X” Pull Request
“Question about the API design” Issue
“Updated the API per our discussion” Pull Request
“Task: run sensitivity analysis” Issue
“Results of sensitivity analysis” Pull Request

Linking Issues and PRs

Connect PRs to the issues they address:

## Summary
Fix confidence interval calculation for small samples.

Fixes #42
Closes #42
Resolves #42

Any of these keywords automatically closes the issue when the PR is merged.

GitHub Issues In-Depth

Creating Effective Issues

Good issue titles:

  • “Bug: Power calculation fails for n < 10”
  • “Feature: Add bootstrap confidence intervals”
  • “Docs: Update installation instructions for M1 Macs”

Bad issue titles:

  • “It doesn’t work”
  • “Question”
  • “Help”

Issue Templates

Create .github/ISSUE_TEMPLATE/bug_report.md:

---
name: Bug Report
about: Report a bug or unexpected behavior
---

## Description
A clear description of the bug.

## Steps to Reproduce
1. Step one
2. Step two
3. See error

## Expected Behavior
What should happen.

## Actual Behavior
What actually happens.

## Environment
- R version:
- OS:
- Package version:

## Additional Context
Screenshots, error messages, etc.

Using Labels

Organize issues with labels:

Label Purpose
bug Something isn’t working
enhancement New feature request
documentation Documentation improvements
question Questions or discussion
good first issue Good for newcomers
priority: high Needs immediate attention
status: in progress Currently being worked on

Milestones

Group issues by milestone (e.g., “v1.0 Release”, “JASA Submission”):

# View issues for a milestone
gh issue list --milestone "v1.0"

Pull Requests In-Depth

The PR Workflow

1. Create a Branch

# Start from updated main
git checkout main
git pull origin main

# Create feature branch
git checkout -b feat/add-bootstrap-ci

# Or fix branch
git checkout -b fix/small-sample-ci

2. Make Changes

# Work on your changes
# ... edit files ...

# Commit frequently with clear messages
git add R/confidence_intervals.R
git commit -m "fix: handle small sample sizes in CI calculation"

git add tests/test-ci.R
git commit -m "test: add tests for small sample CI edge cases"

3. Push to GitHub

# First push: set upstream
git push -u origin feat/add-bootstrap-ci

# Subsequent pushes
git push

4. Open the PR

Via GitHub web interface:

  1. Go to repository on GitHub
  2. Click “Pull requests” → “New pull request”
  3. Select your branch
  4. Fill in the template
  5. Click “Create pull request”

Via command line:

# Open PR with title and body
gh pr create --title "Fix CI calculation for small samples" --body "
## Summary
Fixes confidence interval calculation when n < 20.

## Changes
- Added sample size check in calculate_ci()
- Return NA with warning for n < 5
- Added unit tests for edge cases

## Testing
- All existing tests pass
- Added 3 new tests for small sample behavior

Fixes #42
"

5. Request Review

# Request specific reviewers
gh pr edit --add-reviewer username

# Or via web interface

6. Address Feedback

Reviewers may request changes:

# Make requested changes
# ... edit files ...

# Commit with clear message
git add .
git commit -m "fix: address review feedback - add input validation"

# Push updates (PR automatically updates)
git push

7. Merge

Once approved:

# Merge via CLI
gh pr merge --squash

# Or via web interface: click "Merge pull request"

Writing Good PR Descriptions

Structure:

## Summary
One paragraph explaining what this PR does and why.

## Changes
- Bullet point list of specific changes
- Be concrete: "Added X" not "Updated stuff"

## Testing
How did you verify this works?
- "Ran test suite: all 47 tests pass"
- "Manually tested with example data"
- "Verified output matches expected in #42"

## Screenshots (if applicable)
For UI changes or visualizations.

## Checklist
- [ ] Code follows style guide
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] No hardcoded paths

## Related Issues
Fixes #42
Related to #38

PR Review Guidelines

As a reviewer:

  1. Be constructive - Suggest improvements, don’t just criticize
  2. Be specific - Point to exact lines, suggest fixes
  3. Prioritize - Distinguish blocking issues from suggestions
  4. Test it - Pull the branch and run the code

Review comment prefixes:

Prefix Meaning
blocking: Must fix before merge
suggestion: Nice to have, not required
question: Need clarification
nit: Minor style issue

Example review comments:

blocking: This will fail if `data` is NULL. Add a check:
```r
if (is.null(data)) stop("data cannot be NULL")

suggestion: Consider using vapply instead of sapply for type safety.

question: Why did we choose 0.05 as the threshold here?

nit: Extra whitespace on line 42.


**As the author:**

1. **Respond to all comments** - Even if just "Done" or "Good point, fixed"
2. **Don't take it personally** - Reviews improve code quality
3. **Ask for clarification** - If feedback is unclear
4. **Push fixes** - Then re-request review

### Review Expectations

**Timeline:**

| PR Size | Expected Review Time |
|---------|---------------------|
| Small (< 100 lines) | Within 2 business days |
| Medium (100-500 lines) | Within 4 business days |
| Large (500+ lines) | Within 1 week |

**Tips for faster reviews:**

- Keep PRs small and focused (one feature/fix per PR)
- Write clear descriptions explaining *why*
- Include screenshots for visual changes
- Run tests before requesting review
- Tag appropriate reviewers (not everyone)

**If your PR is blocking:**

1. Add `priority: high` label
2. Message reviewer directly in Teams
3. Ask in lab meeting if urgent

**If you're asked to review:**

1. Acknowledge within 24 hours (even if you need more time)
2. If you can't review in time, say so and suggest someone else
3. Be thorough but timely—perfect shouldn't block good

### Draft PRs

Open a draft PR for early feedback before code is ready:

```bash
gh pr create --draft --title "WIP: Bootstrap confidence intervals"

Use drafts for:

  • Getting early feedback on approach
  • Showing progress on long-running work
  • Discussing design before finishing implementation

Convert to ready when done:

gh pr ready

Merge Strategies

Strategy When to Use
Merge commit Preserve full history (default)
Squash and merge Clean history, combine all commits into one
Rebase and merge Linear history, replay commits on main

Lab default: Squash and merge for clean history.

Complete Workflow Example

Scenario: Fix a bug reported in an issue

1. Issue exists: #42 “CI calculation wrong for small n”

2. Assign yourself and start work:

# On GitHub: assign yourself to #42
# Or via CLI:
gh issue edit 42 --add-assignee @me

# Create branch
git checkout main
git pull origin main
git checkout -b fix/small-sample-ci-42

3. Make the fix:

# Edit the code
# ... fix R/confidence_intervals.R ...

# Add tests
# ... edit tests/test-ci.R ...

# Commit
git add R/confidence_intervals.R
git commit -m "fix: handle n < 20 in CI calculation"

git add tests/test-ci.R
git commit -m "test: add small sample CI tests"

4. Push and create PR:

git push -u origin fix/small-sample-ci-42

gh pr create --title "Fix CI calculation for small samples" --body "
## Summary
Fixes confidence interval calculation for sample sizes under 20.

## Changes
- Added sample size validation in calculate_ci()
- Returns NA with warning for n < 5
- Uses t-distribution instead of normal for n < 30

## Testing
- Added 3 new tests covering edge cases
- All 50 tests pass

Fixes #42
"

5. Get review and iterate:

# Reviewer requests changes
# Make fixes
git add .
git commit -m "fix: address review - improve error message"
git push

# Re-request review
gh pr edit --add-reviewer reviewer-username

6. Merge:

# After approval
gh pr merge --squash

# Clean up local branch
git checkout main
git pull origin main
git branch -d fix/small-sample-ci-42

7. Issue #42 is automatically closed by the merge.

Commit Messages

Use conventional commit format:

type: short description

Longer explanation if needed.

Closes #issue_number

Types

Type Use Case
feat New feature
fix Bug fix
docs Documentation only
style Formatting, no code change
refactor Code restructuring
test Adding tests
chore Maintenance tasks

Examples

# Good commits
git commit -m "feat: add Cox model with time-varying covariates"
git commit -m "fix: correct confidence interval calculation"
git commit -m "docs: add installation instructions"

# Bad commits
git commit -m "updates"
git commit -m "fixed stuff"
git commit -m "WIP"

Branching Strategy

Main Branches

  • main - Production-ready code, always stable
  • develop - Integration branch for features (optional)

Branch Naming

feat/description      # New features
fix/description       # Bug fixes
docs/description      # Documentation
refactor/description  # Code restructuring

Include issue number when applicable:

fix/small-sample-ci-42
feat/bootstrap-intervals-38

Common Commands

Daily Workflow

# Start of day: get latest changes
git checkout main
git pull origin main

# Create branch for new work
git checkout -b feat/my-feature

# Check status
git status

# Stage changes
git add filename.R
git add -A  # All changes (use sparingly)

# Commit
git commit -m "type: description"

# Push
git push -u origin feat/my-feature

GitHub CLI (gh) Commands

# Issues
gh issue list                    # List open issues
gh issue create                  # Create new issue
gh issue view 42                 # View issue #42
gh issue close 42                # Close issue

# Pull Requests
gh pr list                       # List open PRs
gh pr create                     # Create PR
gh pr view 15                    # View PR #15
gh pr checkout 15                # Check out PR branch
gh pr merge --squash             # Merge current PR
gh pr review --approve           # Approve PR

# Combined workflow
gh issue develop 42 --checkout   # Create branch for issue

Viewing History

# View log
git log --oneline -10

# View specific file history
git log --follow -p -- filename.R

# View changes
git diff
git diff --staged

Undoing Changes

# Discard unstaged changes
git checkout -- filename.R

# Unstage file
git reset HEAD filename.R

# Amend last commit (before push)
git commit --amend -m "new message"

# Revert a commit (creates new commit)
git revert commit_hash

Handling Conflicts

# When pull has conflicts
git pull origin main
# Edit conflicted files, remove markers (<<<<, ====, >>>>)
git add conflicted_file.R
git commit -m "fix: resolve merge conflict"

.gitignore

Essential entries for R projects:

# R
.Rhistory
.Rdata
.RDataTmp
*.Rproj.user/

# Targets
_targets/
_targets_r/

# Data (usually)
data/raw/
*.csv
*.rds

# Results (regenerable)
results/
figures/

# Secrets
.env
config/secrets.yml

# OS
.DS_Store
Thumbs.db

Sensitive Data

Never commit:

  • Passwords or API keys
  • Patient data or PHI
  • Unpublished results
  • Personal credentials

Use .env files with .gitignore:

# .env (gitignored)
API_KEY=secret_key_here
DB_PASSWORD=password_here
# In R
Sys.setenv(API_KEY = "secret")  # Or use dotenv package
api_key <- Sys.getenv("API_KEY")

Repository Hygiene

Regular Maintenance

# Remove merged branches
git branch --merged | grep -v main | xargs git branch -d

# Prune remote tracking branches
git fetch --prune

# Check repository size
git count-objects -vH

Before Major Changes

# Create backup branch
git checkout -b backup/before-refactor
git checkout main

Claude Code Git Workflow

Claude Code can manage your git workflow directly.

Common Operations

> What's the git status?
> Create a branch called feature/bootstrap
> Show me what changed in the last commit

Commit Workflow

Use the /commit skill for a streamlined workflow:

> /commit

Claude will: 1. Show staged and unstaged changes 2. Suggest a commit message following lab conventions 3. Create the commit with your approval

Code Review

Use /review before committing to catch issues:

> /review

Claude checks for logic errors, security issues, and lab standard violations.

See Claude Code Guide for more on git integration.