Last updated: May 2026·Git 2.48 · GitHub CLI 2.70 · GitHub Actions · Copilot · Codespaces · Pages
To update: ask Claude at claude.ai — "regenerate the GitHub cheat sheet"
Git 2.48 GH CLI 2.70 Actions · Pages · Packages Copilot · Codespaces Security · Dependabot
⚙️Git Setup & Config
Initial Setup
$git config --global user.name "Sir David"
$git config --global user.email "you@domain.com"
$git config --global core.editor "code --wait"
$git config --global init.defaultBranch main
$git config --global pull.rebase true
$git config --global core.autocrlf inputmacOS/Linux
$git config --global core.autocrlf trueWindows
$git config --list --show-originView all config
Aliases (time savers)
$git config --global alias.st status
$git config --global alias.co checkout
$git config --global alias.br branch
$git config --global alias.lg "log --oneline --graph --decorate --all"
$git config --global alias.undo "reset --soft HEAD~1"
SSH & GPG
$ssh-keygen -t ed25519 -C "you@domain.com"
$cat ~/.ssh/id_ed25519.pub→ paste to GitHub
$ssh -T git@github.comTest connection
$git config --global commit.gpgsign true
$git config --global gpg.program gpg
.gitignore
$curl -o .gitignore https://gitignore.io/api/node,macos
$git rm -r --cached .Untrack already tracked
📦Core Git Commands
Init & Clone
$git initInit new local repo
$git init --bareBare repo (servers)
$git clone <url>Clone repo
$git clone --depth 1 <url>Shallow clone (faster)
$git clone --branch dev <url>Clone specific branch
Stage & Commit
$git statusWorking tree status
$git diffUnstaged changes
$git diff --stagedStaged changes
$git add .Stage all
$git add -pInteractive stage (hunks)
$git add <file>Stage one file
$git commit -m "message"
$git commit --amendModify last commit
$git commit --amend --no-editAmend, keep message
Undo
$git restore <file>Discard working changes
$git restore --staged <file>Unstage file
$git reset --soft HEAD~1Undo commit, keep staged
$git reset --mixed HEAD~1Undo commit, keep files
$git reset --hard HEAD~1⚠ Discard everything
$git revert <hash>Safe undo (new commit)
$git clean -fdRemove untracked files
🌿Branches & Merging
Branch Management
$git branchList local branches
$git branch -aList all (incl. remote)
$git branch feature/loginCreate branch
$git switch feature/loginSwitch branch (modern)
$git switch -c feature/loginCreate & switch
$git branch -m old-name new-nameRename branch
$git branch -d feature/loginDelete (safe)
$git branch -D feature/loginDelete (force)
$git push origin --delete feature/loginDelete remote
Merge
$git merge feature/loginMerge into current
$git merge --no-ff feature/loginAlways merge commit
$git merge --squash feature/loginSquash into one commit
$git merge --abortAbort merge conflict
Rebase
$git rebase mainRebase onto main
$git rebase -i HEAD~5Interactive: last 5
$git rebase --abort
$git rebase --continueAfter resolving conflicts
Cherry-Pick
$git cherry-pick <hash>Apply single commit
$git cherry-pick A..BApply range of commits
$git cherry-pick --no-commit <hash>Stage only
🌐Remotes & Sync
Remote Management
$git remote -vList remotes
$git remote add origin <url>
$git remote set-url origin <url>Change URL
$git remote remove <name>
$git remote rename origin upstream
Push & Pull
$git pushPush to tracked remote
$git push -u origin mainPush + set tracking
$git push --force-with-leaseSafe force push
$git push --tagsPush all tags
$git pullFetch + merge
$git pull --rebaseFetch + rebase (cleaner)
$git fetch --all --pruneFetch + clean stale refs
$git fetch origin main:mainFetch without checkout
Tags & Releases
$git tagList all tags
$git tag v1.0.0Lightweight tag
$git tag -a v1.0.0 -m "Release v1.0.0"Annotated
$git tag -a v1.0.0 <hash>Tag specific commit
$git push origin v1.0.0Push one tag
$git push origin --tagsPush all tags
$git tag -d v1.0.0Delete local tag
$git push origin --delete v1.0.0Delete remote tag
🔍History, Log & Stash
Log
$git logFull log
$git log --onelineCompact view
$git log --oneline --graph --allVisual branch tree
$git log -5Last 5 commits
$git log --author="David"
$git log --since="2 weeks ago"
$git log --grep="fix" --onelineSearch messages
$git log -S "function login"Search code changes
$git log --follow <file>File history (renames)
$git show <hash>Show commit diff
$git blame <file>Who changed each line
$git reflogAll HEAD movements
$git bisect startFind bug-introducing commit
$git bisect good <hash>
$git bisect bad <hash>
Stash
$git stashStash working changes
$git stash push -m "wip: login UI"Named stash
$git stash popRestore + remove stash
$git stash apply stash@{1}Apply specific stash
$git stash listShow all stashes
$git stash drop stash@{0}Delete stash
$git stash clearDelete all stashes
$git stash branch feature/workStash → new branch
✍️Conventional Commits & Git Flow
Conventional Commit Format
<type>(scope)!: description Types: feat: New feature → MINOR version bump fix: Bug fix → PATCH version bump docs: Documentation only style: Formatting, no logic change refactor: Restructure without feature/fix perf: Performance improvement test: Add or update tests chore: Build, deps, tooling ci: CI/CD configuration security: Security fix revert: Revert prior commit Breaking change → MAJOR bump: feat!: remove deprecated endpoint # or add footer: BREAKING CHANGE: <description> Examples: feat(auth): add OAuth2 login fix(api): handle null user gracefully docs: update README quickstart chore(deps): bump lodash to 4.17.21
Trunk-Based Development (Recommended)
Main is always deployable. Short-lived feature branches (1-2 days). Merge via PR. Feature flags for incomplete work.
Gitflow Branching Model
main → production only (tagged releases) develop → integration branch feature/* → branch from develop release/* → branch from develop, merge to main+develop hotfix/* → branch from main, merge to main+develop bugfix/* → branch from develop
Naming Conventions
feature/PROJ-123-user-login fix/null-pointer-on-logout docs/update-api-reference release/v2.4.0 hotfix/v2.3.1-fix-auth-bypass chore/upgrade-php-8.2
GitHub CLI (gh)
Auth & Setup
$gh auth loginAuthenticate
$gh auth statusCheck auth state
$gh auth tokenPrint token
Repos
$gh repo create myapp --public
$gh repo create myapp --private --clone
$gh repo clone owner/repo
$gh repo fork owner/repo --clone
$gh repo view --webOpen in browser
$gh repo list --limit 20
Pull Requests
$gh pr create --title "Add login" --body "closes #42"
$gh pr create --fillAuto-fill from commits
$gh pr create --draft
$gh pr listList open PRs
$gh pr view 42View PR details
$gh pr checkout 42Checkout PR locally
$gh pr review 42 --approve
$gh pr review 42 --request-changes --body "..."
$gh pr merge 42 --squash
$gh pr merge --merge --delete-branch
$gh pr close 42
Issues
$gh issue create --title "Bug" --label "bug"
$gh issue list --state open --label bug
$gh issue view 12
$gh issue close 12 --comment "Fixed in #45"
$gh issue edit 12 --add-label "priority:high"
Releases
$gh release create v1.0.0 --title "v1.0.0" --notes "First release"
$gh release create v1.0.0 --generate-notes
$gh release list
$gh release view v1.0.0
$gh release upload v1.0.0 ./dist/app.zip
🔀PR Workflow & Code Review
PR Best Practices
Small PRs. Under 400 lines changed. One concern per PR. Easier to review, faster to merge.
📋Link to issue: Closes #42 or Fixes #42 in body — auto-closes issue on merge.
🏷️Labels: bug, enhancement, documentation, breaking change, WIP, needs review, blocked.
PR Template (.github/PULL_REQUEST_TEMPLATE.md)
## Summary What does this PR do and why? ## Changes - [ ] Feature / fix / refactor / docs ## Testing How was this tested? Paste test output. ## Screenshots (if UI changes) ## Checklist - [ ] Tests pass (all green) - [ ] No stubs or TODOs - [ ] CHANGELOG updated - [ ] Docs updated if needed - [ ] No secrets committed
Merge Strategies
StrategyWhen to use
Merge commitKeep full history (default)
Squash mergeClean main history (recommended)
Rebase mergeLinear history, no merge commits
Review Comments
# Suggestion block (applies a one-click fix) ```suggestion corrected code here ``` # Request changes vs approve LGTM = Looks Good To Me nit: = minor nitpick (non-blocking) blocking: = must fix before merge q: = question, not blocking
CODEOWNERS
# .github/CODEOWNERS * @org/team-leads # default *.php @org/backend src/frontend/ @org/frontend docs/ @org/tech-writers .github/ @org/devops
⚙️GitHub Actions — Workflow Reference
Workflow Triggers
on: push: branches: [main, develop] paths: ['src/**', '!docs/**'] pull_request: types: [opened, synchronize, reopened] schedule: - cron: '0 2 * * 1' # Mon 2am workflow_dispatch: # manual trigger inputs: environment: type: choice options: [staging, production] release: types: [published] issue_comment: types: [created]
CI Pipeline Template
name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest strategy: matrix: php: ['8.1', '8.2', '8.3'] steps: - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - name: Install deps run: composer install --no-dev - name: Run tests run: ./vendor/bin/phpunit - name: Upload coverage uses: codecov/codecov-action@v4
Key Syntax Elements
# Job conditions if: github.ref == 'refs/heads/main' if: github.event_name == 'push' if: success() && always() if: contains(github.event.pull_request.labels.*.name, 'deploy') # Secrets + Env env: DB_URL: ${{ secrets.DATABASE_URL }} NODE_ENV: production # Outputs between jobs id: build run: echo "version=1.0.0" >> $GITHUB_OUTPUT # consume: ${{ needs.build.outputs.version }} # Cache - uses: actions/cache@v4 with: path: vendor key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} # Artifact upload - uses: actions/upload-artifact@v4 with: name: build-output path: dist/
Common Actions
ActionPurpose
actions/checkout@v4Checkout code
actions/setup-node@v4Setup Node.js
actions/setup-python@v5Setup Python
actions/cache@v4Cache dependencies
actions/upload-artifact@v4Upload build files
actions/github-script@v7Run JS with GitHub API
peter-evans/create-pr@v7Auto-create PR
docker/build-push-action@v6Build + push Docker
aws-actions/configure-credentialsAWS auth
anthropics/claude-code-action@v1Claude Code in CI
🛡️Security Features
Dependabot (dependabot.yml)
version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: weekly labels: [dependencies] reviewers: [devops-lead] - package-ecosystem: github-actions directory: / schedule: interval: weekly
Branch Protection Rules
🔒Required for main: Require PR + N approvals. Dismiss stale reviews. Require status checks. Require signed commits. Restrict force push.
Secret Scanning
🔍Enabled in Security tab. Scans for 200+ token patterns. Alerts repo admins. Push protection blocks secrets before they land.
Code Scanning (CodeQL)
name: CodeQL on: [push, schedule] jobs: analyze: runs-on: ubuntu-latest steps: - uses: github/codeql-action/init@v3 with: languages: javascript, python - uses: github/codeql-action/analyze@v3
SECURITY.md Template
## Supported Versions | Version | Supported | |---------|-----------| | 2.x | ✅ Yes | | 1.x | ❌ No | ## Reporting a Vulnerability Do NOT use public issues. Email: security@company.com GPG: [key link] Response: 48h acknowledge, 7 days critical patch
GitHub Platform Features
💬
Issues
Bug tracking, feature requests, tasks. Labels, assignees, milestones, templates.
Free
🔀
Pull Requests
Code review, conversations, suggested changes, required reviewers.
Free
📋
Projects
Kanban/table/roadmap. Linked to issues & PRs. Custom fields & workflows.
Free
💬
Discussions
Community Q&A, announcements, ideas. Separate from issues.
Free
📦
Packages
npm, Docker, Maven, NuGet, RubyGems. Private packages for paid plans.
Paid
🌐
Pages
Static site hosting. Custom domains. HTTPS. Deploy from branch or Actions.
Free
💻
Codespaces
Cloud dev env. VS Code in browser. 2-core free tier. devcontainer.json config.
Paid
🤖
Copilot
AI code completion, chat, PR summaries, code review. IDE + CLI + GitHub.com.
$10/mo
🔍
Code Search
Regex search across all repos. Symbol search. Path filters.
Free
Actions
CI/CD. 2000 min/month free (public). Self-hosted runners. Marketplace.
Free*
📊
Insights
Contributors, traffic, dependency graph, code frequency charts.
Free
🔐
Environments
Named deploy targets (staging/production). Required reviewers. Secrets scoping.
Team+
GitHub CLI Extensions
$gh extension install github/gh-copilot
$gh copilot suggest "undo last commit"
$gh copilot explain "git rebase -i HEAD~5"
$gh extension install dlvhdr/gh-dashDashboard
📁.github/ Structure
Complete .github/ Layout
.github/ ├── CODEOWNERS # Auto-reviewers per path ├── FUNDING.yml # Sponsor buttons ├── dependabot.yml # Auto dependency updates ├── PULL_REQUEST_TEMPLATE.md │ ├── ISSUE_TEMPLATE/ │ ├── bug_report.yml │ ├── feature_request.yml │ ├── documentation.yml │ └── config.yml # Links + blank disable │ ├── workflows/ │ ├── ci.yml # Test on push/PR │ ├── deploy.yml # Deploy on merge to main │ ├── release.yml # Release on tag v*.*.* │ ├── security.yml # Weekly CVE + CodeQL │ ├── pages.yml # Deploy GitHub Pages │ └── stale.yml # Auto-close stale issues │ ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md ├── SECURITY.md └── SUPPORT.md
Issue Template (YAML format)
name: Bug Report description: Something is broken labels: [bug, triage] assignees: [lead-dev] body: - type: textarea id: what-happened label: What happened? placeholder: Describe the bug validations: required: true - type: dropdown id: severity label: Severity options: [Critical, High, Low]
🌐Pages, Packages & Environments
GitHub Pages Deploy Workflow
name: Deploy Pages on: push: branches: [main] permissions: contents: read pages: write id-token: write jobs: deploy: environment: name: github-pages url: ${{ steps.deploy.outputs.page_url }} steps: - uses: actions/checkout@v4 - uses: actions/configure-pages@v5 - uses: actions/upload-pages-artifact@v3 with: path: ./dist - id: deploy uses: actions/deploy-pages@v4
Environments & Deploy Secrets
🔐Environments scope secrets to staging/production. Add required reviewers to gate production deploys.
jobs: deploy-prod: environment: production steps: - run: echo ${{ secrets.PROD_KEY }}
GitHub Packages (Docker)
name: Publish Docker steps: - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/build-push-action@v6 with: push: true tags: ghcr.io/${{ github.repository }}:latest
devcontainer.json (Codespaces)
{ "name": "My App Dev", "image": "mcr.microsoft.com/devcontainers/php:8.2", "postCreateCommand": "composer install", "customizations": { "vscode": { "extensions": ["GitHub.copilot"] } }, "forwardPorts": [8080] }
⌨️Keyboard Shortcuts
GitHub.com Global
S
Focus search
GN
Go to Notifications
GC
Go to Code tab
GI
Go to Issues
GP
Go to Pull Requests
GA
Go to Actions
GB
Go to Projects (Board)
GW
Go to Wiki
?
Show keyboard shortcuts
Code Browsing
T
File finder (fuzzy)
L
Jump to line
W
Switch branch/tag
Y
Permalink to commit SHA
B
Toggle blame view
.
Open in github.dev editor
>
Open in Codespaces
Issues & PRs
C
Open new comment
CtrlEnter
Submit comment
R
Quote selected text
E
Add emoji reaction
A
Set assignee
L
Set label
M
Set milestone
Markdown Editor
CtrlB
Bold
CtrlI
Italic
CtrlK
Insert link
CtrlShift7
Ordered list
CtrlShift8
Unordered list
Markdown Quick Reference
# H1 ## H2 ### H3 **bold** *italic* ~~strike~~ `code` ```lang\ncode\n``` > blockquote - [ ] task - [x] done [text](url) ![alt](img-url) #42 → link issue @username → mention SHA → link commit :emoji: → 😀
🔬Advanced Git Operations
Submodules
$git submodule add <url> path/Add submodule
$git submodule update --init --recursiveInit submodules
$git clone --recurse-submodules <url>
$git submodule foreach git pull origin mainUpdate all
$git submodule deinit path/ && git rm path/Remove
Worktrees
$git worktree add ../hotfix hotfix/v1.2.1Multiple branches at once
$git worktree list
$git worktree remove ../hotfix
Sparse Checkout (monorepos)
$git clone --filter=blob:none --sparse <url>
$git sparse-checkout set src/myservice
Interactive Rebase Actions
pick a1b2c3 Use commit as-is reword a1b2c3 Change commit message edit a1b2c3 Pause to amend commit squash a1b2c3 Squash into previous fixup a1b2c3 Squash, discard message drop a1b2c3 Remove commit entirely exec make test Run command after commit
Useful One-Liners
$git shortlog -sn --no-mergesCommit counts by author
$git diff HEAD~5 HEAD --statChanges in last 5 commits
$git log --all --full-history -- "**/deleted-file.php"Find deleted file
$git ls-files | xargs wc -lCount lines in repo
$git for-each-ref --sort=-committerdate refs/heads/Branches by date
$git diff --word-diffInline word changes
$git archive --format=zip HEAD > snapshot.zipExport repo
$git gc --aggressive --prune=nowCleanup + compress
$git count-objects -vHRepo size info
📐Actions: Context Variables & Expressions
github Context
${{ github.actor }} User who triggered ${{ github.event_name }} push | pull_request | etc. ${{ github.ref }} refs/heads/main ${{ github.sha }} Full commit SHA ${{ github.run_id }} Unique workflow run ID ${{ github.run_number }} Sequential run number ${{ github.repository }} owner/repo ${{ github.workspace }} Checkout path ${{ github.token }} Auto GITHUB_TOKEN ${{ github.event.pull_request.number }}
runner Context
${{ runner.os }} Linux | Windows | macOS ${{ runner.arch }} X64 | ARM64 ${{ runner.temp }} Temp directory path
Expressions
# Functions contains(str, 'value') startsWith(str, 'prefix') endsWith(str, 'suffix') format('text {0}', var) join(array, ',') toJSON(value) fromJSON(string) hashFiles('**/lock.json') # Status functions success() all previous steps passed failure() any previous step failed always() run regardless of status cancelled() workflow was cancelled
Reusable Workflows
# caller.yml jobs: call-test: uses: ./.github/workflows/test.yml with: environment: staging secrets: inherit # test.yml (reusable) on: workflow_call: inputs: environment: type: string required: true
🤖Copilot, Search & API
GitHub Copilot Tips
💡Write a comment first. Describe what you want before writing code — Copilot completes from context.
🎯Open relevant files. Copilot uses open tabs as context. Open similar files for better suggestions.
💬Copilot Chat: @workspace to query whole codebase. /explain, /fix, /tests, /doc slash commands.
📝Copilot for PRs: Generates PR description from your changes. Enable in repo settings → Copilot → PR summaries.
Code Search Syntax
language:php filter by language repo:owner/myrepo specific repo path:src/auth in this path extension:php file extension filename:config.php exact filename symbol:functionName function/class name content:"SELECT * FROM" text in file /regex.pattern/ regex search # Combine: language:php symbol:authenticate repo:myorg/
GitHub REST API Quick Ref
# Auth: Bearer token or gh auth token BASE_URL=https://api.github.com # List PRs curl $BASE_URL/repos/owner/repo/pulls \ -H "Authorization: Bearer $GH_TOKEN" # Create issue curl -X POST $BASE_URL/repos/owner/repo/issues \ -H "Authorization: Bearer $GH_TOKEN" \ -d '{"title":"Bug","body":"Details"}' # GraphQL gh api graphql -f query=' query { viewer { login } } '
Webhooks
🔔Settings → Webhooks → Add. Payload URL receives JSON POST for events: push, pull_request, issue, release, workflow_run. Verify X-Hub-Signature-256 with your secret.
🚀Release Automation & Versioning
Semantic Versioning
# MAJOR.MINOR.PATCH v2.4.1 ↑ Breaking change (MAJOR) ↑ New feature (MINOR) ↑ Bug fix (PATCH) # Pre-release v2.5.0-alpha.1 v2.5.0-beta.3 v2.5.0-rc.1
Automated Release Workflow
name: Release on: push: tags: ['v*.*.*'] jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # full history for notes - name: Build run: make build - name: Create Release uses: softprops/action-gh-release@v2 with: generate_release_notes: true files: dist/**
gh CLI Release Flow
$git tag -a v2.5.0 -m "Release v2.5.0"
$git push origin v2.5.0
$gh release create v2.5.0 --generate-notes --latest
Auto-Changelog (release-please)
name: Release Please on: push: branches: [main] jobs: release-please: uses: googleapis/release-please-action@v4 with: release-type: node token: ${{ secrets.GITHUB_TOKEN }}
release-please reads Conventional Commits → auto-bumps version → creates CHANGELOG → opens release PR. Merge to release.