Add comprehensive GitHub guide covering account setup, collaboration, and API usage

This commit is contained in:
2026-02-05 21:00:02 -06:00
parent e8f4979ff3
commit ea00a7be82
13 changed files with 8495 additions and 79 deletions

926
mindmap/Distributed Git.md Normal file
View File

@@ -0,0 +1,926 @@
```markdown
# Distributed Git
## Context & Goals (Why this chapter)
- Starting point
- A remote Git repository already exists as a shared focal point
- You already know basic local Git commands/workflow
- What “distributed” enables
- Git supports distributed collaboration patterns beyond centralized VCSs
- Two roles youll learn to operate in
- Contributor
- Contribute code successfully
- Make it easy for you + project maintainer
- Integrator / Maintainer
- Maintain a project with many contributors
- Integrate others work sustainably and clearly
## Distributed Workflows (Collaboration models)
### Git vs Centralized Version Control Systems (CVCSs)
- CVCS mental model
- Central hub/repository is the primary “source”
- Developers are “nodes” consuming/syncing with that hub
- Git mental model (distributed)
- Every developer is potentially both:
- A node (contributor to others)
- A hub (maintains a public repo others can base work on)
- Result: many possible workflow designs
- You can choose one workflow
- Or mix-and-match features
### Centralized Workflow (Single shared hub)
- Core idea
- One central repository (“hub”) accepts code
- Everyone synchronizes with that central location
- What happens when changes overlap in time
- Two developers clone from hub and both change things
- First developer to push succeeds
- Second developer must first merge the upstream work locally
- Prevents overwriting the first developers work
- True in Git just like Subversion (or any CVCS)
- Why people like it
- Familiar paradigm for many teams
- Git-specific note
- You can keep using this model in Git
- Give everyone push access
- Git prevents overwriting (rejects non-fast-forward pushes)
- Scale note
- Not limited to small teams
- Git branching makes it possible for hundreds of devs to work across dozens of branches
- Figure 53: Centralized workflow
- Hub repository with multiple developers syncing to it
### Integration-Manager Workflow (Multiple repos + canonical “official” repo)
- Core idea
- Each developer:
- Has write access to their own public repository
- Has read access to others repositories
- There is a canonical (“official”) repository
- Contribution mechanics (typical steps)
1. Maintainer pushes to their public repository
2. Contributor clones that repository and makes changes
3. Contributor pushes to their own public copy
4. Contributor requests maintainer to pull changes (often email)
5. Maintainer adds contributor repo as remote, tests locally, merges locally
6. Maintainer pushes merged result to canonical repo
- Where its common
- Hub-based hosting (e.g., GitHub/GitLab-style forking)
- Key advantage emphasized
- Asynchronous pace
- Contributor keeps working without waiting for acceptance
- Maintainer can pull in changes whenever ready
- Figure 54: Integration-manager workflow
- Blessed/canonical repo + integration manager + contributor public/private repos
### Dictator and Lieutenants Workflow (Large hierarchical projects)
- What it is
- Variant of multi-repo workflow
- Used in huge projects with hundreds of collaborators (example: Linux kernel)
- Roles
- Lieutenants
- Integration managers for specific subsystems/areas
- Benevolent dictator
- Single final integration manager
- Pushes to reference (“blessed”) repository
- Process (typical steps)
1. Regular developers
- Work on topic branches
- Rebase their work on top of `master`
- `master` here = reference repos `master` that dictator pushes to
2. Lieutenants
- Merge developers topic branches into lieutenants `master`
3. Dictator
- Merges lieutenants `master` branches into dictators `master`
4. Dictator pushes to reference repository
- Other developers rebase on that updated `master`
- When it helps
- Very large projects
- Highly hierarchical environments
- Delegates integration work; collects large subsets before final integration
- Noted as
- Not common overall
- But useful in specific contexts
- Figure 55: Benevolent dictator workflow
- Dictator integrates from lieutenants; pushes to blessed repository
### Patterns for Managing Source Code Branches (external guide callout)
- Reference
- Martin Fowler guide: “Patterns for Managing Source Code Branches”
- Link: https://martinfowler.com/articles/branching-patterns.html
- What the guide covers (as noted)
- Common Git workflows
- How/when to use them
- Comparison of high vs low integration frequencies
### Workflows Summary (transition)
- Distributed Git allows many variations
- Choose a workflow (or combination) that fits reality
- Next: specific contributing patterns and use cases
## Contributing to a Project (How to contribute effectively)
### Why its hard to prescribe one “right” way
- Git is flexible → many real-world collaboration styles
- Every project differs
### Key variables that change the “best” approach
- Active contributor count (and activity level)
- Small/dormant: 23 devs, few commits/day (or less)
- Large: thousands of devs, hundreds/thousands of commits/day
- Practical risk with larger activity
- Your changes may not apply cleanly later
- Your changes may become obsolete/broken before merging
- Need to keep work up to date and commits valid
- Workflow in use
- Centralized (everyone can push to main line)
- Integration manager / maintainer gatekeeping
- Peer review requirements
- Lieutenant system (submit to subsystem maintainers first)
- Your commit access
- Write access vs no write access changes everything
- If no access
- How does project accept contributions (policy/method)?
- Contribution size & frequency
- How much you contribute at a time
- How often you contribute
### Approach in chapter
- Presents a series of use cases (simple → complex)
- Goal
- Let you construct the workflow you need in practice
### Commit Guidelines (preparing high-quality contributions)
- Source of guidance
- Git projects tips: `Documentation/SubmittingPatches`
- Guideline 1: Avoid whitespace errors
- Check before committing:
- `git diff --check`
- Purpose
- Identify whitespace problems early
- Prevent annoying reviewers/maintainers
- Figure 56: Output of `git diff --check`
- Guideline 2: Make commits logically separate changesets
- Keep changes digestible
- Dont bundle multiple unrelated issues into one massive commit
- Use staging area to split work
- Even if you did work across multiple issues before committing
- If changes overlap in same file
- Use partial staging:
- `git add --patch`
- (Referenced as covered in “Interactive Staging”)
- Key point emphasized
- Final snapshot can be identical whether you do 1 commit or 5
- But review/revert is much easier with clean, separated commits
- Benefit
- Easier to later pull out/revert one changeset
- Tooling reference
- “Rewriting History” provides techniques for crafting clean history
- Guideline 3: Write high-quality commit messages
- Why
- Makes using Git + collaborating easier
- Recommended structure
- Summary line
- ~50 characters or less
- Concise description of changeset
- Blank line (important)
- Tools (e.g., rebase) can get confused without it
- Body (optional, but recommended when needed)
- More detailed explanation
- Wrap around ~72 characters
- Include motivation for change
- Contrast implementation with previous behavior (Git project requirement)
- Style rules
- Imperative mood
- “Fix bug” (not “Fixed bug” / “Fixes bug”)
- Matches messages auto-generated by `git merge` and `git revert`
- Formatting details
- Multiple paragraphs separated by blank lines
- Bullet points are okay
- Hyphen/asterisk + single space
- Hanging indent
- Conventions vary
- Example quality reference
- Look at Git project history:
- `git log --no-merges`
- Callout: “Do as we say, not as we do”
- Book examples often use `git commit -m` for brevity
- Not meant as best-practice formatting
## Use Case 1: Private Small Team (simple shared repo)
### Setting
- Private = closed-source, not public
- 12 other developers
- Everyone has push access to the shared repository
- Workflow resembles centralized systems (e.g., Subversion), but with Git advantages
- Offline commits
- Easier branching/merging
- Key difference vs Subversion: merges happen client-side
### Example scenario: John & Jessica pushing to shared repo
- John: clone, edit, commit
- `git clone john@githost:simplegit.git`
- edit `lib/simplegit.rb`
- `git commit -am 'Remove invalid default value'`
- Jessica: clone, edit, commit
- `git clone jessica@githost:simplegit.git`
- edit `TODO`
- `git commit -am 'Add reset task'`
- Jessica pushes successfully
- `git push origin master`
- Push output explained (last line format)
- `<oldref>..<newref> fromref → toref`
- `oldref`: previous remote reference
- `newref`: updated remote reference
- `fromref`: local ref being pushed
- `toref`: remote ref being updated
- Reference: `git-push` documentation
- John tries to push and is rejected
- `git push origin master`
- Error: rejected (non-fast forward)
- Key lesson vs Subversion
- Even if they edited different files
- Git requires John to fetch + merge locally before pushing
- Subversion might do server-side merge; Git does not
### John resolves the non-fast-forward
- Step 1: Fetch upstream changes
- `git fetch origin`
- Fetch downloads changes but does not merge them
- Figure 57: Johns divergent history (local master vs `origin/master`)
- Step 2: Merge fetched upstream
- `git merge origin/master`
- Merge strategy shown: `recursive`
- Figure 58: Johns repository after merging `origin/master`
- Step 3: Test merged code (recommended)
- Step 4: Push merged result
- `git push origin master`
- Figure 59: Johns history after pushing to origin
### Jessicas parallel work: topic branch + later integration
- Jessica created topic branch `issue54`
- 3 commits on that branch
- She hadnt fetched Johns updates yet
- Figure 60: Jessicas topic branch
- Jessica fetches new work
- `git fetch origin`
- Figure 61: Jessicas history after fetching Johns changes
- Jessica determines what new commits exist on `origin/master`
- `git log --no-merges issue54..origin/master`
- Meaning of `issue54..origin/master`
- Show commits on `origin/master` that are not on `issue54`
- Note: range syntax referenced as covered later in “Commit Ranges”
- Jessica integrates (order doesnt matter for final snapshot)
- Switch to master
- `git checkout master`
- Message may indicate behind `origin/master` and fast-forwardable
- Merge topic branch to master (chosen first)
- `git merge issue54`
- Result: fast-forward merge (no new merge commit)
- Merge Johns upstream work
- `git merge origin/master`
- Result: merge commit created via recursive strategy
- Figure 62: Jessicas history after merging Johns changes
- Jessica pushes
- `git push origin master`
- Figure 63: Jessicas history after pushing all changes
### General “simple multi-developer” sequence (as summarized)
- Work locally (often in a topic branch)
- Merge topic branch into `master` when ready
- Before sharing
- Fetch and merge `origin/master` if it changed
- Push `master` to server
- Figure 64: General sequence of events for this simple workflow
## Use Case 2: Private Managed Team (team branches + integrators)
### Setting
- Larger private group
- Small groups collaborate on features
- Integrators (a subset of engineers) merge into mainline
- Only integrators can update `master` of main repo
- Team collaboration happens on shared feature branches
### Scenario setup
- FeatureA: John + Jessica
- FeatureB: Jessica + Josie
- Work happens on team-based branches; integrators pull together later
### Jessica works on FeatureA (with John)
- Create feature branch
- `git checkout -b featureA`
- Work + commit
- `git commit -am 'Add limit to log function'`
- Share with John
- Push feature branch (no `master` push permission)
- `git push -u origin featureA`
- `-u` / `--set-upstream` sets upstream tracking for easier push/pull
- Notify John (email)
### Jessica works on FeatureB (with Josie)
- Base new branch off server `master`
- `git fetch origin`
- `git checkout -b featureB origin/master`
- Work + commits
- `git commit -am 'Make ls-tree function recursive'`
- `git commit -am 'Add ls-files'`
- Figure 65: Jessicas initial commit history (featureA and featureB in progress)
### Josie already started an upstream branch for FeatureB
- Josie pushed initial work as branch `featureBee`
- Jessica fetches
- `git fetch origin`
- New remote-tracking branch: `origin/featureBee`
- Jessica merges Josies work into her local `featureB`
- `git merge origin/featureBee`
- Jessica pushes merged result back to the shared upstream branch
- Uses a refspec:
- `git push -u origin featureB:featureBee`
- Refspec concept
- Push local `featureB` to remote branch `featureBee`
- Reference: “The Refspec”
- `-u` sets upstream for simpler future pushes/pulls
### John updates FeatureA; Jessica reviews and merges
- Fetch updates (includes Johns latest on featureA)
- `git fetch origin`
- See what John added (compare local vs fetched)
- `git log featureA..origin/featureA`
- Merge it in
- `git checkout featureA`
- `git merge origin/featureA` (fast-forward in example)
- Add minor tweaks
- `git commit -am 'Add small tweak to merged content'`
- Push featureA back to server
- `git push`
- Figure 66: Jessicas history after committing on a feature branch
### Integrators merge FeatureA and FeatureBee into mainline
- Team informs integrators the branches are ready
- Integrators merge into mainline
- After a fetch, Jessica sees merge commit(s)
- Figure 67: Jessicas history after integrators merged both topic branches
### Benefits emphasized
- Multiple teams can work in parallel
- Late merging of independent lines of work
- Remote branches let subgroups collaborate without blocking entire team
- Figure 68: Basic sequence of the managed-team workflow
## Use Case 3: Forked Public Project (contribute via forks & pull requests)
### Why this differs
- Public project: you typically cannot push to the official repo
- Need a different path to get work to maintainers
### Typical fork-based flow
- Clone main repository
- `git clone <url>`
- Create a topic branch for your work
- `git checkout -b featureA`
- Commit as you work
- `git commit` (repeat as needed)
- Optional cleanup for review
- Use interactive rebase:
- `rebase -i`
- Goals: squash commits, reorder, make review easier
- Reference: “Rewriting History”
### Fork + push topic branch to your fork
- Fork via hosting site (“Fork” button) → writable fork
- Add fork as remote
- `git remote add myfork <url>`
- Push only the topic branch (recommended)
- `git push -u myfork featureA`
- Why avoid merging into your `master` before pushing?
- If rejected or cherry-picked, you dont need to rewind your master
- Maintainers may merge/rebase/cherry-pick; youll receive it later by pulling upstream
### Notify maintainers: Pull request / request-pull
- “Pull request” can be created:
- Through the website (e.g., GitHub mechanism)
- Or manually via `git request-pull` + email
- `git request-pull` purpose
- Produces a summary of changes being requested for pull
- Inputs
- Base branch to pull into (e.g., `origin/master`)
- Repo URL to pull from (your fork)
- Output includes (as shown)
- Base commit reference (“changes since commit …”)
- Where to pull from (URL + branch)
- Commit list + diffstat summary
### Best practice for multiple contributions
- Keep a local `master` tracking `origin/master`
- Work in topic branches
- Easy to discard if rejected
- Easy to rebase if upstream moves
### Starting a second topic: dont stack topics on old branches
- Start new branch from current upstream master
- `git checkout -b featureB origin/master`
- Work + commit
- Push
- `git push myfork featureB`
- Request pull
- `git request-pull origin/master myfork`
- Update your view of upstream
- `git fetch origin`
- Resulting structure
- Topics become separate silos (patch-queue-like)
- Figure 69: Initial commit history with featureB work
### Scenario: maintainer cant merge your featureA cleanly anymore
- Cause
- Upstream `origin/master` moved; your topic doesnt apply cleanly
- Fix
- Rebase your topic onto current upstream
- `git checkout featureA`
- `git rebase origin/master`
- Force push updated branch to your fork
- `git push -f myfork featureA`
- Why `-f` is required
- Rebase rewrites history
- New commits may not be descendants of the remote branch tip
- Alternative mentioned
- Push to a new branch (e.g., `featureAv2`) instead of force-updating
- Figure 70: Commit history after rebasing featureA work
### Scenario: maintainer likes featureB but requests implementation changes
- Goal
- Re-base on current `origin/master`
- Provide revised branch version
- Workflow
- Create new branch from current upstream
- `git checkout -b featureBv2 origin/master`
- Squash merge old feature branch changes
- `git merge --squash featureB`
- Make requested implementation changes
- Commit
- `git commit`
- Push new branch
- `git push myfork featureBv2`
- Meaning of `--squash`
- Combines all changes into one changeset
- Produces final state as if merged, but without a merge commit
- New commit has only one parent
- Lets you add more edits before recording the final commit
- Extra option callout
- `--no-commit` can delay commit in default merge process
- Figure 71: Commit history after featureBv2 work
## Use Case 4: Public Project over Email (patch series via mailing list)
### When this is used
- Many older/larger projects accept patches via mailing lists
- Each project has specific procedures → you must check their rules
### High-level flow
- Create a topic branch per patch series
- Instead of forking/pushing
- Generate email-ready patches
- Email to developer mailing list
### Create commits on a topic branch
- `git checkout -b topicA`
- Work + commit
- `git commit` (repeat)
### Generate mbox-formatted patch emails: `git format-patch`
- Command example
- `git format-patch -M origin/master`
- What it produces
- One `*.patch` file per commit
- Each patch file = one email message
- Subject = first line of commit message
- Body = remainder of message + the diff
- Why its nice
- Applying patches generated this way preserves commit info properly
- Option noted
- `-M` makes Git detect renames
### Patch file structure (what maintainers/reviewers see)
- Email-like headers
- `From <sha> Mon Sep 17 00:00:00 2001`
- `From: <author>`
- `Date: <date>`
- `Subject: [PATCH x/y] <summary>`
- Commit message body text
- Separator
- `---`
- Patch begins
- `diff --git ...`
- Version footer (as shown in example)
### Adding extra explanation without changing commit message
- You can edit patch files
- Place extra notes between:
- the `---` line
- and the `diff --git` line
- These notes
- are readable by developers
- are ignored by patch application
### Sending patches without breaking formatting
- Copy/paste into email client can break whitespace/newlines
- Git-provided tools to send properly formatted patches
#### Option A: IMAP (drafts workflow) with `git imap-send`
- Setup `~/.gitconfig` `[imap]` section (example values shown)
- `folder` (e.g., `[Gmail]/Drafts`)
- `host` (e.g., `imaps://imap.gmail.com`)
- `user`
- `pass`
- `port` (e.g., `993`)
- `sslverify = false`
- SSL note
- If IMAP server doesnt use SSL
- last lines may be unnecessary
- host uses `imap://` not `imaps://`
- Send patches to Drafts folder
- `cat *.patch | git imap-send`
- Then in email client
- Set `To:` mailing list
- Possibly CC maintainer/area owner
- Send
#### Option B: SMTP with `git send-email`
- Setup `~/.gitconfig` `[sendemail]` section (example values shown)
- `smtpencryption = tls`
- `smtpserver = smtp.gmail.com`
- `smtpuser`
- `smtpserverport = 587`
- Send patch files
- `git send-email *.patch`
- Interactive prompts noted
- “From” identity
- Recipients
- Message-ID / In-Reply-To for threading
- Output includes per-patch send logs and headers
- Tip resource
- Configuration help + sandbox for trial patches:
- https://git-send-email.io
## Contribution Summary (end of “Contributing” portion)
- Covered
- Multiple workflows (private vs public)
- How to handle merges in those workflows
- Commit hygiene
- whitespace checks
- logically separated commits
- strong commit messages
- Patch generation and emailing
- Transition
- Next: maintaining a project (integration/maintainer side)
## Maintaining a Project (Integrator/Maintainer perspective)
### What “maintaining” involves
- Accepting and applying patches from email
- Often produced by `format-patch`
- Integrating changes from remote branches
- From repos you add as remotes
- Applies whether you
- maintain a canonical repository
- or help by verifying/approving patches
- Goal
- Accept work in a way that is clear for contributors
- Sustainable long-term
### Working in Topic Branches (safe integration practice)
- Best practice
- Try new contributions in a temporary topic branch
- Why
- Easy to test and tweak
- Easy to abandon temporarily and return later
- Naming guidance
- Use descriptive theme-based names (e.g., `ruby_client`)
- Git maintainer convention:
- namespace: `sc/ruby_client`
- `sc` = contributor shorthand
- Create topic branch from `master`
- Create only:
- `git branch sc/ruby_client master`
- Create and switch immediately:
- `git checkout -b sc/ruby_client master`
### Applying Patches from Email (two main tools)
- Two methods
- `git apply`
- `git am`
#### Applying with `git apply` (for raw diffs)
- When to use
- Patch generated from `git diff` or generic Unix diff (not recommended if `format-patch` available)
- Apply a patch file
- `git apply /tmp/patch-ruby-client.patch`
- What it does
- Modifies files in working directory
- Similar to `patch -p1`, but:
- More paranoid (fewer fuzzy matches)
- Understands Git diff format adds/deletes/renames (patch tool may not)
- “Apply all or abort all” (atomic)
- Unlike `patch`, which can partially apply and leave a messy state
- Important limitation
- Does not create a commit
- You must stage and commit manually afterward
- Preflight check
- `git apply --check <patch>`
- Behavior
- No output → should apply cleanly
- Non-zero exit status on failure → script-friendly
#### Applying with `git am` (for `format-patch` / mbox)
- When to use (preferred)
- Contributor used `git format-patch`
- Patch includes author info and commit message
- Meaning / concept
- `am` = apply patches from a mailbox
- Reads mbox format (plain-text emails in one file)
- Apply a patch file generated by `format-patch`
- `git am 0001-limit-log-function.patch`
- What it does automatically
- Creates commits for you
- Uses email headers/body to populate:
- Author info: From + Date
- Commit message: Subject + body (before diff)
- Committer info becomes the applier + apply time
- Inspecting result (example command shown)
- `git log --pretty=fuller -1`
- Distinction highlighted
- Author vs Committer (applier)
- If patch fails to apply cleanly
- Common causes noted
- Your branch diverged too far
- Patch depends on another patch not applied yet
- Failure behavior
- Stops and shows options:
- Continue after fixing: `git am --resolved`
- Skip patch: `git am --skip`
- Abort and restore original branch: `git am --abort`
- Adds conflict markers to files (like merge/rebase)
- Manual conflict workflow
- Fix file(s)
- Stage:
- `git add <file>`
- Continue:
- `git am --resolved`
- Smarter conflict handling option: `-3`
- `git am -3 <patch>`
- What it does
- Attempts a three-way merge
- Caveat
- Doesnt work if the base commit referenced by patch isnt in your repo
- When it works well
- Patch based on a public commit you have
- Example behavior shown
- Can detect “Patch already applied” when appropriate
- Interactive mode for patch series
- `git am -3 -i <mbox>`
- Stops at each patch and asks:
- yes / no / edit / view patch / accept all
- Useful when
- You have many patches saved
- You want to preview or skip already-applied patches
### Checking Out Remote Branches (pulling history from contributor repos)
- When to use
- Contributor provides:
- repository URL
- branch name containing their changes
- One-time setup + local testing
- Add remote:
- `git remote add jessica git://github.com/jessica/myproject.git`
- Fetch:
- `git fetch jessica`
- Checkout local branch from remote-tracking branch:
- `git checkout -b rubyclient jessica/ruby-client`
- Ongoing benefit
- If same contributor sends more branches
- you can fetch/checkout without re-adding remote
- Pros emphasized
- You get the full commit history
- You know where its based → proper three-way merges by default
- Avoid needing `-3` guesswork
- Cons / practicality
- Not efficient to maintain hundreds of remotes for occasional contributors
- For one-off patches, email may be easier
- Scripts/hosted services may change the trade-off
- One-time pull without saving a remote
- `git pull <url>`
- Does not store the remote in your config
### Determining What Is Introduced (reviewing a topic branch)
- Review commits unique to topic branch
- Exclude master commits:
- `git log contrib --not master`
- Equivalent idea to `master..contrib`
- Review changes per commit
- `git log -p ...` to append diffs
- Review overall diff of what merging would introduce
- Pitfall
- `git diff master` can be misleading if histories diverged
- It compares tip snapshots and may make it look like topic removes master-only changes
- Correct intention
- Diff topic tip vs common ancestor with master
- Compute common ancestor explicitly
- `git merge-base contrib master`
- Then:
- `git diff <merge-base-sha>`
- or `git diff $(git merge-base contrib master)`
- Shorthand: triple-dot diff
- `git diff master...contrib`
- Shows only changes introduced on topic branch since divergence
### Integrating Contributed Work (strategies)
#### Merging Workflows (merge-based integration)
- Simple merge-into-master workflow
- `master` contains stable code
- For each completed/verified topic branch
- merge into `master`
- delete topic branch
- repeat
- Figures
- Figure 72: History with several topic branches (`ruby_client`, `php_client`)
- Figure 73: After merging topic branches
- Two-phase merge cycle (master + develop)
- Two long-running branches
- `master` = only updated on stable releases
- `develop` = integration branch for new code
- Both pushed to public repository
- Process
- Merge topic branches into `develop`
- When ready to release
- tag release
- fast-forward `master` to `develop`
- Figures
- Figure 74: Before topic merge
- Figure 75: After topic merge (into develop)
- Figure 76: After project release (master fast-forward)
- User-facing implication
- Users can choose:
- `master` for stable builds
- `develop` for cutting-edge
- Extension: add `integrate` branch
- `integrate` collects work together
- When stable + tests pass
- merge into `develop`
- After `develop` proves stable
- fast-forward `master`
#### Large-Merging Workflows (Git project example)
- Git project long-running branches
- `master`
- `next`
- `seen` (formerly `pu` = proposed updates)
- `maint` (maintenance backports)
- Workflow
- New contributions collected as topic branches
- Topics evaluated
- Safe/ready → merge into `next` and push for wider testing
- Need work → merge into `seen`
- Totally stable → re-merge into `master`
- After master updates
- `next` and `seen` rebuilt from `master`
- Behavior noted
- `master` moves forward steadily
- `next` rebased occasionally
- `seen` rebased more often
- Topic branches removed after they reach `master`
- `maint` branch purpose
- Forked from last release for backports / maintenance releases
- Figures
- Figure 77: Managing many parallel contributed topic branches
- Figure 78: Merging topics into `next`/`seen` and re-merging to `master`
- Note
- Specialized; refer to Git Maintainers guide for full clarity
#### Rebasing and Cherry-Picking Workflows (linear history preference)
- Rebase-based integration
- Maintainer rebases topic branch on top of current `master` (or `develop`)
- If successful
- fast-forward `master`
- Outcome
- Mostly linear history
- Cherry-pick-based integration
- Cherry-pick = reapply the patch from a single commit onto current branch
- Useful when
- You want only some commits from a topic branch
- Or topic branch contains only one commit
- Example
- Before: Figure 79 (commit `e43a6` on topic branch)
- Command:
- `git cherry-pick e43a6`
- After: Figure 80 (new commit SHA because applied at different time)
- After cherry-picking
- remove topic branch / drop unwanted commits
### Rerere (Reuse Recorded Resolution)
- When it helps
- Lots of merges/rebases
- Long-lived topic branches
- Meaning
- “reuse recorded resolution”
- What it does
- Records successful conflict resolutions (pre/post images)
- Reapplies the same resolution automatically if conflict repeats
- Enable (recommended global)
- `git config --global rerere.enabled true`
- Interacting with rerere
- `git rerere` command
- With no args:
- attempts to match current conflicts to recorded resolutions
- (automatic if enabled)
- Subcommands mentioned
- show what will be recorded
- erase specific resolutions
- clear entire cache
- Reference
- Covered in more detail later in “Rerere”
### Tagging Your Releases
- Purpose
- Mark releases so they can be recreated later
- Signed tagging example
- `git tag -s v1.5 -m 'my signed 1.5 tag'`
- Requires PGP key + passphrase
- Distributing public PGP key (for verifying signed tags)
- Problem
- Others need your public key to verify signatures
- Git projects approach
- Store public key in repo as a blob
- Add a tag pointing directly to that blob
- Steps
1. Find the key
- `gpg --list-keys`
2. Export key and write to Git object database (blob)
- `gpg -a --export <KEYID> | git hash-object -w --stdin`
- Output is the blob SHA-1
3. Tag that blob
- `git tag -a maintainer-pgp-pub <blob-sha>`
4. Share tag(s)
- `git push --tags`
5. Users import key from repo
- `git show maintainer-pgp-pub | gpg --import`
6. Users verify signed tags using imported key
- Extra note
- Put verification instructions in tag message
- `git show <tag>` displays them
### Generating a Build Number (human-readable commit identifier)
- Problem
- Git doesnt provide monotonically increasing build numbers per commit
- Solution
- `git describe <commit>`
- Output format
- `<most recent tag>-<commits since tag>-g<abbrev sha>`
- `g` indicates Git
- Example
- `git describe master``v1.6.2-rc1-20-g8c5b85c`
- Behavior notes
- If commit itself is tagged
- Output is just the tag name
- Default requires annotated tags (`-a` or `-s`)
- Include lightweight tags with `--tags`
- Usability note
- Can use describe string with `git checkout` / `git show`
- But relies on abbreviated SHA → may become invalid if abbreviation length changes
- Example mentioned: Linux kernel increased abbrev length (8 → 10) for uniqueness
### Preparing a Release (archives for non-Git users)
- Tool
- `git archive`
- Create tar.gz snapshot (example)
- `git archive master --prefix='project/' | gzip > \`git describe master\`.tar.gz`
- Create zip snapshot (example)
- `git archive master --prefix='project/' --format=zip > \`git describe master\`.zip`
- Resulting archive contents
- Latest snapshot
- Under a top-level directory prefix (e.g., `project/`)
### The Shortlog (release notes / mailing list summary)
- Purpose
- Quick changelog summary since last release (or last email)
- Tool
- `git shortlog`
- Example
- `git shortlog --no-merges master --not v1.0.1`
- Output properties
- Groups commits by author
- Lists commit summaries
- Excludes merge commits with `--no-merges`
## Chapter Summary (end)
- You should now be comfortable
- Contributing using multiple distributed workflows
- Maintaining/integrating contributed work
- Next chapter preview
- GitHub (major Git hosting service)
```