Add comprehensive GitHub guide covering account setup, collaboration, and API usage
This commit is contained in:
798
mindmap/Git Branching.md
Normal file
798
mindmap/Git Branching.md
Normal file
@@ -0,0 +1,798 @@
|
||||
```markmap
|
||||
# Git Branching
|
||||
|
||||
## Why branching matters (and why Git is different)
|
||||
- Branching (general VCS concept)
|
||||
- Meaning: diverge from the main line of development
|
||||
- Goal: keep working without disturbing the main line
|
||||
- Traditional VCS branching (typical tradeoff)
|
||||
- Often “expensive”
|
||||
- May require creating a full new copy of the source directory
|
||||
- Large projects → branching can take a long time
|
||||
- Git branching “killer feature”
|
||||
- Incredibly lightweight model
|
||||
- Branch operations are (nearly) instantaneous
|
||||
- Switching branches is typically just as fast
|
||||
- Encourages frequent branching + merging (even multiple times per day)
|
||||
- Mastering branching can significantly change how you develop
|
||||
|
||||
## Branches in a Nutshell (how Git’s model works)
|
||||
- Why you must understand Git’s storage model
|
||||
- Branching is “just pointers” in Git, but that only makes sense once you know what commits are
|
||||
- Reference: earlier concept “What is Git?” (snapshots, SHA-1, objects)
|
||||
|
||||
### Git stores snapshots, not diffs/changesets
|
||||
- Git’s core model
|
||||
- Instead of storing a sequence of diffs, Git stores a sequence of snapshots
|
||||
- Each commit represents the state of the project at that point
|
||||
|
||||
### Commit objects: what a commit contains
|
||||
- Commit object includes
|
||||
- Pointer to the snapshot you committed (via a tree object)
|
||||
- Metadata
|
||||
- author name + email
|
||||
- commit message
|
||||
- Parent commit pointer(s)
|
||||
- 0 parents → initial commit
|
||||
- 1 parent → normal commit
|
||||
- 2+ parents → merge commit (merging 2+ branches)
|
||||
|
||||
### Example: first commit with 3 files (blobs + tree + commit)
|
||||
- Scenario
|
||||
- Working directory contains 3 files
|
||||
- You stage all and commit
|
||||
- Staging step (`git add …`)
|
||||
- Example:
|
||||
- `git add README test.rb LICENSE`
|
||||
- Git computes a checksum (SHA-1) for each file version
|
||||
- Git stores each file version as a **blob** object
|
||||
- The staging area (index) records the blob checksums for what’s staged
|
||||
- Commit step (`git commit …`)
|
||||
- Example:
|
||||
- `git commit -m "Initial commit"`
|
||||
- Git checksums each directory (here: project root) and stores a **tree** object
|
||||
- Tree object
|
||||
- Lists directory contents
|
||||
- Maps filenames → blob IDs
|
||||
- (And subdirectories → subtree IDs)
|
||||
- Git creates a **commit** object
|
||||
- Contains metadata + pointer to the root tree
|
||||
- Object count after this commit (in this example)
|
||||
- 3 blobs (file contents)
|
||||
- 1 tree (directory listing + blob references)
|
||||
- 1 commit (metadata + pointer to root tree)
|
||||
|
||||
### Commit history: parents create a graph
|
||||
- Each new commit typically
|
||||
- Points to a new snapshot (tree)
|
||||
- Points to its direct parent commit (previous tip)
|
||||
- Merge commits
|
||||
- Have multiple parents
|
||||
- Represent snapshots produced by merges
|
||||
|
||||
### What a branch is (Git definition)
|
||||
- Branch = lightweight movable pointer to a commit (the tip)
|
||||
- Default starting branch name
|
||||
- `master` (historical default name)
|
||||
- Moves forward automatically as you commit on it
|
||||
|
||||
#### Note: “master” is not special
|
||||
- It’s identical to any other branch
|
||||
- It’s common because
|
||||
- `git init` creates it by default
|
||||
- many repos never rename it
|
||||
|
||||
### Creating a new branch (pointer creation only)
|
||||
- Command
|
||||
- `git branch testing`
|
||||
- Effect
|
||||
- Creates a new pointer named `testing`
|
||||
- Points to the same commit you’re currently on
|
||||
- Does **not** switch your working branch
|
||||
|
||||
### HEAD: how Git tracks “current branch”
|
||||
- HEAD in Git
|
||||
- Special pointer to the local branch you currently have checked out
|
||||
- Difference from other VCSs (conceptual)
|
||||
- In Git, HEAD is a pointer to the current local branch (not just “latest revision” in a repo)
|
||||
|
||||
### Seeing branch pointers in `git log`
|
||||
- Useful visualization option
|
||||
- `git log --oneline --decorate`
|
||||
- What `--decorate` shows
|
||||
- Labels like `HEAD -> master`
|
||||
- Other branch pointers (e.g., `testing`) attached to commits
|
||||
|
||||
### Switching branches (checkout)
|
||||
- Switch to an existing branch
|
||||
- `git checkout testing`
|
||||
- Effect
|
||||
- Moves HEAD to point to `testing`
|
||||
- Your next commit will advance `testing` (because HEAD points to it)
|
||||
|
||||
### Committing advances only the checked-out branch pointer
|
||||
- If you commit while on `testing`
|
||||
- `testing` pointer moves forward
|
||||
- `master` pointer stays behind (unchanged)
|
||||
|
||||
### Switching back updates pointers and your working directory
|
||||
- Switch back
|
||||
- `git checkout master`
|
||||
- Checkout does two major things
|
||||
- Moves HEAD to `master`
|
||||
- Resets working directory to match the snapshot at `master`’s tip
|
||||
- Result
|
||||
- Your future work on `master` diverges from the commit you left behind on `testing`
|
||||
|
||||
#### Note: `git log` doesn’t show all branches by default
|
||||
- Default behavior
|
||||
- `git log` shows the history reachable from the currently checked-out branch
|
||||
- To see another branch’s history explicitly
|
||||
- `git log testing`
|
||||
- To see all branches
|
||||
- `git log --all` (often paired with `--graph` and `--decorate`)
|
||||
|
||||
#### Note: switching branches changes working directory files
|
||||
- On branch switch, Git may
|
||||
- add files
|
||||
- remove files
|
||||
- modify files
|
||||
- Safety rule
|
||||
- If Git can’t switch cleanly (because it would overwrite conflicting uncommitted changes), it will block the checkout
|
||||
|
||||
### Divergent history and visualization
|
||||
- When both branches get new commits after diverging
|
||||
- History becomes a DAG with multiple “tips”
|
||||
- View divergence clearly
|
||||
- `git log --oneline --decorate --graph --all`
|
||||
|
||||
### Why Git branches are cheap
|
||||
- A branch is stored as a simple reference (a file) containing
|
||||
- the 40-character SHA-1 of the commit it points to
|
||||
- plus a newline → ~41 bytes written
|
||||
- Consequences
|
||||
- Create/delete branches instantly
|
||||
- Switching is fast because it’s mostly pointer movement + updating working directory snapshot
|
||||
- Contrast: older VCS branching
|
||||
- Often implemented by copying the entire project directory
|
||||
- Can take seconds/minutes depending on repo size
|
||||
- Merge support benefit
|
||||
- Git records parent pointers in commits
|
||||
- Merge-base detection for merges is typically automatic and easy
|
||||
|
||||
### Creating a branch and switching immediately
|
||||
- Common pattern
|
||||
- `git checkout -b <newbranch>`
|
||||
- Git ≥ 2.23 alternative: `git switch`
|
||||
- switch to existing: `git switch <branch>`
|
||||
- create + switch: `git switch -c <newbranch>` (or `--create`)
|
||||
- return to previous branch: `git switch -`
|
||||
|
||||
## Basic Branching and Merging (realistic workflow)
|
||||
- Example workflow goal: develop features while handling urgent production fixes
|
||||
- High-level steps (website scenario)
|
||||
- Work on site
|
||||
- Create branch for a user story
|
||||
- Work on that branch
|
||||
- Urgent hotfix appears
|
||||
- switch to production branch
|
||||
- create hotfix branch
|
||||
- test hotfix
|
||||
- merge hotfix and deploy
|
||||
- return to user story branch
|
||||
|
||||
### Basic Branching example (issue branch + hotfix branch)
|
||||
- Starting assumption
|
||||
- You already have a few commits on `master`
|
||||
|
||||
#### Create and work on a topic branch (issue #53)
|
||||
- Create + switch
|
||||
- `git checkout -b iss53`
|
||||
- Shorthand for
|
||||
- `git branch iss53`
|
||||
- `git checkout iss53`
|
||||
- Do work and commit
|
||||
- edit `index.html`
|
||||
- `git commit -a -m "Create new footer [issue 53]"`
|
||||
- Result
|
||||
- `iss53` advances (HEAD points to it)
|
||||
|
||||
#### Interrupt with urgent hotfix (without mixing in feature work)
|
||||
- Key rule before switching branches
|
||||
- If working directory or staging area has uncommitted changes that would conflict, Git blocks switching
|
||||
- Best practice: keep a clean working state when switching
|
||||
- Mentioned workarounds (covered later): stashing, commit amending
|
||||
- Switch back to production/stable branch
|
||||
- `git checkout master`
|
||||
- What you gain
|
||||
- working directory restored to `master` snapshot (pre-issue work)
|
||||
- you can focus on hotfix cleanly
|
||||
|
||||
#### Create and finish the hotfix
|
||||
- Create + switch to hotfix branch
|
||||
- `git checkout -b hotfix`
|
||||
- Fix and commit
|
||||
- edit `index.html`
|
||||
- `git commit -a -m "Fix broken email address"`
|
||||
|
||||
#### Merge hotfix into master (fast-forward)
|
||||
- Merge steps
|
||||
- `git checkout master`
|
||||
- `git merge hotfix`
|
||||
- Why it’s a “fast-forward” merge
|
||||
- hotfix tip commit is directly ahead of master tip commit
|
||||
- No divergence to reconcile
|
||||
- Git simply moves the `master` pointer forward
|
||||
- Deployment outcome
|
||||
- master now points to a commit whose snapshot includes the hotfix
|
||||
- you can deploy production fix
|
||||
|
||||
#### Delete completed hotfix branch
|
||||
- Delete (safe when merged)
|
||||
- `git branch -d hotfix`
|
||||
- Rationale
|
||||
- master already contains the hotfix work
|
||||
|
||||
#### Return to feature branch (iss53) and continue
|
||||
- Switch back
|
||||
- `git checkout iss53`
|
||||
- Continue work and commit
|
||||
- `git commit -a -m "Finish the new footer [issue 53]"`
|
||||
- Important note: hotfix isn’t in `iss53` automatically
|
||||
- Options if needed
|
||||
- merge master into iss53: `git merge master`
|
||||
- or wait until iss53 is merged back into master
|
||||
|
||||
### Basic Merging (merge feature branch into master)
|
||||
- When issue #53 is done
|
||||
- `git checkout master`
|
||||
- `git merge iss53`
|
||||
- Why this merge differs from the hotfix merge
|
||||
- histories diverged earlier
|
||||
- master tip is not an ancestor of iss53 tip
|
||||
- Git performs a three-way merge
|
||||
- Inputs
|
||||
- snapshot at master tip
|
||||
- snapshot at iss53 tip
|
||||
- snapshot at their common ancestor
|
||||
- Output
|
||||
- a new merged snapshot
|
||||
- a new merge commit
|
||||
- “special” because it has more than one parent
|
||||
- Merge strategy note (as shown in output)
|
||||
- merge made by the `recursive` strategy (typical default for two heads)
|
||||
|
||||
#### Clean up merged branch
|
||||
- Delete iss53 after merge
|
||||
- `git branch -d iss53`
|
||||
|
||||
### Basic Merge Conflicts (when Git cannot auto-merge)
|
||||
- When conflicts occur
|
||||
- both branches changed the same part of the same file differently
|
||||
- What `git merge` does on conflict
|
||||
- stops and reports conflict(s)
|
||||
- does NOT create the merge commit yet
|
||||
- requires manual resolution
|
||||
|
||||
#### Identify unmerged paths
|
||||
- Use
|
||||
- `git status`
|
||||
- Status shows
|
||||
- you are in a merging state
|
||||
- list of “unmerged paths”
|
||||
- hints to:
|
||||
- fix conflicts
|
||||
- `git add` files to mark resolution
|
||||
- then `git commit` to conclude merge
|
||||
|
||||
#### Conflict markers inserted into files
|
||||
- Git writes markers like
|
||||
- `<<<<<<<` (start of conflict block)
|
||||
- `=======` (separator)
|
||||
- `>>>>>>>` (end of block)
|
||||
- Meaning
|
||||
- Top section = HEAD version (current branch at merge time, e.g., master)
|
||||
- Bottom section = incoming branch version (e.g., iss53)
|
||||
|
||||
#### Resolve and mark as resolved
|
||||
- Manual resolution workflow
|
||||
- edit file(s)
|
||||
- choose one side or combine them
|
||||
- remove all markers
|
||||
- Mark resolution
|
||||
- `git add <file>` for each conflicted file
|
||||
- staging indicates conflict resolved in Git
|
||||
|
||||
#### Using a merge tool (optional)
|
||||
- Run
|
||||
- `git mergetool`
|
||||
- Behavior
|
||||
- opens a visual merge tool
|
||||
- helps walk through conflict resolution
|
||||
- If not configured
|
||||
- Git warns `merge.tool` isn’t configured
|
||||
- offers possible tool choices (platform dependent)
|
||||
- you can specify an alternative tool name
|
||||
|
||||
#### Finalize the merge
|
||||
- Verify state
|
||||
- `git status`
|
||||
- typically indicates “all conflicts fixed” but merge still in progress
|
||||
- Conclude
|
||||
- `git commit`
|
||||
- Merge commit message details
|
||||
- default message mentions merged branch
|
||||
- often lists conflicts
|
||||
- note in message references merge metadata (e.g., `.git/MERGE_HEAD`)
|
||||
- you may edit message to explain how/why conflicts were resolved
|
||||
- Reference for deeper conflict handling
|
||||
- “Advanced Merging” (mentioned as later coverage)
|
||||
|
||||
## Branch Management (everyday utilities)
|
||||
- `git branch` does more than create/delete
|
||||
- provides multiple views and filters of branch state
|
||||
|
||||
### Listing branches
|
||||
- `git branch`
|
||||
- lists local branches
|
||||
- `*` shows current branch (HEAD points here)
|
||||
|
||||
### See last commit on each branch
|
||||
- `git branch -v`
|
||||
- shows branch tip commit SHA + message summary
|
||||
|
||||
### Filter by merge status
|
||||
- `git branch --merged`
|
||||
- branches already merged into current branch
|
||||
- usually safe to delete those (except the current `*` branch)
|
||||
- `git branch --no-merged`
|
||||
- branches not merged into current branch
|
||||
- deletion safety
|
||||
- `git branch -d <branch>` fails if not fully merged
|
||||
- `git branch -D <branch>` forces deletion (discarding unmerged work)
|
||||
|
||||
#### Note: merge-status filters are relative to a base
|
||||
- Default base
|
||||
- current branch (if no argument given)
|
||||
- You can compare relative to a different branch without checking it out
|
||||
- `git branch --no-merged master`
|
||||
|
||||
## Changing a branch name (rename)
|
||||
- Safety warning
|
||||
- do not rename branches still used by other collaborators
|
||||
- do not rename default branches (master/main/etc.) without reading next section
|
||||
|
||||
### Rename locally
|
||||
- `git branch --move bad-branch-name corrected-branch-name`
|
||||
- Effect
|
||||
- preserves history
|
||||
- changes only your local ref name initially
|
||||
|
||||
### Publish the renamed branch and set upstream
|
||||
- `git push --set-upstream origin corrected-branch-name`
|
||||
- Effect
|
||||
- creates the new remote branch name
|
||||
- configures tracking
|
||||
|
||||
### Remove the old remote branch name
|
||||
- `git push origin --delete bad-branch-name`
|
||||
- Effect
|
||||
- fully replaces the bad remote name with the corrected one
|
||||
|
||||
### Verification
|
||||
- `git branch --all`
|
||||
- shows local branches and `remotes/origin/...` remote-tracking refs
|
||||
|
||||
## Changing the master branch name (e.g., `master` → `main`)
|
||||
- High-impact warning
|
||||
- renaming default branch can break
|
||||
- integrations/services
|
||||
- helper utilities
|
||||
- build/release scripts
|
||||
- any references in code, configs, docs
|
||||
- consult collaborators
|
||||
- search/update all references to the old name
|
||||
|
||||
### Local rename
|
||||
- `git branch --move master main`
|
||||
- Result
|
||||
- local `master` ref no longer exists
|
||||
- local `main` points to the same commit tip
|
||||
|
||||
### Push and set upstream
|
||||
- `git push --set-upstream origin main`
|
||||
- Result
|
||||
- remote now has `main`
|
||||
- remote may still have `master`
|
||||
- remote HEAD may still point to `origin/master` until host settings change
|
||||
|
||||
### Migration checklist (must update external references)
|
||||
- Dependent projects
|
||||
- update code/config referencing old branch
|
||||
- Test runner configs
|
||||
- update any branch-name assumptions
|
||||
- Build/release scripts
|
||||
- update target branch names
|
||||
- Repo host settings
|
||||
- default branch
|
||||
- merge rules / protections
|
||||
- other branch-name-based settings
|
||||
- Documentation
|
||||
- update old references
|
||||
- Pull requests
|
||||
- close/merge/retarget PRs aimed at old branch
|
||||
|
||||
### Delete old remote branch after transition
|
||||
- `git push origin --delete master`
|
||||
|
||||
## Branching Workflows (patterns enabled by lightweight branches)
|
||||
- Goal
|
||||
- choose a branching strategy that matches team/release needs
|
||||
- Key enabler
|
||||
- easy repeated three-way merges over time
|
||||
|
||||
### Long-Running Branches (progressive stability)
|
||||
- Concept
|
||||
- keep multiple always-open branches for different stability levels
|
||||
- merge “upwards” as code becomes stable
|
||||
- Common pattern
|
||||
- `master`: only stable/released (or release-candidate) code
|
||||
- `develop` / `next`: integration/testing branch; can be unstable
|
||||
- topic branches merged into develop/next for testing before master
|
||||
- How to think about “stability”
|
||||
- linear commit history view
|
||||
- stable branches are “behind” (older, tested commits)
|
||||
- bleeding-edge branches are “ahead” (newer, less proven commits)
|
||||
- “silo” view
|
||||
- commits graduate to more stable silos once fully tested
|
||||
- Multi-level stability in large projects
|
||||
- additional branches like `proposed` / `pu` (proposed updates)
|
||||
- idea: not everything is ready for `next` or `master` immediately
|
||||
- Note
|
||||
- not required, but often helpful for large/complex projects
|
||||
|
||||
### Topic Branches (short-lived branches)
|
||||
- Definition
|
||||
- branch created for a single feature/bugfix/experiment
|
||||
- typically merged and deleted after completion
|
||||
- Why Git makes this common
|
||||
- branch creation/merging is cheap → can do it many times a day
|
||||
- Benefits
|
||||
- clean context switching (work isolated by topic)
|
||||
- easier code review (topic’s commits grouped)
|
||||
- flexible integration timing (minutes, days, months later)
|
||||
- can merge in any order regardless of creation order
|
||||
- Example topology from the chapter
|
||||
- work on `master`
|
||||
- branch `iss91` (issue work)
|
||||
- branch `iss91v2` off `iss91` (alternate approach)
|
||||
- return to `master` and continue other work
|
||||
- branch `dumbidea` off `master` (experimental idea)
|
||||
- outcome
|
||||
- discard `iss91` if inferior
|
||||
- merge `iss91v2` and `dumbidea` if chosen
|
||||
- Reminder: local operations
|
||||
- branching/merging is local-only until you fetch/push/pull
|
||||
- Reference mention
|
||||
- more workflow discussion later in “Distributed Git”
|
||||
|
||||
## Remote Branches (remote references + remote-tracking branches)
|
||||
### Remote references overview
|
||||
- Remote repos contain references (pointers) to
|
||||
- branches
|
||||
- tags
|
||||
- other refs
|
||||
- Ways to inspect
|
||||
- `git ls-remote <remote>` (full list of remote refs)
|
||||
- `git remote show <remote>` (focus on remote branches + info)
|
||||
|
||||
### Remote-tracking branches
|
||||
- Definition
|
||||
- local references that record the state of remote branches
|
||||
- you can’t move them yourself
|
||||
- Git updates them during network communication
|
||||
- Naming
|
||||
- `<remote>/<branch>`
|
||||
- Examples
|
||||
- `origin/master`
|
||||
- `origin/iss53`
|
||||
- Mental model
|
||||
- bookmarks showing where a remote branch was last time you connected
|
||||
|
||||
### Clone example (how origin/master appears)
|
||||
- When cloning from a server
|
||||
- Git names the remote `origin` by default
|
||||
- downloads data
|
||||
- creates `origin/master` (remote-tracking)
|
||||
- creates your local `master` starting at same commit as origin’s master
|
||||
|
||||
#### Note: “origin” is not special
|
||||
- It’s just the default name created by `git clone`
|
||||
- You can rename the default remote at clone time
|
||||
- `git clone -o booyah ...` → remote-tracking branch becomes `booyah/master`
|
||||
|
||||
### Divergence between local and remote
|
||||
- If you commit locally and someone else pushes to the remote
|
||||
- histories diverge
|
||||
- `origin/master` does not move until you communicate
|
||||
|
||||
### Fetching updates remote-tracking branches
|
||||
- `git fetch origin`
|
||||
- contacts remote
|
||||
- downloads objects you don’t have
|
||||
- updates pointers like `origin/master` to newer commits
|
||||
|
||||
### Multiple remotes
|
||||
- Add another remote
|
||||
- `git remote add teamone <url>`
|
||||
- Fetch it
|
||||
- `git fetch teamone`
|
||||
- Possible outcome
|
||||
- if teamone has only a subset of commits you already have from origin:
|
||||
- fetch downloads no new objects
|
||||
- still updates `teamone/master` pointer to match teamone’s master tip
|
||||
|
||||
## Pushing (sharing branches)
|
||||
### Why pushing is explicit
|
||||
- Local branches do not automatically sync to remotes
|
||||
- Benefit
|
||||
- you can keep private local branches
|
||||
- push only branches you intend to share/collaborate on
|
||||
|
||||
### Push a branch
|
||||
- Pattern
|
||||
- `git push <remote> <branch>`
|
||||
- Example
|
||||
- `git push origin serverfix`
|
||||
- What Git expands it to (conceptual)
|
||||
- `refs/heads/serverfix:refs/heads/serverfix`
|
||||
- Push local branch to a different remote branch name
|
||||
- `git push origin serverfix:awesomebranch`
|
||||
|
||||
### Authentication convenience (HTTPS)
|
||||
- HTTPS push commonly prompts for username/password
|
||||
- To avoid typing credentials repeatedly
|
||||
- credential cache example:
|
||||
- `git config --global credential.helper cache`
|
||||
- reference mentioned: “Credential Storage” (for other options)
|
||||
|
||||
### After someone else fetches
|
||||
- Fetching a pushed branch
|
||||
- `git fetch origin`
|
||||
- Result
|
||||
- creates/updates a remote-tracking ref (e.g., `origin/serverfix`)
|
||||
- does NOT create a local editable branch automatically
|
||||
|
||||
### Using fetched remote-tracking branch work
|
||||
- Merge directly into current branch
|
||||
- `git merge origin/serverfix`
|
||||
- Create a local branch based on it (editable) and track it
|
||||
- `git checkout -b serverfix origin/serverfix`
|
||||
|
||||
## Tracking Branches (local branches that track upstream)
|
||||
### Definitions
|
||||
- Tracking branch
|
||||
- local branch tied to a remote-tracking branch
|
||||
- Upstream branch
|
||||
- remote-tracking branch the local branch tracks
|
||||
|
||||
### Why tracking matters
|
||||
- On a tracking branch, `git pull` can automatically
|
||||
- fetch from the right remote
|
||||
- merge the right branch
|
||||
|
||||
### How tracking branches are created
|
||||
- Common creation form
|
||||
- `git checkout -b <branch> <remote>/<branch>`
|
||||
- Shorthand
|
||||
- `git checkout --track origin/serverfix`
|
||||
- Extra shortcut
|
||||
- `git checkout serverfix`
|
||||
- works if
|
||||
- local `serverfix` doesn’t exist, and
|
||||
- exactly one remote has `serverfix`
|
||||
- Different local name than remote branch
|
||||
- `git checkout -b sf origin/serverfix`
|
||||
- local `sf` tracks `origin/serverfix`
|
||||
|
||||
### Set or change upstream later
|
||||
- `git branch -u origin/serverfix`
|
||||
- also available as `--set-upstream-to`
|
||||
|
||||
### Upstream shorthand in commands
|
||||
- `@{upstream}` or `@{u}`
|
||||
- references the upstream branch of the current branch
|
||||
- Example
|
||||
- `git merge @{u}` instead of `git merge origin/master` (when master tracks origin/master)
|
||||
|
||||
### Inspect tracking status and ahead/behind
|
||||
- `git branch -vv`
|
||||
- shows local branches
|
||||
- indicates upstream tracking target
|
||||
- shows ahead/behind counts
|
||||
- Interpreting counts
|
||||
- ahead N → N local commits not pushed
|
||||
- behind N → N remote commits not merged locally
|
||||
- Cache caveat
|
||||
- ahead/behind shown is from last fetch; command doesn’t contact server
|
||||
- To refresh counts
|
||||
- `git fetch --all; git branch -vv`
|
||||
|
||||
## Pulling (fetch + merge convenience)
|
||||
- `git fetch`
|
||||
- downloads new data
|
||||
- does not modify working directory
|
||||
- leaves integration to you (merge/rebase)
|
||||
- `git pull`
|
||||
- in most cases = `fetch` immediately followed by `merge`
|
||||
- uses tracking (upstream) info to pick remote + branch
|
||||
- Guidance from the chapter
|
||||
- explicit `fetch` + `merge` is often clearer than the “magic” of `pull`
|
||||
|
||||
## Deleting Remote Branches
|
||||
- When a remote branch is no longer needed
|
||||
- merged into mainline/stable branch on the server
|
||||
- Delete remote branch pointer
|
||||
- `git push origin --delete serverfix`
|
||||
- Effect
|
||||
- removes the branch pointer on the server
|
||||
- server may keep underlying objects until garbage collection
|
||||
- accidental deletions can often be recovered before GC runs
|
||||
|
||||
## Rebasing (the other integration strategy)
|
||||
- Two main ways to integrate changes between branches
|
||||
- `merge`
|
||||
- `rebase`
|
||||
|
||||
### The Basic Rebase (replaying commits)
|
||||
- Starting situation
|
||||
- branches diverged; each has unique commits
|
||||
- Merge recap (already covered earlier)
|
||||
- three-way merge of:
|
||||
- tip snapshot A
|
||||
- tip snapshot B
|
||||
- common ancestor snapshot
|
||||
- creates a new snapshot + merge commit
|
||||
- Rebase concept
|
||||
- take the patch introduced by commits on one branch
|
||||
- reapply them on top of another branch’s tip
|
||||
- Example commands
|
||||
- `git checkout experiment`
|
||||
- `git rebase master`
|
||||
- Internal steps (conceptual)
|
||||
- find common ancestor between current branch and target branch
|
||||
- compute diffs for each commit on current branch since ancestor
|
||||
- save diffs temporarily
|
||||
- reset current branch to target tip
|
||||
- apply diffs sequentially (creating new commits with new SHAs)
|
||||
- After rebase
|
||||
- integrate by fast-forward merge
|
||||
- `git checkout master`
|
||||
- `git merge experiment`
|
||||
- Result comparison
|
||||
- final snapshot content is the same as with merge
|
||||
- history is different
|
||||
- rebase → linear-looking history
|
||||
- merge → preserves the true parallel shape
|
||||
- Common use case (contributing workflow)
|
||||
- rebase your work onto `origin/master` before submitting patches
|
||||
- maintainer can integrate via fast-forward / clean apply
|
||||
- Core conceptual distinction
|
||||
- rebase: replay changes in order introduced
|
||||
- merge: combine endpoints and record a merge
|
||||
|
||||
### More Interesting Rebases (rebasing a branch off another topic branch)
|
||||
- Scenario
|
||||
- topic branch `server` created from master; commits added
|
||||
- topic branch `client` created from `server`; commits added
|
||||
- later additional commits added to `server`
|
||||
- Goal
|
||||
- ship client changes now (merge into master)
|
||||
- delay server changes until tested
|
||||
- Use `--onto`
|
||||
- `git rebase --onto master server client`
|
||||
- Meaning
|
||||
- take commits on `client` that are not on `server`
|
||||
- replay them as if `client` started from `master`
|
||||
- Integrate client quickly
|
||||
- `git checkout master`
|
||||
- `git merge client` (fast-forward)
|
||||
- Integrate server later without manual checkout
|
||||
- `git rebase master server`
|
||||
- checks out `server` and replays onto master
|
||||
- `git checkout master`
|
||||
- `git merge server` (fast-forward)
|
||||
- Cleanup
|
||||
- delete topic branches once integrated
|
||||
- `git branch -d client`
|
||||
- `git branch -d server`
|
||||
|
||||
### The Perils of Rebasing (rewriting published history)
|
||||
- The one-line rule
|
||||
- Do not rebase commits that exist outside your repository and that people may have based work on
|
||||
- Why rebasing public commits is dangerous
|
||||
- rebase abandons existing commits and creates new ones
|
||||
- new commits have different SHAs
|
||||
- collaborators who based work on old SHAs must reconcile mismatched history
|
||||
- Example failure pattern (from the chapter)
|
||||
- you clone and do work
|
||||
- someone else pushes a merge to the central server
|
||||
- later they rebase their work and `push --force` (rewriting server history)
|
||||
- you fetch new commits
|
||||
- if you `git pull` normally, you may create a merge combining old + new lines
|
||||
- can lead to duplicate-looking commits (same message/author/date) with different IDs
|
||||
- pushing that back can reintroduce commits the other dev tried to eliminate
|
||||
- Social consequence emphasized
|
||||
- if you rewrite shared history, teammates will have to re-merge and untangle confusion
|
||||
|
||||
### Rebase When You Rebase (recovering after a force-push)
|
||||
- Problem after force-push
|
||||
- determine which commits are uniquely yours vs rewritten copies
|
||||
- Patch-id concept
|
||||
- besides commit SHA-1, Git can compute a checksum based on the patch content (“patch-id”)
|
||||
- How rebase helps
|
||||
- rebasing onto the updated target can let Git:
|
||||
- identify which commits are already represented (same patch)
|
||||
- replay only the unique commits
|
||||
- Example approach
|
||||
- `git rebase teamone/master`
|
||||
- What Git may compute during this recovery rebase (as described)
|
||||
- determine commits unique to your branch
|
||||
- exclude merge commits from replay
|
||||
- detect commits that were rewritten but represent the same patch in the target
|
||||
- apply remaining unique commits on top of the updated branch
|
||||
- Limitation noted
|
||||
- works best if rewritten commits are almost the same patch
|
||||
- otherwise Git may not detect duplication and may reapply a similar patch (possibly failing)
|
||||
- Convenience options
|
||||
- `git pull --rebase` instead of normal pull
|
||||
- or manual: `git fetch` then `git rebase <remote>/<branch>`
|
||||
- configure default:
|
||||
- `git config --global pull.rebase true`
|
||||
- Safety guideline recap
|
||||
- safe: rebase commits that never left your machine
|
||||
- generally ok: rebase pushed commits if nobody based work on them
|
||||
- risky: rebase publicly shared commits → coordinate + warn others to use `pull --rebase`
|
||||
|
||||
### Rebase vs. Merge (choosing based on what “history” means)
|
||||
- Two viewpoints on commit history
|
||||
- History as a factual record
|
||||
- commit history documents what actually happened
|
||||
- rewriting is “lying” about events
|
||||
- merge commits reflect real parallel work
|
||||
- History as a curated story
|
||||
- raw development includes missteps and dead ends
|
||||
- before mainline, rewrite history to tell a clearer story
|
||||
- tools mentioned: `rebase`, `filter-branch`
|
||||
- Conclusion
|
||||
- no universal best choice; depends on team/project
|
||||
- Practical “best of both worlds” guideline
|
||||
- rebase local changes before pushing (clean up)
|
||||
- never rebase anything you’ve pushed somewhere shared/public
|
||||
|
||||
## Summary (skills this chapter expects you to have now)
|
||||
- Branch creation and switching
|
||||
- create branches, move between them
|
||||
- understand HEAD as “current branch pointer”
|
||||
- Merging
|
||||
- fast-forward merges
|
||||
- three-way merges and merge commits (multiple parents)
|
||||
- resolve conflicts (markers, `status`, `add`, `mergetool`, final `commit`)
|
||||
- Branch management
|
||||
- list branches and identify current branch
|
||||
- inspect branch tips (`-v`)
|
||||
- find merged/unmerged branches (`--merged`, `--no-merged`)
|
||||
- delete safely (`-d`) or forcibly (`-D`)
|
||||
- rename branches (local + remote cleanup)
|
||||
- rename default branch (master/main) with ecosystem updates
|
||||
- Collaboration with remotes
|
||||
- remote-tracking branches, fetch/push/pull behaviors
|
||||
- create tracking branches and set upstream
|
||||
- delete remote branches
|
||||
- Rebasing
|
||||
- what rebase does and why it can make history linear
|
||||
- advanced rebase (`--onto`)
|
||||
- when rebasing is dangerous and how to mitigate with `pull --rebase`
|
||||
- Next topic preview (mentioned)
|
||||
- how to run your own Git repository-hosting server
|
||||
```
|
||||
Reference in New Issue
Block a user