Git Workflow Helper
Common git operations for working with INAV repositories.
🚨 Read Git Guidelines First
Before any git commit operation, read: claude/developer/guides/CRITICAL-BEFORE-COMMIT.md
This checklist covers:
- Never use
git add -A - Human review of commit messages
- Commit message format and best practices
- When to use (and not use)
--amend - Hook handling
Read it now using the Read tool when performing commit operations.
⚠️ CRITICAL: Git Safety Rules ⚠️
Questions Are Not Commands
When the user asks a question, ONLY answer the question.
- Do NOT take any action (delete, push, modify, etc.)
- Do NOT "fix" things while explaining them
- Do NOT assume you know what action should follow
- WAIT for explicit instructions before doing anything
Never Destroy Evidence During Investigation
When investigating a problem or answering questions about repository state:
- Do NOT delete branches, tags, or commits
- Do NOT push, force-push, or overwrite anything
- Do NOT "clean up" anything
- PRESERVE the current state so it can be examined
- The evidence is needed to understand and fix the problem
Never Alter the Public Record
Once something is pushed to a public/shared repository:
- It becomes part of the permanent record
- Other developers around the world may have fetched it
- Altering it (force push, amend+push) creates problems for EVERYONE
- It breaks other developers' local repositories
- It corrupts CI/CD pipelines, PR references, and git history
- The damage is often irreversible and far-reaching
Force pushing after a PR is merged corrupts GitHub's PR display:
- GitHub's "Files changed" tab shows the diff between base and the CURRENT branch head
- If you force push after merge, the PR now shows DIFFERENT code than what was actually merged
- Example: PR #2496 actually merged an
afterCopyhook, but after force push GitHub showspostPackage - Anyone reviewing the PR history sees FALSE information about what was merged
- This makes debugging, auditing, and understanding project history impossible
- The merge commit in master contains the ORIGINAL code, but the PR display shows the AMENDED code
- This is a permanent corruption of the project's historical record
Force Push Rules
NEVER, EVER force push to master, main, or any shared branch:
# ❌ ABSOLUTELY FORBIDDEN - NEVER DO THIS:
git push -f origin master
git push --force origin main
git push -f upstream master
# These commands DESTROY other people's work permanently
# They rewrite history and can cause unrecoverable data loss
If a regular push is rejected:
- STOP immediately
- Do
git pullto merge remote changes - Or ask the user what to do
- NEVER use force push to "fix" it
Force push is ONLY acceptable:
- On your own feature branches that nobody else uses
- When explicitly requested by the user
- NEVER on master/main/shared branches under any circumstances
🔒 Sandbox Restrictions
Claude Code runs in a sandbox that restricts network access:
- Git operations requiring network (fetch, pull, push) may fail with "Network is unreachable" or "Connection refused"
- This is NOT a network outage - it's the sandbox blocking unapproved network operations
- SSH to github.com (port 22) is in the allowed list but may require permission prompts
- If git fetch/pull/push fails, the user needs to approve the network operation or run it manually
When you see network errors:
- Don't assume the network is down
- Recognize it as a sandbox restriction
- Ask the user if they want to approve the operation or handle it manually
- The user can run git commands directly (unsandboxed) if needed
One approved exception: plain git push to origin (NEVER force-push). github.com
and ssh.github.com are in the sandbox allowlist, so pushes normally work sandboxed;
if the sandbox still blocks a push, retrying that one command with
dangerouslyDisableSandbox: true is approved. Do not generalize this to any other
operation — everything else follows the recognize-and-ask steps above.
Repository Structure
The INAV project consists of three standalone repositories:
inav/- Flight controller firmware (C/C99)inav-configurator/- Desktop GUI (JavaScript/Electron)inavwiki/- Documentation (Markdown)
Each repository has its own git history and must be managed independently.
Creating Branches
🚨 CRITICAL: Always Specify Base Branch When Creating Branches — This Is the Single Authority
This section is the single authoritative source for the {repo, change-type} → base-branch decision. Every other guide, skill, and README that mentions a base branch should point here (or at the script below) instead of repeating the table. If you find a stale copy elsewhere, that's a bug — fix it to be a pointer.
NEVER create a branch without specifying the base branch — branching from current HEAD may include unrelated commits, WIP changes, or simply the wrong base, contaminating the PR.
Use the script (preferred)
claude/developer/scripts/git/new-branch.sh <repo> <bugfix|feature|breaking> <branch-name> [--dry-run]
# repo: inav | inav-configurator | PrivacyLRS
It looks up the base branch below, refuses to run on a dirty tree, fetches the correct
remote, prints its reasoning, and creates the branch. Use --dry-run to preview first.
Base-branch decision table
| Repo | Remote | Change type | Base branch | Notes |
|---|---|---|---|---|
| PrivacyLRS | origin |
any | secure_01 |
Separate fork/derivative project |
| inav | upstream |
bugfix | release/9.1 |
TEMPORARY OVERRIDE — maintenance-9.x is damaged. REVIEW-BY 2027-02: verify repair before reverting to maintenance-9.x |
| inav | upstream |
feature | maintenance-10.x |
Same temporary override as above |
| inav | upstream |
breaking | maintenance-10.x |
Matches the normal (non-override) rule |
| inav-configurator | upstream |
bugfix | maintenance-9.x |
NOT affected by the inav override — configurator's maintenance-9.x is fine |
| inav-configurator | upstream |
feature | maintenance-9.x |
Not affected by the inav override |
| inav-configurator | upstream |
breaking | maintenance-10.x |
MSP protocol / settings structure changes |
NEVER target PRs to master - it receives merges only (maintenance-9.x → master → maintenance-10.x).
Manual fallback (only if the script can't be used)
git fetch <remote>
git checkout -b <branch-name> <remote>/<base-branch>
Substitute <remote> and <base-branch> from the table above. Then:
git push -u origin <branch-name>
Create Branch from Specific Commit
# Create branch from specific commit
git checkout -b bugfix-123 <commit-hash>
# Or from a tag
git checkout -b new-feature v9.0.0
Branch Naming Conventions
PrivacyLRS:
- Use flat naming WITHOUT slashes
- ✅ Good:
encryption-test-suite,fix-counter-sync,add-telemetry - ❌ Bad:
feature/encryption-tests,security/fixes
INAV:
- Use kebab-case with descriptive names
- ✅ Good:
fix-telemetry-bug,feature-battery-limit,update-sitl-binary - Bug fixes:
fix-<description> - Features:
feature-<description>
Switching Branches
Safe Branch Switching
Always check for uncommitted changes before switching:
# Check status first
git status
# If clean, switch branches
git checkout <branch-name>
# Or use switch
git switch <branch-name>
Handling Uncommitted Changes
If you have uncommitted changes:
Option 1: Stash changes
git stash save "WIP: description of changes"
git checkout <branch-name>
# Later, restore changes
git stash pop
Option 2: Commit changes
git add .
git commit -m "WIP: save progress"
git checkout <branch-name>
Option 3: Discard changes (careful!)
git checkout -- . # Discard all changes
git checkout <branch-name>
Git Status Summary
Quick Status Check
# Basic status
git status
# Short format
git status -s
# Show branch and tracking info
git status -sb
Comprehensive Status
Get a complete picture of your repository:
# Branch information
echo "=== Current Branch ==="
git branch --show-current
# Status
echo "=== Working Tree Status ==="
git status
# Commits ahead/behind remote
echo "=== Remote Tracking ==="
git status -sb | head -1
# Recent commits
echo "=== Recent Commits ==="
git log --oneline -5
# Staged changes
echo "=== Staged Changes ==="
git diff --cached --stat
# Unstaged changes
echo "=== Unstaged Changes ==="
git diff --stat
Branch Management
List Branches
# Local branches
git branch
# Remote branches
git branch -r
# All branches with last commit
git branch -v
# All branches including remote
git branch -a
Delete Branches
# Delete local branch (safe - only if merged)
git branch -d <branch-name>
# Force delete local branch
git branch -D <branch-name>
# Delete remote branch
git push origin --delete <branch-name>
Rename Branch
# Rename current branch
git branch -m <new-name>
# Rename specific branch
git branch -m <old-name> <new-name>
# Update remote
git push origin -u <new-name>
git push origin --delete <old-name>
Checking Branch Status
Compare with Remote
# Fetch latest from remote
git fetch origin
# Check if branch is ahead/behind
git status
# See commits not pushed
git log origin/<branch-name>..<branch-name>
# See commits not pulled
git log <branch-name>..origin/<branch-name>
Compare with Other Branches
# See commits in current branch not in master
git log master..HEAD
# See files changed between branches
git diff master..HEAD --stat
# Show branch divergence
git log --oneline --graph --all --decorate -10
Working with Multiple Repositories
Since inav/, inav-configurator/, and inavwiki/ are standalone repos:
Check Status Across All Repos
# From project root
for repo in inav inav-configurator inavwiki; do
if [ -d "$repo" ]; then
echo "=== $repo ==="
cd $repo
git status -sb
cd ..
echo ""
fi
done
Create Matching Branches
If working on a feature that spans multiple repos, create each from its own correct base — see the decision table above (inavwiki has no base-branch table; branch it from its default branch):
claude/developer/scripts/git/new-branch.sh inav <bugfix|feature|breaking> my-feature
claude/developer/scripts/git/new-branch.sh inav-configurator <bugfix|feature|breaking> my-feature
cd inavwiki && git checkout -b my-feature && git push -u origin my-feature
Updating the Harness Repo Itself
The root inavflight/ repo (claude/ and .claude/) is its own git repo. A
SessionStart hook (.claude/hooks/check-framework-update.sh) asks — roughly once a
month — whether to pull it. If you say yes, just run the pull the hook's own message
names: origin for this repo's own setup, or upstream if this checkout is a fork with
an upstream remote configured (that's where real framework updates land in that case;
origin would just be your own fork).
git pull --ff-only <remote> master
--ff-only refuses to create a merge commit if local and remote have diverged — if it
fails, stop and check git status/git log before doing anything else, rather than
force-merging over local changes. This is a single human-confirmed action each time the
hook asks; no automated enforcement is needed beyond that.
Common Workflows
Starting New Work
See "Creating Branches" above — use new-branch.sh or the manual fallback with the
correct base branch from the decision table. Do not branch from master; it's a
merge-only mirror, not a base.
Updating a Branch with Its Base
Rebase or merge against the same base branch you created from (from the decision
table above) — not master:
git checkout my-feature
git fetch <remote> # upstream for inav/inav-configurator, origin for PrivacyLRS
git rebase <remote>/<base-branch> # or: git merge <remote>/<base-branch>
Switching Between Tasks
# Save current work
git stash save "WIP: current task description"
# Switch to other branch
git checkout other-branch
# Work on other task...
# Return to original branch
git checkout original-branch
git stash pop
Troubleshooting
Branch is Behind Remote
# Pull latest changes
git pull origin <branch-name>
# Or fetch and merge manually
git fetch origin
git merge origin/<branch-name>
Branch Has Diverged
# View divergence
git status
# Option 1: Rebase your changes
git pull --rebase origin <branch-name>
# Option 2: Merge
git pull origin <branch-name>
Accidentally Committed to Wrong Branch
# Move last commit to new branch
git checkout -b correct-branch
git checkout wrong-branch
git reset --hard HEAD~1
git checkout correct-branch
Resources
- Git basics:
git --help - Project workflow: See
claude/manager/README.mdandclaude/developer/README.md
Related Skills
- create-pr - Create pull requests after committing changes
- pr-review - Review pull requests and check out PR branches
- check-builds - Check CI build status for branches and PRs
- start-task - Begin tasks with proper branch setup
- finish-task - Complete tasks with commits and cleanup