docs(git): add research reference corpus for git plugin
11 topic files covering the full git surface area needed for skill and agent authoring: overview, installation, configuration, cli-reference, commits (Conventional Commits v1.0.0), branching-merging, submodules, worktrees, gitflow, remotes (push/pull/fetch/force-with-lease), and history-inspection (bisect, log --format, pickaxe, --diff-filter). Includes sources.md mapping all 13 source documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0147vXtL5sP6vorDdqXGJJU9
This commit is contained in:
180
plugins/git/docs/research/docs/git/branching-merging.md
Normal file
180
plugins/git/docs/research/docs/git/branching-merging.md
Normal file
@@ -0,0 +1,180 @@
|
||||
---
|
||||
topic: branching-merging
|
||||
source_keys:
|
||||
- context7-git-htmldocs
|
||||
---
|
||||
|
||||
## Branching Model
|
||||
|
||||
Git branches are cheap: each is just a ref file (41 bytes) pointing to a commit. Creating, switching, and deleting branches is a sub-millisecond operation regardless of repo size.
|
||||
|
||||
The canonical branching workflow is:
|
||||
1. Create a branch from a stable point (usually `main` or `develop`).
|
||||
2. Commit work on the branch.
|
||||
3. Integrate back via merge or rebase.
|
||||
4. Delete the branch.
|
||||
|
||||
## Creating and Switching Branches
|
||||
|
||||
```bash
|
||||
git switch -c <branch> # create and switch (preferred, Git 2.23+)
|
||||
git switch -c <branch> <start> # from a specific commit or remote branch
|
||||
git switch <existing-branch> # switch to existing
|
||||
git switch - # switch back to previous branch
|
||||
|
||||
# Legacy equivalents
|
||||
git checkout -b <branch>
|
||||
git checkout <branch>
|
||||
```
|
||||
|
||||
When switching, Git updates `HEAD`, the index, and the working tree. Uncommitted changes that conflict with the target branch will block the switch (Git refuses to overwrite them).
|
||||
|
||||
## Merge Strategies
|
||||
|
||||
### Fast-forward merge
|
||||
|
||||
If the target branch has not diverged from the source, Git simply advances the branch pointer — no merge commit is created. History remains linear.
|
||||
|
||||
```bash
|
||||
git merge <branch> # fast-forward if possible
|
||||
```
|
||||
|
||||
### True merge (--no-ff)
|
||||
|
||||
Forces a merge commit even when a fast-forward is possible. Preserves the fact that a group of commits came from a branch. Required by Gitflow on all supporting-branch merges.
|
||||
|
||||
```bash
|
||||
git merge --no-ff <branch>
|
||||
git merge --no-ff -m "Merge feature/X" <branch>
|
||||
```
|
||||
|
||||
### Squash merge
|
||||
|
||||
Collapses all commits from the source branch into a single staged change, which you then commit manually. Keeps the target branch history clean; discards individual commit granularity.
|
||||
|
||||
```bash
|
||||
git merge --squash <branch>
|
||||
git commit -m "feat: add X" # separate commit step required
|
||||
```
|
||||
|
||||
### Octopus merge
|
||||
|
||||
Merging more than two branches simultaneously. Git uses this by default when you pass multiple branch names. Fails on conflicts — use sequential two-way merges when conflicts are expected.
|
||||
|
||||
```bash
|
||||
git merge branch-a branch-b branch-c
|
||||
```
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
When Git cannot auto-merge, it inserts conflict markers into the affected files and stops:
|
||||
|
||||
```
|
||||
<<<<<<< HEAD
|
||||
current branch content
|
||||
=======
|
||||
incoming branch content
|
||||
>>>>>>> feature/x
|
||||
```
|
||||
|
||||
Resolution workflow:
|
||||
|
||||
```bash
|
||||
# 1. Find conflicted files
|
||||
git status
|
||||
|
||||
# 2. Edit each file to resolve markers, then stage
|
||||
git add <resolved-file>
|
||||
|
||||
# 3. Continue
|
||||
git merge --continue # or git commit if --continue is unavailable
|
||||
|
||||
# Alternatively: abort and reset
|
||||
git merge --abort
|
||||
```
|
||||
|
||||
Tools:
|
||||
```bash
|
||||
git mergetool # open configured merge.tool (meld, vimdiff, etc.)
|
||||
git diff --diff-filter=U # show only conflicted files
|
||||
```
|
||||
|
||||
## Rebase
|
||||
|
||||
Rebase replays a sequence of commits on top of a new base, rewriting SHAs in the process. The result is a linear history with no merge commits.
|
||||
|
||||
```bash
|
||||
git rebase main # rebase current branch onto main
|
||||
git rebase --onto <newbase> <upstream> <branch> # transplant a range
|
||||
```
|
||||
|
||||
**Interactive rebase** — rewrites local history:
|
||||
|
||||
```bash
|
||||
git rebase -i HEAD~5 # edit last 5 commits
|
||||
```
|
||||
|
||||
Interactive commands:
|
||||
| Command | Effect |
|
||||
|---|---|
|
||||
| `pick` | Keep commit as-is |
|
||||
| `reword` | Keep commit but edit message |
|
||||
| `edit` | Pause for amending |
|
||||
| `squash` | Fold into previous commit (keep message) |
|
||||
| `fixup` | Fold into previous commit (discard message) |
|
||||
| `drop` | Remove commit entirely |
|
||||
| `exec` | Run a shell command |
|
||||
|
||||
**Golden rule of rebasing:** Never rebase commits that have been pushed to a shared branch. Rebase rewrites history; force-pushing to shared branches breaks other people's local copies.
|
||||
|
||||
## Conflict Resolution During Rebase
|
||||
|
||||
```bash
|
||||
# Resolve each conflicting commit, then:
|
||||
git add <file>
|
||||
git rebase --continue
|
||||
|
||||
# Skip a problematic commit:
|
||||
git rebase --skip
|
||||
|
||||
# Abort and return to pre-rebase state:
|
||||
git rebase --abort
|
||||
```
|
||||
|
||||
## Cherry-picking
|
||||
|
||||
Applies the diff introduced by a specific commit onto the current branch as a new commit.
|
||||
|
||||
```bash
|
||||
git cherry-pick <sha> # apply one commit
|
||||
git cherry-pick <sha-a>^..<sha-b> # apply a range (inclusive)
|
||||
git cherry-pick -n <sha> # stage without committing (for editing)
|
||||
```
|
||||
|
||||
Cherry-picking does not maintain a history link between branches. For sharing code between branches, prefer merge or rebase unless you specifically need to apply an isolated patch.
|
||||
|
||||
## Tracking Branches
|
||||
|
||||
A tracking relationship lets `git pull` and `git push` know which remote branch to target.
|
||||
|
||||
```bash
|
||||
git push -u origin <branch> # push and set upstream
|
||||
git branch --set-upstream-to=origin/<branch> # set tracking on existing branch
|
||||
git branch -vv # show tracking info for all branches
|
||||
```
|
||||
|
||||
`@{upstream}` (or `@{u}`) is shorthand for the tracked remote branch:
|
||||
```bash
|
||||
git log @{u}..HEAD # commits not yet pushed
|
||||
git diff @{u} # diff against upstream
|
||||
```
|
||||
|
||||
## Comparing Branches
|
||||
|
||||
```bash
|
||||
git log main..feature # commits in feature not in main
|
||||
git log feature..main # commits in main not in feature
|
||||
git log --left-right main...feature # both diverging sets (symmetric diff)
|
||||
git diff main...feature # diff from common ancestor to feature tip
|
||||
git merge-base main feature # print the common ancestor commit
|
||||
```
|
||||
212
plugins/git/docs/research/docs/git/cli-reference.md
Normal file
212
plugins/git/docs/research/docs/git/cli-reference.md
Normal file
@@ -0,0 +1,212 @@
|
||||
---
|
||||
topic: cli-reference
|
||||
source_keys:
|
||||
- context7-git-htmldocs
|
||||
- git-scm-docs
|
||||
---
|
||||
|
||||
## Setup and Init
|
||||
|
||||
```bash
|
||||
git init [<directory>] # initialise new repo (or reinit existing)
|
||||
git init --bare # bare repo (no working tree; used as remote)
|
||||
git clone <url> [<directory>] # clone a remote repo
|
||||
git clone --recurse-submodules # clone including all submodules
|
||||
git clone --depth <n> # shallow clone (only last n commits)
|
||||
git clone --filter=blob:none # blobless partial clone
|
||||
```
|
||||
|
||||
## Staging and Status
|
||||
|
||||
```bash
|
||||
git status # show working tree and staging area state
|
||||
git status -s # short format
|
||||
git add <file> # stage a file
|
||||
git add -p # interactively stage hunks
|
||||
git add -A # stage all changes including deletions
|
||||
git rm <file> # remove file from index and working tree
|
||||
git rm --cached <file> # unstage (remove from index only)
|
||||
git mv <old> <new> # rename/move a file
|
||||
git diff # unstaged changes
|
||||
git diff --cached # staged changes (what will be committed)
|
||||
git diff HEAD # all uncommitted changes
|
||||
git restore <file> # discard working tree changes (Git 2.23+)
|
||||
git restore --staged <file> # unstage (Git 2.23+)
|
||||
```
|
||||
|
||||
## Committing
|
||||
|
||||
```bash
|
||||
git commit -m "<message>" # commit with inline message
|
||||
git commit # open editor for message
|
||||
git commit -a # stage tracked changes and commit in one step
|
||||
git commit --amend # rewrite the most recent commit (local only)
|
||||
git commit --amend --no-edit # amend without changing the message
|
||||
git commit --allow-empty # commit with no changes (useful for triggers)
|
||||
```
|
||||
|
||||
### Key `git commit` Flags
|
||||
|
||||
| Flag | Meaning |
|
||||
|---|---|
|
||||
| `-m <msg>` | Inline message; multiple `-m` flags become separate paragraphs |
|
||||
| `-F <file>` | Read message from file; `-` reads from stdin |
|
||||
| `-a` | Auto-stage modified tracked files |
|
||||
| `-n` / `--no-verify` | Skip pre-commit and commit-msg hooks |
|
||||
| `--author "<Name> <email>"` | Override author |
|
||||
| `--date <date>` | Override author date |
|
||||
| `--squash=<commit>` | Prefix message with "squash!" for use with `rebase --autosquash` |
|
||||
| `--fixup=<commit>` | Prefix message with "fixup!" for `rebase --autosquash` |
|
||||
| `--reset-author` | Reassign authorship to the committer (use with `--amend`) |
|
||||
| `--trailer <token>:<value>` | Append a footer trailer to the message |
|
||||
| `--cleanup=<mode>` | Control message whitespace handling: `strip`, `whitespace`, `verbatim`, `scissors` |
|
||||
|
||||
## Branching
|
||||
|
||||
```bash
|
||||
git branch # list local branches
|
||||
git branch -a # list local and remote branches
|
||||
git branch -vv # show tracking info and last commit
|
||||
git branch <name> # create branch at current HEAD
|
||||
git branch <name> <start> # create branch at specific commit
|
||||
git branch -d <name> # delete (safe — refuses if unmerged)
|
||||
git branch -D <name> # delete (force)
|
||||
git branch -m <old> <new> # rename branch
|
||||
git branch --set-upstream-to=origin/<branch> # set tracking
|
||||
git switch <branch> # switch to branch (Git 2.23+)
|
||||
git switch -c <branch> # create and switch (Git 2.23+)
|
||||
git checkout <branch> # switch (legacy)
|
||||
git checkout -b <branch> # create and switch (legacy)
|
||||
```
|
||||
|
||||
## Merging
|
||||
|
||||
```bash
|
||||
git merge <branch> # merge branch into current branch
|
||||
git merge --no-ff <branch> # always create a merge commit
|
||||
git merge --squash <branch> # squash into a single staged change
|
||||
git merge --abort # cancel an in-progress merge
|
||||
git merge --continue # continue after conflict resolution
|
||||
git merge -m "<msg>" <branch> # custom merge commit message
|
||||
git merge --into-name <branch> # override branch name in default message
|
||||
```
|
||||
|
||||
## Rebasing
|
||||
|
||||
```bash
|
||||
git rebase <base> # rebase current branch onto base
|
||||
git rebase -i HEAD~<n> # interactive rebase of last n commits
|
||||
git rebase -i <commit> # interactive rebase from commit onwards
|
||||
git rebase --onto <newbase> <upstream> <branch> # transplant branch
|
||||
git rebase --continue # continue after conflict resolution
|
||||
git rebase --abort # restore pre-rebase state
|
||||
git rebase --skip # skip the conflicting commit
|
||||
git rebase --quit # abort but keep HEAD position
|
||||
git rebase --autosquash # auto-apply fixup!/squash! commits
|
||||
```
|
||||
|
||||
Interactive rebase `pick` commands: `pick`, `reword`, `edit`, `squash`, `fixup`, `drop`, `exec`, `break`, `label`, `reset`, `merge`.
|
||||
|
||||
## Cherry-picking
|
||||
|
||||
```bash
|
||||
git cherry-pick <commit> # apply a commit onto current branch
|
||||
git cherry-pick <a>..<b> # apply a range (exclusive of a)
|
||||
git cherry-pick <a>^..<b> # apply a range (inclusive of a)
|
||||
git cherry-pick -n <commit> # apply without committing (stage only)
|
||||
git cherry-pick --abort
|
||||
git cherry-pick --continue
|
||||
```
|
||||
|
||||
## History and Inspection
|
||||
|
||||
```bash
|
||||
git log # full log
|
||||
git log --oneline # compact one-line per commit
|
||||
git log --graph --oneline --all # branch graph
|
||||
git log --stat # show file change counts
|
||||
git log -p # show patch diff for each commit
|
||||
git log --author="<name>"
|
||||
git log --grep="<pattern>"
|
||||
git log --since="2 weeks ago"
|
||||
git log <file> # history of a specific file
|
||||
git log <branch>..<branch> # commits in second not in first
|
||||
git show <commit> # show commit details and diff
|
||||
git diff <commit1> <commit2> # diff between two commits
|
||||
git blame <file> # annotate each line with last commit
|
||||
git bisect start # start binary search for bug
|
||||
git bisect good <commit>
|
||||
git bisect bad <commit>
|
||||
git bisect reset
|
||||
```
|
||||
|
||||
## Remote Operations
|
||||
|
||||
```bash
|
||||
git remote -v # list remotes
|
||||
git remote add <name> <url> # add a remote
|
||||
git remote remove <name>
|
||||
git remote rename <old> <new>
|
||||
git fetch <remote> # download objects and refs
|
||||
git fetch --all # fetch all remotes
|
||||
git fetch --prune # remove stale remote-tracking refs
|
||||
git pull # fetch + merge (or rebase if configured)
|
||||
git push <remote> <branch> # push branch to remote
|
||||
git push -u origin <branch> # push and set upstream
|
||||
git push --force-with-lease # safe force push (checks remote tip)
|
||||
git push --tags # push tags
|
||||
git push origin :<branch> # delete remote branch
|
||||
```
|
||||
|
||||
## Stashing
|
||||
|
||||
```bash
|
||||
git stash # stash working tree and index
|
||||
git stash push -m "<msg>" # stash with description
|
||||
git stash push -u # include untracked files
|
||||
git stash list # show all stashes
|
||||
git stash pop # apply most recent and remove from list
|
||||
git stash apply stash@{n} # apply without removing
|
||||
git stash drop stash@{n} # delete a stash
|
||||
git stash clear # delete all stashes
|
||||
git stash branch <branch> # create branch from stash
|
||||
```
|
||||
|
||||
## Tags
|
||||
|
||||
```bash
|
||||
git tag # list tags
|
||||
git tag <name> # lightweight tag at HEAD
|
||||
git tag -a <name> -m "<msg>" # annotated tag
|
||||
git tag <name> <commit> # tag a specific commit
|
||||
git tag -d <name> # delete local tag
|
||||
git push origin <tag> # push tag
|
||||
git push origin --tags # push all tags
|
||||
git push origin :refs/tags/<name> # delete remote tag
|
||||
```
|
||||
|
||||
## Undoing
|
||||
|
||||
```bash
|
||||
git reset HEAD~1 # undo last commit, keep changes staged
|
||||
git reset --soft HEAD~1 # undo last commit, keep changes staged
|
||||
git reset --mixed HEAD~1 # undo last commit, unstage changes
|
||||
git reset --hard HEAD~1 # undo last commit, discard changes
|
||||
git revert <commit> # create new commit that undoes a past commit
|
||||
git revert -n <commit> # stage the revert without committing
|
||||
git clean -fd # delete untracked files and directories
|
||||
git clean -n # dry run (show what would be deleted)
|
||||
```
|
||||
|
||||
## Plumbing (scripting-safe)
|
||||
|
||||
```bash
|
||||
git rev-parse HEAD # print full SHA of HEAD
|
||||
git rev-parse --short HEAD # print short SHA
|
||||
git rev-parse --show-toplevel # print repo root path
|
||||
git symbolic-ref HEAD # print the ref HEAD points to
|
||||
git cat-file -t <sha> # print object type
|
||||
git cat-file -p <sha> # print object contents
|
||||
git update-ref refs/heads/<b> <sha> # set a ref to a commit
|
||||
git for-each-ref refs/heads/ # list refs with metadata
|
||||
```
|
||||
169
plugins/git/docs/research/docs/git/commits.md
Normal file
169
plugins/git/docs/research/docs/git/commits.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
topic: commits
|
||||
source_keys:
|
||||
- conventional-commits-spec
|
||||
- commitlint-config-conventional
|
||||
---
|
||||
|
||||
## Conventional Commits Specification (v1.0.0)
|
||||
|
||||
Conventional Commits is a lightweight convention on top of commit messages that provides a set of rules for creating an explicit commit history. It enables automated tooling (CHANGELOG generation, semantic version bumping) and structured filtering.
|
||||
|
||||
## Message Format
|
||||
|
||||
```
|
||||
<type>[optional scope]: <description>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer(s)]
|
||||
```
|
||||
|
||||
Each section is separated by a blank line. The header is the only required part.
|
||||
|
||||
## Rules
|
||||
|
||||
| Element | Rule |
|
||||
|---|---|
|
||||
| `type` | Required. Lowercase noun. |
|
||||
| `scope` | Optional. Noun in parentheses directly after type: `feat(api):`. |
|
||||
| `description` | Required. Immediately follows `type/scope: `. Imperative mood, no trailing period. |
|
||||
| `body` | Optional. Begins one blank line after description. Free-form prose, multiple paragraphs allowed. |
|
||||
| `footer(s)` | Optional. Begins one blank line after body (or description). `<token>: <value>` format. |
|
||||
| `BREAKING CHANGE` | Must be uppercase. Either a footer token or signalled by `!` before the colon. |
|
||||
|
||||
## Standard Types
|
||||
|
||||
The spec mandates only `feat` and `fix`. The following 11 types are the de-facto standard from `@commitlint/config-conventional` (Angular commit message guidelines):
|
||||
|
||||
| Type | Meaning | SemVer impact | Appears in CHANGELOG |
|
||||
|---|---|---|---|
|
||||
| `feat` | New user-visible feature | MINOR | Yes |
|
||||
| `fix` | Bug fix | PATCH | Yes |
|
||||
| `perf` | Performance improvement, no API change | PATCH | Yes |
|
||||
| `revert` | Reverts a previous commit | PATCH | Yes |
|
||||
| `docs` | Documentation only | none | No |
|
||||
| `style` | Formatting, whitespace — no logic change | none | No |
|
||||
| `refactor` | Code restructuring — no feature or fix | none | No |
|
||||
| `test` | Adding or fixing tests | none | No |
|
||||
| `build` | Build system or external dependency changes | none | No |
|
||||
| `ci` | CI configuration and scripts | none | No |
|
||||
| `chore` | Anything not fitting above | none | No |
|
||||
|
||||
A `BREAKING CHANGE` footer or `!` on **any** type always triggers a MAJOR bump.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
Two equivalent notations:
|
||||
|
||||
**`!` in header** (preferred — visible in `git log --oneline`):
|
||||
```
|
||||
feat!: drop support for Node 6
|
||||
feat(api)!: remove deprecated endpoint
|
||||
```
|
||||
|
||||
**`BREAKING CHANGE` footer** (machine-readable body):
|
||||
```
|
||||
feat: allow config to extend other configs
|
||||
|
||||
BREAKING CHANGE: `extends` key now used for extending config files
|
||||
```
|
||||
|
||||
**Both together** (most explicit):
|
||||
```
|
||||
feat!: drop support for Node 6
|
||||
|
||||
BREAKING CHANGE: use JavaScript features not available in Node 6.
|
||||
```
|
||||
|
||||
Rules:
|
||||
- `BREAKING CHANGE` must be all caps.
|
||||
- `BREAKING-CHANGE` (hyphenated) is an accepted synonym.
|
||||
- Any type can carry a breaking change, not just `feat`.
|
||||
- The footer value must describe what broke.
|
||||
|
||||
## Footer Token Rules
|
||||
|
||||
```
|
||||
<token>: <value>
|
||||
<token> #<value> # for issue references
|
||||
```
|
||||
|
||||
- Tokens use hyphens for word separation: `Reviewed-by`, `Co-authored-by`, `Refs`.
|
||||
- Exception: `BREAKING CHANGE` (space allowed, uppercase).
|
||||
- Multiple footers allowed, one per line.
|
||||
- Blank line required before the footer block.
|
||||
|
||||
Valid footer examples:
|
||||
```
|
||||
Reviewed-by: Z
|
||||
Refs: #123
|
||||
Co-authored-by: Alice <alice@example.com>
|
||||
BREAKING CHANGE: the `--format` flag now requires a value
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Minimal — no body, no footer:
|
||||
```
|
||||
docs: correct spelling of CHANGELOG
|
||||
```
|
||||
|
||||
With scope:
|
||||
```
|
||||
feat(lang): add Polish language
|
||||
```
|
||||
|
||||
Breaking change via `!`:
|
||||
```
|
||||
feat!: send an email to the customer when a product is shipped
|
||||
```
|
||||
|
||||
Breaking change via footer:
|
||||
```
|
||||
feat: allow provided config object to extend other configs
|
||||
|
||||
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
|
||||
```
|
||||
|
||||
Multi-paragraph body with multiple footers:
|
||||
```
|
||||
fix: prevent racing of requests
|
||||
|
||||
Introduce a request id and a reference to latest request. Dismiss
|
||||
incoming responses other than from latest request.
|
||||
|
||||
Remove timeouts which were used to mitigate the racing issue but are
|
||||
obsolete now.
|
||||
|
||||
Reviewed-by: Z
|
||||
Refs: #123
|
||||
```
|
||||
|
||||
Revert:
|
||||
```
|
||||
revert: let us never again speak of the noodle incident
|
||||
|
||||
Refs: 676104e, a215868
|
||||
```
|
||||
|
||||
## commitlint Constraints (`config-conventional`)
|
||||
|
||||
| Constraint | Value |
|
||||
|---|---|
|
||||
| Header max length | 100 characters |
|
||||
| Subject must not end with `.` | enforced |
|
||||
| Subject must be lowercase | enforced (not sentence-case or UPPER-CASE) |
|
||||
| Body / footer line max length | 100 characters |
|
||||
| Type must be one of the 11 standard types | error if not |
|
||||
| Blank line before body | warning |
|
||||
| Blank line before footer | warning |
|
||||
|
||||
## SemVer Mapping Summary
|
||||
|
||||
| Condition | SemVer bump |
|
||||
|---|---|
|
||||
| `fix`, `perf`, `revert` | PATCH |
|
||||
| `feat` | MINOR |
|
||||
| Any type with `BREAKING CHANGE` or `!` | MAJOR |
|
||||
| All other types (`docs`, `style`, `refactor`, `test`, `build`, `ci`, `chore`) | none |
|
||||
147
plugins/git/docs/research/docs/git/configuration.md
Normal file
147
plugins/git/docs/research/docs/git/configuration.md
Normal file
@@ -0,0 +1,147 @@
|
||||
---
|
||||
topic: configuration
|
||||
source_keys:
|
||||
- git-scm-docs
|
||||
---
|
||||
|
||||
## Config Scopes
|
||||
|
||||
Git reads configuration from three scopes in order: system → global → local. The last value wins. A fourth `worktree` scope exists when `extensions.worktreeConfig` is enabled.
|
||||
|
||||
| Scope | Flag | File (Linux/macOS) | File (Windows) |
|
||||
|---|---|---|---|
|
||||
| system | `--system` | `$(prefix)/etc/gitconfig` | `$(prefix)\etc\gitconfig` |
|
||||
| global | `--global` | `~/.gitconfig` or `$XDG_CONFIG_HOME/git/config` | `%USERPROFILE%\.gitconfig` |
|
||||
| local | `--local` (default) | `.git/config` | `.git/config` |
|
||||
| worktree | `--worktree` | `.git/config.worktree` | `.git/config.worktree` |
|
||||
|
||||
Writes default to local scope. Pass `--global` to write user-wide settings.
|
||||
|
||||
## Inspecting Config
|
||||
|
||||
```bash
|
||||
git config --list # merged view of all scopes
|
||||
git config --global --list # global scope only
|
||||
git config --global --edit # open in $EDITOR
|
||||
git config --get user.email # read a single key
|
||||
git config --unset core.editor # remove a key
|
||||
```
|
||||
|
||||
## Essential Variables
|
||||
|
||||
### Identity (required — no defaults)
|
||||
|
||||
```bash
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "you@example.com"
|
||||
```
|
||||
|
||||
These are stamped on every commit. There is no system default — omitting them causes `git commit` to fail.
|
||||
|
||||
### Editor
|
||||
|
||||
```bash
|
||||
git config --global core.editor "code --wait" # VS Code
|
||||
git config --global core.editor "vim"
|
||||
git config --global core.editor "nano"
|
||||
```
|
||||
|
||||
Used for commit messages, rebase TODO lists, `git notes edit`, etc. Falls back to `$VISUAL` / `$EDITOR` env vars if unset.
|
||||
|
||||
### Default Branch Name
|
||||
|
||||
```bash
|
||||
git config --global init.defaultBranch main
|
||||
```
|
||||
|
||||
Controls the name of the initial branch created by `git init`. Defaults to `master` on most installations; set to `main` to match current convention.
|
||||
|
||||
### Pull Behaviour
|
||||
|
||||
```bash
|
||||
git config --global pull.rebase true # rebase instead of merge on pull
|
||||
```
|
||||
|
||||
| Value | Behaviour |
|
||||
|---|---|
|
||||
| `false` | Merge (creates a merge commit) |
|
||||
| `true` | Rebase (rewrites local commits on top of fetched) |
|
||||
| `merges` | Rebase, preserving merge commits |
|
||||
| `interactive` | Interactive rebase on pull |
|
||||
|
||||
Leaving this unset causes a warning on every `git pull` in Git ≥ 2.27. Setting `pull.rebase true` is the cleaner-history choice for most workflows.
|
||||
|
||||
### Push Behaviour
|
||||
|
||||
```bash
|
||||
git config --global push.default simple
|
||||
```
|
||||
|
||||
| Value | Behaviour |
|
||||
|---|---|
|
||||
| `simple` (default) | Push current branch to its upstream; refuse if names differ |
|
||||
| `current` | Push current branch to same-named remote branch |
|
||||
| `upstream` | Push to the branch's configured upstream, regardless of name |
|
||||
| `matching` | Push all matching local/remote branch pairs |
|
||||
| `nothing` | Refuse all pushes unless an explicit refspec is given |
|
||||
|
||||
### Line Endings
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
git config --global core.autocrlf true
|
||||
|
||||
# Linux / macOS
|
||||
git config --global core.autocrlf input
|
||||
```
|
||||
|
||||
`true` converts CRLF→LF on check-in and LF→CRLF on check-out (Windows). `input` converts CRLF→LF on check-in only.
|
||||
|
||||
### Credential Storage
|
||||
|
||||
```bash
|
||||
git config --global credential.helper cache # in-memory, expires
|
||||
git config --global credential.helper osxkeychain # macOS Keychain
|
||||
git config --global credential.helper manager-core # Windows Credential Manager
|
||||
```
|
||||
|
||||
### Global Ignore File
|
||||
|
||||
```bash
|
||||
git config --global core.excludesFile ~/.gitignore_global
|
||||
```
|
||||
|
||||
Patterns in this file are ignored across all repos without touching `.gitignore`.
|
||||
|
||||
### Merge and Diff Tools
|
||||
|
||||
```bash
|
||||
git config --global merge.tool meld # or vimdiff, kdiff3, etc.
|
||||
git config --global diff.tool vimdiff
|
||||
```
|
||||
|
||||
### Aliases
|
||||
|
||||
Defined under `[alias]` in the config file:
|
||||
```ini
|
||||
[alias]
|
||||
st = status
|
||||
co = checkout
|
||||
br = branch -vv
|
||||
last = log -1 HEAD
|
||||
lg = log --graph --oneline --decorate --all
|
||||
undo = reset --soft HEAD~1
|
||||
```
|
||||
|
||||
## Minimal First-Time Setup
|
||||
|
||||
```bash
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global core.editor "vim"
|
||||
git config --global init.defaultBranch main
|
||||
git config --global pull.rebase true
|
||||
git config --global push.default simple
|
||||
git config --global credential.helper cache
|
||||
git config --global core.excludesFile ~/.gitignore_global
|
||||
```
|
||||
158
plugins/git/docs/research/docs/git/gitflow.md
Normal file
158
plugins/git/docs/research/docs/git/gitflow.md
Normal file
@@ -0,0 +1,158 @@
|
||||
---
|
||||
topic: gitflow
|
||||
source_keys:
|
||||
- nvie-gitflow-post
|
||||
- atlassian-gitflow-tutorial
|
||||
- gitflow-cheatsheet
|
||||
---
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
Gitflow is a branching model that treats branching and merging as routine operations, not exceptional ones. It defines a strict structure where every branch has a fixed purpose, a fixed origin point, and a fixed merge target. This predictability enables automated tooling and makes the history of any project self-documenting.
|
||||
|
||||
The central invariant: `main` always reflects production-ready code; `develop` always reflects the latest integrated development state. All other branches are temporary scaffolding.
|
||||
|
||||
The model was designed for software with **explicit versioned releases**. Vincent Driessen (the original author) noted in 2020 that teams doing continuous delivery should prefer GitHub Flow instead.
|
||||
|
||||
## The Five Branch Types
|
||||
|
||||
### 1. `main` (permanent)
|
||||
|
||||
HEAD always reflects a production-ready, releasable state. Every commit is tagged with a version. Automated deployment pipelines trigger off this branch.
|
||||
|
||||
**Receives merges from:** `release/*` and `hotfix/*` only. Never committed to directly.
|
||||
|
||||
### 2. `develop` (permanent)
|
||||
|
||||
Integration branch for all completed features. HEAD reflects the latest delivered development changes for the next release. When `develop` is feature-complete for a release, a release branch forks from it.
|
||||
|
||||
**Receives merges from:** `feature/*`, `release/*`, `hotfix/*`.
|
||||
|
||||
### 3. Feature branches (short-lived)
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| Branch from | `develop` |
|
||||
| Merge back to | `develop` |
|
||||
| Naming | `feature/<name>` or `feature/TICKET-123-description` |
|
||||
|
||||
Isolate development of a single feature. Live primarily in developer local repos; pushed to `origin` only when collaboration is needed. No direct relationship with `main`.
|
||||
|
||||
Lifecycle:
|
||||
1. Branch from `develop`.
|
||||
2. Develop in isolation.
|
||||
3. Merge back to `develop` with `--no-ff`.
|
||||
4. Delete the branch.
|
||||
|
||||
### 4. Release branches (short-lived)
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| Branch from | `develop` |
|
||||
| Merge back to | both `main` AND `develop` |
|
||||
| Naming | `release/<version>` (e.g. `release/1.2.0`) |
|
||||
|
||||
Purpose: prepare a production release. Once branched, no new features — only bug fixes, version bumping, and release metadata. This frees `develop` to receive features for the *next* release immediately.
|
||||
|
||||
Lifecycle:
|
||||
1. Branch from `develop` when it has reached the desired state.
|
||||
2. Bump the version number as the first commit.
|
||||
3. Fix last-minute bugs directly on the release branch.
|
||||
4. Merge into `main` with `--no-ff`; tag the merge commit with the version.
|
||||
5. Merge back into `develop` with `--no-ff` (to carry bug fixes forward).
|
||||
6. Delete the branch.
|
||||
|
||||
### 5. Hotfix branches (short-lived)
|
||||
|
||||
| Property | Value |
|
||||
|---|---|
|
||||
| Branch from | `main` (from the tagged production commit) |
|
||||
| Merge back to | both `main` AND `develop` (or active release branch) |
|
||||
| Naming | `hotfix/<version>` (e.g. `hotfix/1.2.1`) |
|
||||
|
||||
Purpose: emergency patches for production bugs. Allows fixing critical issues without interrupting feature development on `develop`.
|
||||
|
||||
Lifecycle:
|
||||
1. Branch from `main`.
|
||||
2. Bump the patch version.
|
||||
3. Fix the bug.
|
||||
4. Merge into `main` with `--no-ff`; tag with new version.
|
||||
5. Merge into `develop` with `--no-ff` — or into the active release branch if one is open (it will carry the fix into `develop` at close).
|
||||
6. Delete the branch.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
| Branch type | Convention | Examples |
|
||||
|---|---|---|
|
||||
| Permanent | exact name | `main`, `develop` |
|
||||
| Feature | `feature/<name>` | `feature/login-oauth`, `feature/JIRA-42-cart` |
|
||||
| Release | `release/<version>` | `release/2.1.0` |
|
||||
| Hotfix | `hotfix/<version>` | `hotfix/2.1.1` |
|
||||
|
||||
Versions follow semantic versioning: `MAJOR.MINOR.PATCH`.
|
||||
|
||||
## The `--no-ff` Rule
|
||||
|
||||
All merges of supporting branches (feature, release, hotfix) into permanent branches use `--no-ff`:
|
||||
|
||||
```bash
|
||||
git merge --no-ff <branch>
|
||||
```
|
||||
|
||||
This forces a merge commit even when a fast-forward is possible, preserving the branch history in the DAG. Without it, the commit group collapses into a linear history and you lose the ability to identify which commits belonged to a given feature or to revert a feature atomically by reverting the merge commit.
|
||||
|
||||
## Hard Invariants
|
||||
|
||||
1. `main` only receives merges from `release/*` and `hotfix/*`.
|
||||
2. `develop` only receives merges from `feature/*`, `release/*`, and `hotfix/*`.
|
||||
3. All merges into permanent branches use `--no-ff`.
|
||||
4. Release branches are created from `develop`; hotfix branches are created from `main`.
|
||||
5. Both release and hotfix branches merge into **both** `main` and `develop` at close.
|
||||
6. Version tags are applied to the merge commit on `main`.
|
||||
|
||||
## git-flow CLI
|
||||
|
||||
The `git-flow` CLI wraps the manual operations. The `git-flow-avh` fork is the most maintained.
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
git flow init # interactive prompt for branch naming
|
||||
git flow init -d # use defaults without prompting
|
||||
```
|
||||
|
||||
**Feature branches:**
|
||||
```bash
|
||||
git flow feature start <name> # branch feature/<name> from develop
|
||||
git flow feature finish <name> # merge into develop (--no-ff), delete
|
||||
git flow feature publish <name> # push to origin
|
||||
git flow feature track <name> # track a remote feature branch
|
||||
```
|
||||
|
||||
**Release branches:**
|
||||
```bash
|
||||
git flow release start <version> # branch release/<version> from develop
|
||||
git flow release publish <version> # push for collaboration
|
||||
git flow release finish <version> # merge into main (tagged) + develop, delete
|
||||
```
|
||||
|
||||
**Hotfix branches:**
|
||||
```bash
|
||||
git flow hotfix start <version> # branch hotfix/<version> from main
|
||||
git flow hotfix finish <version> # merge into main (tagged) + develop, delete
|
||||
```
|
||||
|
||||
## When to Use Gitflow
|
||||
|
||||
**Good fit:**
|
||||
- Software with explicit versioned releases: libraries, desktop apps, mobile apps, versioned APIs.
|
||||
- Projects that must maintain and patch multiple concurrent production versions.
|
||||
- Larger teams with parallel feature development and release preparation happening simultaneously.
|
||||
- Workflows where release preparation (docs, QA, sign-off) takes meaningful calendar time.
|
||||
|
||||
**Poor fit / when not to use:**
|
||||
- Continuously deployed web applications (SaaS, internal tools, websites) — release branches add ceremony with no benefit when deploys happen multiple times per day.
|
||||
- Teams practising trunk-based development where the trunk is always deployable — GitHub Flow (short-lived feature branches off `main`, fast merges, immediate deploy) is simpler and better matched.
|
||||
- Small teams or solo projects where branching overhead exceeds the benefit.
|
||||
- Projects without versioned releases.
|
||||
|
||||
Driessen's own 2020 note: "If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub Flow) instead of trying to shoehorn git-flow into your team."
|
||||
359
plugins/git/docs/research/docs/git/history-inspection.md
Normal file
359
plugins/git/docs/research/docs/git/history-inspection.md
Normal file
@@ -0,0 +1,359 @@
|
||||
---
|
||||
topic: history-inspection
|
||||
source_keys:
|
||||
- git-scm-bisect-docs
|
||||
- git-scm-log-docs
|
||||
- git-scm-diff-docs
|
||||
- context7-git-htmldocs
|
||||
---
|
||||
|
||||
## git bisect
|
||||
|
||||
Binary search through commit history to find the commit that introduced a bug or behaviour change. Requires O(log2 N) test steps.
|
||||
|
||||
### Core Workflow
|
||||
|
||||
```bash
|
||||
git bisect start
|
||||
git bisect bad # current HEAD is broken
|
||||
git bisect good <commit> # known-good baseline
|
||||
|
||||
# Git checks out midpoint. Test, then:
|
||||
git bisect good # test passed
|
||||
git bisect bad # test failed
|
||||
|
||||
# Repeat until Git prints "X is the first bad commit"
|
||||
git bisect reset # return to original HEAD
|
||||
git bisect reset <commit> # return to a specific commit
|
||||
git bisect reset bisect/bad # check out the bad commit itself
|
||||
```
|
||||
|
||||
Compact start form:
|
||||
```bash
|
||||
git bisect start HEAD v1.2 -- # HEAD=bad, v1.2=good; -- separates paths
|
||||
git bisect start HEAD v1.2 -- src/ # limit bisection to src/ directory
|
||||
```
|
||||
|
||||
### bisect run — Automated Mode
|
||||
|
||||
```bash
|
||||
git bisect run <cmd> [<arg>...]
|
||||
```
|
||||
|
||||
Runs `<cmd>` on each candidate commit. Git interprets the exit code:
|
||||
|
||||
| Exit code | Meaning |
|
||||
|---|---|
|
||||
| `0` | Good (test passed) |
|
||||
| `1–124` | Bad (test failed) |
|
||||
| `125` | Skip this commit (cannot test — e.g. build broken) |
|
||||
| `126–127` | POSIX shell errors — treated as bad |
|
||||
| `128+` | Aborts the bisect session |
|
||||
|
||||
The 125 build-failure skip pattern:
|
||||
```bash
|
||||
#!/bin/sh
|
||||
make || exit 125 # skip if build is broken
|
||||
./check_test_case.sh # 0=good, nonzero=bad
|
||||
```
|
||||
|
||||
Keep test scripts outside the repository so checkout does not clobber them.
|
||||
|
||||
### bisect skip
|
||||
|
||||
```bash
|
||||
git bisect skip # skip current commit
|
||||
git bisect skip v2.5..v2.6 # skip a range (v2.5 exclusive, v2.6 inclusive)
|
||||
git bisect skip v2.5 v2.5..v2.6 # skip point commit + range
|
||||
```
|
||||
|
||||
If the first bad commit is adjacent to a skipped commit, bisect reports it cannot pinpoint the exact culprit but prints the likely candidates.
|
||||
|
||||
### bisect log / bisect replay
|
||||
|
||||
```bash
|
||||
git bisect log # print session history (good/bad/skip decisions)
|
||||
git bisect log > bisect.log # save to file
|
||||
# edit bisect.log to remove a wrong decision
|
||||
git bisect reset && git bisect replay bisect.log # replay from edited log
|
||||
```
|
||||
|
||||
Use `log` + `replay` to undo mistakes without restarting from scratch.
|
||||
|
||||
### bisect visualize / view
|
||||
|
||||
```bash
|
||||
git bisect visualize # open remaining suspects in gitk
|
||||
git bisect view # alias for visualize
|
||||
git bisect visualize --stat # show stat instead of full diff
|
||||
git bisect visualize -p # show patches
|
||||
```
|
||||
|
||||
Falls back to `git log` when no graphical display is detected (checks `DISPLAY`, `SESSIONNAME`, `MSYSTEM`, `SECURITYSESSIONID`).
|
||||
|
||||
### Non-Bug Hunts: new / old / custom terms
|
||||
|
||||
Use `new`/`old` when searching for a property change rather than a regression:
|
||||
|
||||
```bash
|
||||
git bisect start
|
||||
git bisect new HEAD # has the property
|
||||
git bisect old HEAD~10 # does not have the property
|
||||
```
|
||||
|
||||
Custom terms:
|
||||
```bash
|
||||
git bisect start --term-new slow --term-old fast
|
||||
git bisect slow # equivalent to: git bisect bad
|
||||
git bisect fast # equivalent to: git bisect good
|
||||
git bisect terms # show active term names
|
||||
```
|
||||
|
||||
### Advanced Start Flags
|
||||
|
||||
| Flag | Effect |
|
||||
|---|---|
|
||||
| `--no-checkout` | Updates `BISECT_HEAD` ref instead of checking out; useful for tests that don't need a working tree; automatic in bare repos |
|
||||
| `--first-parent` | Follow only first parents at merges; finds the integration commit that introduced a regression; ignores broken side branches |
|
||||
| `-- <path>...` | Limit bisection to specific paths; reduces number of trials |
|
||||
|
||||
---
|
||||
|
||||
## git log — Format and Filtering
|
||||
|
||||
### Named Format Presets (`--format` / `--pretty`)
|
||||
|
||||
| Name | Output |
|
||||
|---|---|
|
||||
| `oneline` | `<hash> <title>` |
|
||||
| `short` | hash, author, title |
|
||||
| `medium` | hash, author, date, full message (default) |
|
||||
| `full` | adds committer |
|
||||
| `fuller` | separate author/committer dates |
|
||||
| `reference` | `<abbrev> (<title>, <date>)` — for use in commit messages |
|
||||
| `email` | RFC 2822 email format |
|
||||
| `raw` | full object as stored in the object database |
|
||||
| `format:<str>` | custom template with placeholders |
|
||||
|
||||
### Custom Format Placeholders
|
||||
|
||||
**Commit identity:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%H` | full commit hash |
|
||||
| `%h` | abbreviated commit hash |
|
||||
| `%T` | tree hash |
|
||||
| `%t` | abbreviated tree hash |
|
||||
| `%P` | full parent hashes |
|
||||
| `%p` | abbreviated parent hashes |
|
||||
|
||||
**Author:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%an` | author name |
|
||||
| `%aN` | author name (mailmap-resolved) |
|
||||
| `%ae` | author email |
|
||||
| `%aE` | author email (mailmap-resolved) |
|
||||
| `%ad` | author date (respects `--date=`) |
|
||||
| `%ar` | author date, relative |
|
||||
| `%at` | author date, UNIX timestamp |
|
||||
| `%ai` | author date, ISO 8601-like |
|
||||
| `%aI` | author date, strict ISO 8601 |
|
||||
| `%as` | author date, short (YYYY-MM-DD) |
|
||||
|
||||
**Committer:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%cn` | committer name |
|
||||
| `%ce` | committer email |
|
||||
| `%cd` | committer date (respects `--date=`) |
|
||||
| `%cr` | committer date, relative |
|
||||
| `%ct` | committer date, UNIX timestamp |
|
||||
| `%ci` | committer date, ISO 8601-like |
|
||||
| `%cs` | committer date, short |
|
||||
|
||||
**Message:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%s` | subject (first line) |
|
||||
| `%f` | sanitized subject (filename-safe) |
|
||||
| `%b` | body (everything after blank line following subject) |
|
||||
| `%B` | raw body (subject + body) |
|
||||
| `%N` | commit notes |
|
||||
|
||||
**Refs and decorations:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%d` | ref names (like `--decorate`) |
|
||||
| `%D` | ref names without surrounding parentheses |
|
||||
| `%S` | ref name by which commit was reached (requires `--source`) |
|
||||
| `%(decorate[:opts])` | custom decorated refs; options: `prefix=`, `suffix=`, `separator=`, `pointer=`, `tag=` |
|
||||
| `%(describe[:opts])` | like `git describe`; options: `tags=`, `abbrev=`, `match=`, `exclude=` |
|
||||
|
||||
**GPG signature:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%G?` | status: `G`=good, `B`=bad, `U`=unknown, `X`=expired, `R`=revoked, `N`=no signature |
|
||||
| `%GS` | signer name |
|
||||
| `%GK` | signing key ID |
|
||||
|
||||
**Trailers:**
|
||||
```
|
||||
%(trailers[:key=<k>][,only][,separator=<s>][,unfold][,keyonly][,valueonly])
|
||||
```
|
||||
|
||||
**Formatting / color:**
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%n` | newline |
|
||||
| `%%` | literal `%` |
|
||||
| `%Cred` / `%Cgreen` / `%Cblue` / `%Creset` | terminal colors |
|
||||
| `%C(<spec>)` | color per git-config spec |
|
||||
| `%<(<n>[,trunc])` | right-pad field to width n |
|
||||
| `%>(<n>)` | left-pad to width |
|
||||
|
||||
**Reflog** (requires `-g` / `--walk-reflogs`):
|
||||
|
||||
| Placeholder | Meaning |
|
||||
|---|---|
|
||||
| `%gD` | reflog selector (e.g. `refs/stash@{1}`) |
|
||||
| `%gd` | shortened reflog selector |
|
||||
| `%gs` | reflog subject |
|
||||
|
||||
### Pickaxe Search: -S and -G
|
||||
|
||||
**`-S<string>`** — finds commits where the **count** of `<string>` changed (i.e. the string was added or removed net). Does not match commits where the string merely appears in a diff hunk without a count change.
|
||||
|
||||
```bash
|
||||
git log -S"my_function"
|
||||
git log -S"my_function" --pickaxe-regex # treat as POSIX ERE
|
||||
git log -S"my_function" --pickaxe-all # show all files in matching changesets
|
||||
```
|
||||
|
||||
**`-G<regex>`** — finds commits where any added or removed **line** in the patch matches `<regex>`. Broader than `-S`: matches whenever the pattern appears in diff text regardless of count.
|
||||
|
||||
```bash
|
||||
git log -G"frotz\(nitfol"
|
||||
```
|
||||
|
||||
**Critical distinction:** given a diff that removes one occurrence of `foo` and adds one occurrence of `foo` (net change = 0):
|
||||
- `-S"foo"` — does **not** match (count unchanged)
|
||||
- `-G"foo"` — **matches** (pattern appears in patch text)
|
||||
|
||||
Binary files are searched by `-S`; ignored by `-G` unless `--text` is supplied.
|
||||
|
||||
**`--pickaxe-all`** — when a match is found, show all changed files in that changeset, not just the matching ones.
|
||||
|
||||
### --follow
|
||||
|
||||
```bash
|
||||
git log --follow -- <file>
|
||||
```
|
||||
|
||||
Continues file history across renames. Without `--follow`, log stops at the rename boundary. Only valid for a single file path.
|
||||
|
||||
### --diff-filter
|
||||
|
||||
Selects commits (in `git log`) or files (in `git diff`) by change type:
|
||||
|
||||
| Letter | Meaning |
|
||||
|---|---|
|
||||
| `A` | Added |
|
||||
| `C` | Copied |
|
||||
| `D` | Deleted |
|
||||
| `M` | Modified |
|
||||
| `R` | Renamed |
|
||||
| `T` | Type changed (regular file ↔ symlink ↔ submodule) |
|
||||
| `U` | Unmerged (conflict) |
|
||||
| `X` | Unknown (indicates a git bug) |
|
||||
| `B` | Pairing broken |
|
||||
|
||||
Lowercase letters **exclude** that type:
|
||||
```bash
|
||||
git log --diff-filter=ad # exclude added and deleted files
|
||||
git log --diff-filter=M # only show commits with modified files
|
||||
```
|
||||
|
||||
`C` and `R` only appear when copy/rename detection is enabled (`-C`, `-M` flags or `diff.renames` config).
|
||||
|
||||
### -L — Line Range History
|
||||
|
||||
Traces the evolution of a specific range of lines or a named function through commits. Implies `--patch`.
|
||||
|
||||
```bash
|
||||
git log -L 10,20:file.txt
|
||||
git log -L /start_pattern/,/end_pattern/:file.txt
|
||||
git log -L :myfunction:src/app.c
|
||||
git log -L /init/,+15:config.py # 15 lines after first match of /init/
|
||||
```
|
||||
|
||||
Range formats:
|
||||
| Format | Meaning |
|
||||
|---|---|
|
||||
| `<n>` | Absolute line number (1-based) |
|
||||
| `/<regex>/` | First line matching regex from previous range end |
|
||||
| `^/<regex>/` | First line matching regex from file start |
|
||||
| `+<n>` / `-<n>` | Offset relative to `<start>` (end position only) |
|
||||
|
||||
Limitations: incompatible with `--raw`, `--numstat`, `--shortstat`, `--name-only`, `--name-status`, `--check`. Cannot use pathspec limiters alongside `-L`.
|
||||
|
||||
### Graph and Ancestry Filters
|
||||
|
||||
```bash
|
||||
git log --first-parent # at merges, follow only first parent (mainline evolution)
|
||||
git log --merges # only merge commits (≥2 parents); equivalent to --min-parents=2
|
||||
git log --no-merges # only non-merge commits; equivalent to --max-parents=1
|
||||
git log --ancestry-path D..M # only commits actually on the path from D to M
|
||||
git log --min-parents=<n> # include only commits with ≥ n parents
|
||||
git log --max-parents=<n> # include only commits with ≤ n parents
|
||||
```
|
||||
|
||||
`--ancestry-path` is significant: without it, `D..M` includes all commits reachable from M but not D — including side branches that merged into the path. With it, only commits directly between D and M are shown.
|
||||
|
||||
---
|
||||
|
||||
## git diff — Output Control
|
||||
|
||||
### --stat
|
||||
|
||||
```bash
|
||||
git diff --stat # diffstat: file names + ± bar
|
||||
git diff --stat=<width>,<name-width>,<count>
|
||||
git diff --compact-summary # alongside --stat: shows new/gone, +x/-x (executable), +l (symlink)
|
||||
git diff --numstat # machine-readable: <added>\t<deleted>\t<path>; - for binary
|
||||
```
|
||||
|
||||
### --name-only / --name-status
|
||||
|
||||
```bash
|
||||
git diff --name-only # only filenames, one per line
|
||||
git diff --name-status # status letter + filename per line
|
||||
```
|
||||
|
||||
`--name-status` uses the same status letters as `--diff-filter`.
|
||||
|
||||
### --word-diff
|
||||
|
||||
```bash
|
||||
git diff --word-diff # inline word-level diff with [-removed-] {+added+} markers
|
||||
git diff --word-diff=color # color only, no markers
|
||||
git diff --word-diff=porcelain # machine-readable: +/- prefixed lines, ~ for newlines
|
||||
git diff --word-diff-regex=<re> # define what counts as a "word"
|
||||
```
|
||||
|
||||
### Whitespace Flags
|
||||
|
||||
| Flag | Effect |
|
||||
|---|---|
|
||||
| `-b` / `--ignore-space-change` | Treat any run of whitespace as equivalent; ignore trailing whitespace |
|
||||
| `-w` / `--ignore-all-space` | Ignore all whitespace completely |
|
||||
| `--ignore-space-at-eol` | Ignore whitespace at end-of-line only |
|
||||
| `--ignore-blank-lines` | Ignore changes consisting entirely of blank lines |
|
||||
| `-I<regex>` / `--ignore-matching-lines=<re>` | Ignore changes where all changed lines match regex |
|
||||
53
plugins/git/docs/research/docs/git/installation.md
Normal file
53
plugins/git/docs/research/docs/git/installation.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
topic: installation
|
||||
source_keys:
|
||||
- git-scm-docs
|
||||
---
|
||||
|
||||
## Linux
|
||||
|
||||
Debian / Ubuntu:
|
||||
```bash
|
||||
sudo apt install git-all
|
||||
```
|
||||
|
||||
Fedora / RHEL / CentOS:
|
||||
```bash
|
||||
sudo dnf install git-all
|
||||
```
|
||||
|
||||
Other distributions use their native package manager. The `git-all` meta-package pulls in optional tools (GUI clients, credential helpers); install `git` alone for the minimal CLI.
|
||||
|
||||
## macOS
|
||||
|
||||
The fastest path — run any git command and macOS prompts you to install the Xcode Command Line Tools:
|
||||
```bash
|
||||
git --version
|
||||
```
|
||||
|
||||
This installs Apple's bundled git. For a more recent version, use the binary installer from git-scm.com or install via Homebrew:
|
||||
```bash
|
||||
brew install git
|
||||
```
|
||||
|
||||
## Windows
|
||||
|
||||
**Option 1 — Git for Windows** (recommended): download the installer from git-scm.com/download/win. It includes Git Bash (a POSIX shell), Git GUI, and optionally integrates with the Windows credential manager.
|
||||
|
||||
**Option 2 — Chocolatey**:
|
||||
```bash
|
||||
choco install git
|
||||
```
|
||||
|
||||
**Option 3 — winget**:
|
||||
```bash
|
||||
winget install --id Git.Git
|
||||
```
|
||||
|
||||
## Post-install Verification
|
||||
|
||||
```bash
|
||||
git --version
|
||||
```
|
||||
|
||||
Minimum recommended versions for modern features: 2.23+ (for `git switch` / `git restore`), 2.38+ (for `git worktree` improvements).
|
||||
76
plugins/git/docs/research/docs/git/overview.md
Normal file
76
plugins/git/docs/research/docs/git/overview.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
topic: overview
|
||||
source_keys:
|
||||
- context7-git-htmldocs
|
||||
---
|
||||
|
||||
## What Git Is
|
||||
|
||||
Git is a distributed version control system designed to track changes in source code across the full lifetime of a project. Unlike centralised VCS tools, every developer holds a complete copy of the repository — full history, all branches, all objects. This means most operations (log, diff, branch, commit) are local and fast, and the repository survives any single node failing.
|
||||
|
||||
## Core Mental Model
|
||||
|
||||
Git models a project's history as a directed acyclic graph (DAG) of commit objects. Each commit is identified by a SHA-1 hash derived from its content and parent references, making history immutable by design. You cannot change a past commit — you can only create new commits that supersede it.
|
||||
|
||||
Three areas govern where changes live at any moment:
|
||||
|
||||
- **Working tree** — the files on disk you edit directly.
|
||||
- **Index (staging area)** — a snapshot assembled for the next commit. Changes must be explicitly staged with `git add` before they become part of a commit.
|
||||
- **Repository (`.git/`)** — the permanent object store. Once committed, content is addressable by hash.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
**Repository** — a `.git/` directory containing all objects (blobs, trees, commits, tags) and refs. Bare repositories (no working tree) are used as shared remotes.
|
||||
|
||||
**Commit** — a snapshot of the entire repository tree at a point in time, plus a pointer to its parent(s), author metadata, and a message. A merge commit has two parents.
|
||||
|
||||
**Branch** — a movable pointer to a commit. Creating a branch is cheap: it is just a 41-byte ref file. Switching branches (`git checkout` / `git switch`) updates HEAD and the working tree.
|
||||
|
||||
**HEAD** — a symbolic ref pointing to the currently checked-out branch (or directly to a commit in detached HEAD state). The next commit advances whatever HEAD points to.
|
||||
|
||||
**Remote** — a named reference to another repository. `origin` is the conventional name for the repository a local repo was cloned from. Remotes are fetched into remote-tracking branches (e.g. `origin/main`) which are local, read-only mirrors.
|
||||
|
||||
**Tag** — a permanent, human-readable name for a specific commit. Annotated tags carry a message and are signed; lightweight tags are just a ref alias.
|
||||
|
||||
**Ref** — any named pointer to a commit: branches live under `refs/heads/`, tags under `refs/tags/`, remotes under `refs/remotes/`.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
.git/
|
||||
├── HEAD # points to current branch or commit
|
||||
├── config # local repo config
|
||||
├── index # staging area (binary)
|
||||
├── objects/ # content-addressable object store
|
||||
│ ├── pack/ # packed objects for efficiency
|
||||
│ └── info/
|
||||
├── refs/
|
||||
│ ├── heads/ # local branch tips
|
||||
│ ├── remotes/ # remote-tracking branches
|
||||
│ └── tags/ # tags
|
||||
├── hooks/ # optional shell scripts on git events
|
||||
├── modules/ # submodule git dirs (when present)
|
||||
└── worktrees/ # linked worktree metadata (when present)
|
||||
```
|
||||
|
||||
## Fundamental Workflow
|
||||
|
||||
```bash
|
||||
git init # create a new repository
|
||||
git add <file> # stage changes
|
||||
git diff --cached # review what is staged
|
||||
git commit -m "message" # snapshot staged changes
|
||||
git log --oneline --graph # visualise history
|
||||
git push origin main # send commits to remote
|
||||
git pull # fetch + merge (or rebase) from remote
|
||||
```
|
||||
|
||||
## Architecture Properties
|
||||
|
||||
**Distributed** — every clone is a full backup. There is no single point of failure at the protocol level.
|
||||
|
||||
**Content-addressed** — objects are stored by their SHA-1 hash. Identical content is stored once regardless of how many branches or commits reference it.
|
||||
|
||||
**Immutable history** — commit hashes change if content changes. Rewriting history (rebase, amend) creates new commits; old ones remain until garbage-collected.
|
||||
|
||||
**Porcelain vs plumbing** — Git exposes high-level commands for humans (porcelain: `commit`, `merge`, `log`) and low-level commands for scripting (plumbing: `cat-file`, `update-ref`, `rev-parse`). Scripts should prefer plumbing for stability.
|
||||
192
plugins/git/docs/research/docs/git/remotes.md
Normal file
192
plugins/git/docs/research/docs/git/remotes.md
Normal file
@@ -0,0 +1,192 @@
|
||||
---
|
||||
topic: remotes
|
||||
source_keys:
|
||||
- git-scm-push-docs
|
||||
- git-scm-fetch-docs
|
||||
- git-scm-pull-docs
|
||||
- git-scm-remote-docs
|
||||
- context7-git-htmldocs
|
||||
---
|
||||
|
||||
## Remote Management (`git remote`)
|
||||
|
||||
### Add
|
||||
|
||||
```bash
|
||||
git remote add <name> <url>
|
||||
git remote add -f <name> <url> # fetch immediately after adding
|
||||
git remote add -t <branch> <name> <url> # track only one branch (repeatable)
|
||||
git remote add --no-tags <name> <url> # suppress automatic tag import
|
||||
git remote add --mirror=fetch <name> <url> # mirror all refs locally (bare repos only)
|
||||
git remote add --mirror=push <name> <url> # every push behaves like --mirror
|
||||
```
|
||||
|
||||
### Remove / Rename / URLs
|
||||
|
||||
```bash
|
||||
git remote remove <name> # delete remote + all tracking refs + config
|
||||
git remote rename <old> <new>
|
||||
git remote set-url <name> <newurl> # replace first fetch URL
|
||||
git remote set-url <name> <newurl> <oldurl-regex> # replace specific URL by regex
|
||||
git remote set-url --push <name> <url> # change push URL only (must point same repo)
|
||||
git remote set-url --add <name> <url> # add extra push URL (push to multiple remotes)
|
||||
git remote set-url --delete <name> <regex> # remove matching URLs
|
||||
git remote get-url <name> # show effective URL after insteadOf rewrites
|
||||
git remote get-url --push --all <name> # show all push URLs
|
||||
```
|
||||
|
||||
`--push` on `set-url` changes only where pushes go — fetch and push URLs must still reference the same repository. For genuine fetch-from-A push-to-B workflows, use two separate named remotes.
|
||||
|
||||
### Inspect and Housekeeping
|
||||
|
||||
```bash
|
||||
git remote -v # list remotes with URLs
|
||||
git remote show <name> # live query: tracked branches, ahead/behind status
|
||||
git remote show -n <name> # same, using cached data (no network)
|
||||
git remote prune <name> # delete stale tracking refs (no fetch)
|
||||
git remote prune --dry-run <name> # preview what would be pruned
|
||||
git remote set-head <name> -a # auto-detect remote's default branch (fetch first)
|
||||
git remote set-head <name> <branch> # set remote HEAD explicitly
|
||||
git remote set-head <name> -d # delete refs/remotes/<name>/HEAD
|
||||
```
|
||||
|
||||
`git remote show` requires `-v` before `show`, not after. `set-head -a` silently does nothing if the tracking branch doesn't exist locally — always fetch first.
|
||||
|
||||
## Fetching (`git fetch`)
|
||||
|
||||
```bash
|
||||
git fetch <remote> # fetch all branches from remote
|
||||
git fetch <remote> <branch> # fetch one branch (stores in FETCH_HEAD)
|
||||
git fetch --all # fetch from all configured remotes
|
||||
git fetch --all --prune # fetch all + prune stale tracking refs
|
||||
git fetch --prune # delete remote-tracking refs no longer on remote
|
||||
git fetch --prune-tags # also prune local tags not on remote
|
||||
git fetch --depth=<n> # deepen / create shallow clone
|
||||
git fetch --unshallow # convert shallow clone to full history
|
||||
git fetch --update-shallow # allow fetch to update shallow boundaries
|
||||
git fetch --refmap='' <remote> <branch> # fetch without storing (FETCH_HEAD only)
|
||||
```
|
||||
|
||||
**`--prune` does not prune tags by default.** Add `--prune-tags` explicitly, or configure permanently:
|
||||
```bash
|
||||
git config remote.origin.prune true # auto-prune on every fetch
|
||||
git config fetch.pruneTags true # prune tags when --prune is active
|
||||
```
|
||||
|
||||
**Remote-tracking branch mechanics.** The default fetch refspec is `+refs/heads/*:refs/remotes/origin/*`. The `+` forces updates — remote-tracking branches mirror the remote exactly and do not protect local history. Fetch never touches local branches.
|
||||
|
||||
## Pushing (`git push`)
|
||||
|
||||
```bash
|
||||
git push <remote> <branch> # push branch
|
||||
git push -u origin <branch> # push and set upstream (branch.<name>.remote/merge)
|
||||
git push --all # push all local branches
|
||||
git push --tags # push all tags
|
||||
git push origin <tag> # push a specific tag
|
||||
git push origin --delete <branch> # delete remote branch
|
||||
git push origin :<branch> # delete remote branch (refspec form)
|
||||
git push --prune origin 'refs/heads/*:refs/heads/*' # delete remote branches with no local counterpart
|
||||
```
|
||||
|
||||
### Force Push Safety
|
||||
|
||||
**`--force` (`-f`)** — unconditionally overwrites the remote ref. Applies to all refs in the push. To force only one ref, use `+` in the refspec:
|
||||
```bash
|
||||
git push origin +main develop # forces main, safe-pushes develop
|
||||
```
|
||||
|
||||
**`--force-with-lease`** — rejects the push if the remote ref has moved since your last fetch. Three forms:
|
||||
|
||||
| Form | What it protects |
|
||||
|---|---|
|
||||
| `--force-with-lease` (bare) | All refs being pushed, vs. remote-tracking branch |
|
||||
| `--force-with-lease=<refname>` | Named ref only |
|
||||
| `--force-with-lease=<refname>:<sha>` | Named ref must be at exact SHA — stable, not experimental |
|
||||
|
||||
**Critical caveat with the bare form:** any background process that runs `git fetch` (IDE plugin, cron, editor) updates your remote-tracking branch, making the lease check pass even if someone else has pushed. The protection is silently defeated.
|
||||
|
||||
Two mitigations:
|
||||
```bash
|
||||
# Option 1: dedicated push remote (background tools only fetch origin)
|
||||
git remote add origin-push $(git config remote.origin.url)
|
||||
git push --force-with-lease origin-push
|
||||
|
||||
# Option 2: explicit SHA via tag (unaffected by tracking branch state)
|
||||
git fetch
|
||||
git tag base master
|
||||
git rebase -i master
|
||||
git push --force-with-lease=master:base master:master
|
||||
```
|
||||
|
||||
**`--force-if-includes`** — adds a second check on top of bare `--force-with-lease`: verifies the remote-tracking tip appears in your local branch's reflog, meaning you actually integrated it. No-op without `--force-with-lease`. Has no effect when `--force-with-lease=<ref>:<sha>` is used.
|
||||
|
||||
Safest force-push combination:
|
||||
```bash
|
||||
git push --force-with-lease --force-if-includes origin
|
||||
```
|
||||
|
||||
### Refspec Syntax
|
||||
|
||||
```
|
||||
[+]<src>[:<dst>]
|
||||
```
|
||||
|
||||
| Pattern | Meaning |
|
||||
|---|---|
|
||||
| `<branch>` | Push to same-named remote branch |
|
||||
| `<src>:<dst>` | Push `<src>` local ref to `<dst>` remote ref |
|
||||
| `+<src>:<dst>` | Force this refspec (non-fast-forward allowed) |
|
||||
| `:<branch>` | Delete remote `<branch>` |
|
||||
| `refs/heads/*:refs/heads/*` | Glob: push all matching branches |
|
||||
| `^refs/heads/dev-*` | Negative: exclude matching refs |
|
||||
| `tag <name>` | Sugar for `refs/tags/<name>:refs/tags/<name>` |
|
||||
|
||||
Remote-side policies (`receive.denyDeletes`, `receive.denyDeleteCurrent`, `receive.denyNonFastForwards`) are enforced server-side regardless of local flags.
|
||||
|
||||
## Pulling (`git pull`)
|
||||
|
||||
`git pull` is `git fetch` followed by a merge or rebase. Always fetch first if you want control; `git pull` is convenient but less explicit.
|
||||
|
||||
### Diverged Branch Resolution Strategies
|
||||
|
||||
**`--ff-only`** (recommended default for disciplined teams)
|
||||
- Succeeds only when local is a strict ancestor of remote — no divergence.
|
||||
- Fails explicitly when diverged, forcing a conscious choice.
|
||||
- Config: `git config pull.ff only`
|
||||
|
||||
**`--rebase`** / `--rebase=true`
|
||||
- Replays local unpublished commits on top of fetched tip. Linear history.
|
||||
- Rewrites SHAs — unsafe for commits already pushed to a shared branch.
|
||||
- Config: `git config pull.rebase true`
|
||||
|
||||
**`--rebase=merges`**
|
||||
- Preserves intentional local merge commits during replay.
|
||||
- Config: `git config pull.rebase merges`
|
||||
|
||||
**`--no-rebase`** / merge (default when `pull.rebase=false`)
|
||||
- Three-way merge commit. Non-linear history. Original commits unchanged.
|
||||
- Config: `git config pull.rebase false`
|
||||
|
||||
**`--squash`**
|
||||
- Collapses all incoming commits into staged changes. Does not commit. You write the commit message.
|
||||
|
||||
### Config Precedence for Pull Behaviour
|
||||
|
||||
Precedence (highest wins):
|
||||
1. Command-line flag
|
||||
2. `pull.rebase` global/local config
|
||||
3. `branch.<name>.rebase` (branch-specific override)
|
||||
4. `branch.autoSetupRebase` (set on tracking branch creation)
|
||||
|
||||
Per-branch override example:
|
||||
```bash
|
||||
git config --global pull.rebase true
|
||||
git config branch.develop.rebase false # develop always merges
|
||||
```
|
||||
|
||||
### Pull Gotchas
|
||||
|
||||
- Rebase rewrites SHAs. Only rebase unpublished local work — rebasing already-pushed commits causes conflicts for everyone downstream.
|
||||
- `--recurse-submodules` only fetches already-checked-out submodules; newly added submodules are not initialized automatically.
|
||||
- Default merge strategy changed to `ort` in Git 2.34. `recursive` is now an alias. Strategy options (`-X ours`, `-X theirs`, `-X ignore-space-change`) still pass through.
|
||||
- `pull.rebase` default became `--ff-only` in recent Git versions. Teams migrating from older Git should set this explicitly to avoid surprises.
|
||||
113
plugins/git/docs/research/docs/git/sources.md
Normal file
113
plugins/git/docs/research/docs/git/sources.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Sources
|
||||
|
||||
## context7-git-htmldocs
|
||||
|
||||
- **URL:** context7:/git/htmldocs
|
||||
- **Description:** Official Git HTML documentation from the git/htmldocs repository — covers all commands, concepts, and internals (19,370 code snippets, High reputation).
|
||||
- **Contributing files:** overview.md, cli-reference.md, branching-merging.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-config
|
||||
- **Description:** Official git-scm.com reference pages — git-config manual covering all config variables, scopes, and the installation guide.
|
||||
- **Contributing files:** installation.md, configuration.md, cli-reference.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-submodule-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-submodule
|
||||
- **Description:** Official git-scm.com reference for git-submodule — all subcommands, flags, configuration keys, and behaviour details.
|
||||
- **Contributing files:** submodules.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-worktree-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-worktree
|
||||
- **Description:** Official git-scm.com reference for git-worktree — all subcommands, flags, ref-sharing rules, and gotchas.
|
||||
- **Contributing files:** worktrees.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## nvie-gitflow-post
|
||||
|
||||
- **URL:** https://nvie.com/posts/a-successful-git-branching-model/
|
||||
- **Description:** Original 2010 post by Vincent Driessen introducing the Gitflow branching model, including a 2020 reflection note recommending GitHub Flow for continuous delivery teams.
|
||||
- **Contributing files:** gitflow.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## atlassian-gitflow-tutorial
|
||||
|
||||
- **URL:** https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
|
||||
- **Description:** Atlassian's comprehensive Gitflow tutorial covering all five branch types, lifecycle steps, and CLI usage.
|
||||
- **Contributing files:** gitflow.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## gitflow-cheatsheet
|
||||
|
||||
- **URL:** https://danielkummer.github.io/git-flow-cheatsheet/
|
||||
- **Description:** Visual cheatsheet for the git-flow CLI commands (git-flow-avh fork), covering all subcommands for feature, release, and hotfix branches.
|
||||
- **Contributing files:** gitflow.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## conventional-commits-spec
|
||||
|
||||
- **URL:** https://www.conventionalcommits.org/en/v1.0.0/
|
||||
- **Description:** The Conventional Commits v1.0.0 specification — full format rules, breaking change conventions, footer token format, examples, and SemVer mapping rationale.
|
||||
- **Contributing files:** commits.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## commitlint-config-conventional
|
||||
|
||||
- **URL:** https://github.com/conventional-changelog/commitlint
|
||||
- **Description:** The commitlint `@commitlint/config-conventional` package — defines the 11 standard commit types, header length limits, and validation constraints.
|
||||
- **Contributing files:** commits.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-push-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-push
|
||||
- **Description:** Official git-scm.com reference for git-push — refspec syntax, --force-with-lease semantics (including background-fetch caveat and mitigations), --force-if-includes, --delete, --prune, --set-upstream.
|
||||
- **Contributing files:** remotes.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-fetch-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-fetch
|
||||
- **Description:** Official git-scm.com reference for git-fetch — --prune, --prune-tags, --all, --depth, --unshallow, --update-shallow, remote-tracking branch mechanics and refmap.
|
||||
- **Contributing files:** remotes.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-pull-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-pull
|
||||
- **Description:** Official git-scm.com reference for git-pull — diverged branch resolution strategies (--ff-only, --rebase variants, merge), pull.rebase config precedence, and gotchas.
|
||||
- **Contributing files:** remotes.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-remote-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-remote
|
||||
- **Description:** Official git-scm.com reference for git-remote — add, remove, rename, set-url (fetch/push split), prune, set-head, show, get-url with insteadOf resolution.
|
||||
- **Contributing files:** remotes.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-bisect-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-bisect
|
||||
- **Description:** Official git-scm.com reference for git-bisect — full workflow, bisect run exit code semantics, bisect skip, log/replay, visualize, new/old/custom terms, --no-checkout, --first-parent.
|
||||
- **Contributing files:** history-inspection.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-log-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-log
|
||||
- **Description:** Official git-scm.com reference for git-log — full --format placeholder table, -S/-G pickaxe search, --follow, --diff-filter, -L line range history, --ancestry-path, --first-parent, --merges.
|
||||
- **Contributing files:** history-inspection.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## git-scm-diff-docs
|
||||
|
||||
- **URL:** https://git-scm.com/docs/git-diff
|
||||
- **Description:** Official git-scm.com reference for git-diff — --diff-filter letter table, --stat variants, --name-only/--name-status, --word-diff modes, whitespace flags.
|
||||
- **Contributing files:** history-inspection.md
|
||||
- **Status:** `extracted`
|
||||
203
plugins/git/docs/research/docs/git/submodules.md
Normal file
203
plugins/git/docs/research/docs/git/submodules.md
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
topic: submodules
|
||||
source_keys:
|
||||
- git-scm-submodule-docs
|
||||
---
|
||||
|
||||
## Concept Overview
|
||||
|
||||
A submodule is a full Git repository embedded as a subdirectory inside a parent repository (the superproject). The superproject does not store the submodule's files — it stores a pointer to a specific commit SHA in the submodule's history. Submodules maintain completely independent commit histories.
|
||||
|
||||
Two files govern submodules:
|
||||
|
||||
- `.gitmodules` — version-controlled; defines each submodule's name, path, and URL. Shared with collaborators.
|
||||
- `.git/config` — local only; populated on `git submodule init`. Override URLs here before fetching.
|
||||
|
||||
The submodule's git directory lives at `.git/modules/<name>/`, linked to the working tree via a `.git` pointer file. The working directory normally ends up in **detached HEAD state** after `git submodule update`.
|
||||
|
||||
## Key Commands
|
||||
|
||||
### Add a submodule
|
||||
|
||||
```bash
|
||||
git submodule add <url> <path>
|
||||
git submodule add -b <branch> <url> <path> # track a specific branch
|
||||
git submodule add --depth 1 <url> <path> # shallow clone
|
||||
git submodule add -f <url> <path> # force-add (gitignored path or name conflict)
|
||||
git submodule add --name <name> <url> <path> # logical name differs from path
|
||||
```
|
||||
|
||||
After `add`, two items are staged: a new `.gitmodules` entry and a gitlink at the path. A `git commit` is still required.
|
||||
|
||||
### Initialize
|
||||
|
||||
```bash
|
||||
git submodule init [<path>...]
|
||||
```
|
||||
|
||||
Copies submodule URLs from `.gitmodules` to `.git/config`. This is where you can edit local URL overrides before fetching. Does not clone.
|
||||
|
||||
### Update (clone + checkout)
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive # most common: init + update, all levels
|
||||
git submodule update --remote --merge # update to remote branch tip
|
||||
git submodule update --remote --rebase # same, via rebase
|
||||
git submodule update --jobs <n> # parallel updates
|
||||
git submodule update -f # force (discard local changes)
|
||||
```
|
||||
|
||||
| Flag | Meaning |
|
||||
|---|---|
|
||||
| `--init` | Run init first (avoids a separate step) |
|
||||
| `--remote` | Use the submodule's remote branch tip instead of the superproject's recorded commit |
|
||||
| `--checkout` | Detached HEAD at recorded commit (default) |
|
||||
| `--rebase` | Rebase current branch onto recorded commit |
|
||||
| `--merge` | Merge recorded commit into current branch |
|
||||
| `--recursive` | Operate on nested submodules |
|
||||
| `--jobs <n>` | Parallel clone (defaults to `submodule.fetchJobs`) |
|
||||
| `-N` / `--no-fetch` | Skip remote fetch |
|
||||
| `--depth <n>` | Shallow clone |
|
||||
| `--filter <spec>` | Partial clone filter |
|
||||
|
||||
### Status
|
||||
|
||||
```bash
|
||||
git submodule status [--recursive] [<path>...]
|
||||
git submodule status --cached # show SHA in superproject index
|
||||
```
|
||||
|
||||
Prefix meanings:
|
||||
- `-` — not initialized
|
||||
- `+` — checked-out commit differs from superproject's recorded commit
|
||||
- `U` — merge conflict inside the submodule
|
||||
- (blank) — clean
|
||||
|
||||
### Deinit (unregister)
|
||||
|
||||
```bash
|
||||
git submodule deinit <path>
|
||||
git submodule deinit --all # all submodules
|
||||
git submodule deinit -f <path> # force (local modifications present)
|
||||
```
|
||||
|
||||
Removes the submodule section from `.git/config` and empties the working tree. Does **not** remove the entry from `.gitmodules` or the gitlink from the index — use `git rm` for that.
|
||||
|
||||
### Remove completely
|
||||
|
||||
```bash
|
||||
git submodule deinit path/to/sub
|
||||
git rm path/to/sub
|
||||
rm -rf .git/modules/<name> # stale git dir not auto-cleaned
|
||||
git commit -m "Remove submodule"
|
||||
```
|
||||
|
||||
### Sync URLs
|
||||
|
||||
```bash
|
||||
git submodule sync [--recursive]
|
||||
```
|
||||
|
||||
Propagates URL changes from `.gitmodules` into `.git/config`. Use after a submodule's remote URL has been renamed upstream.
|
||||
|
||||
### Run a command in every submodule
|
||||
|
||||
```bash
|
||||
git submodule foreach <command>
|
||||
git submodule foreach --recursive <command>
|
||||
git submodule foreach 'git pull origin main || :' # || : continues on failure
|
||||
```
|
||||
|
||||
Available shell variables inside `<command>`: `$name`, `$sm_path`, `$displaypath`, `$sha1`, `$toplevel`.
|
||||
|
||||
### Other subcommands
|
||||
|
||||
```bash
|
||||
git submodule summary [<path>...] # show commits between recorded and current
|
||||
git submodule set-branch -b <branch> <path> # set tracking branch for --remote
|
||||
git submodule set-url <path> <url> # update URL in .gitmodules + sync
|
||||
git submodule absorbgitdirs [<path>...] # move embedded .git/ into .git/modules/
|
||||
```
|
||||
|
||||
## Workflow Patterns
|
||||
|
||||
### Clone a repo with submodules
|
||||
|
||||
```bash
|
||||
# One step (Git 2.13+)
|
||||
git clone --recurse-submodules <url>
|
||||
|
||||
# Two steps
|
||||
git clone <url>
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### Add a dependency as a submodule
|
||||
|
||||
```bash
|
||||
git submodule add https://github.com/org/lib.git libs/lib
|
||||
git commit -m "chore: add lib as submodule"
|
||||
```
|
||||
|
||||
### Keep submodules pinned to superproject's recorded commit
|
||||
|
||||
```bash
|
||||
git submodule update --recursive # after every git pull
|
||||
```
|
||||
|
||||
Configure Git to do this automatically on pull:
|
||||
```bash
|
||||
git config submodule.recurse true
|
||||
```
|
||||
|
||||
### Update submodules to latest on their remote branch
|
||||
|
||||
```bash
|
||||
git submodule update --remote --merge --recursive
|
||||
git commit -am "chore: update submodules to latest"
|
||||
```
|
||||
|
||||
### Override a submodule URL locally (private mirror)
|
||||
|
||||
```bash
|
||||
git submodule init
|
||||
# Edit .git/config to change the URL
|
||||
git submodule update
|
||||
```
|
||||
|
||||
## Common Gotchas
|
||||
|
||||
**Detached HEAD by default.** `git submodule update` checks out a specific commit, not a branch. Commits made inside the submodule are invisible to the superproject until you update the pointer. Always check your branch before committing inside a submodule.
|
||||
|
||||
**Two pushes required.** Commit and push inside the submodule first, then update the pointer in the superproject and push that. Forgetting to push the submodule leaves others unable to fetch the recorded commit.
|
||||
|
||||
**`--recursive` is not the default.** Most commands operate one level deep. Pass `--recursive` explicitly for nested submodules.
|
||||
|
||||
**Relative URLs are relative to the remote, not the filesystem.** `../foo.git` is relative to the superproject's default remote URL.
|
||||
|
||||
**Custom update commands are security-gated.** A `.gitmodules` entry of `update = !some-command` is not copied to `.git/config` by `git submodule init`, so cloning cannot execute arbitrary code automatically.
|
||||
|
||||
**`deinit` is not removal.** Use `git rm` after `deinit` to actually remove from the repo. Also delete `.git/modules/<name>/` manually.
|
||||
|
||||
**`.git/modules/` persists after `git rm`.** Re-adding the same path will fail until you delete it.
|
||||
|
||||
## Configuration
|
||||
|
||||
In `.gitmodules` (version-controlled):
|
||||
|
||||
| Key | Purpose |
|
||||
|---|---|
|
||||
| `submodule.<name>.path` | Working tree path |
|
||||
| `submodule.<name>.url` | Remote URL |
|
||||
| `submodule.<name>.branch` | Branch for `update --remote` |
|
||||
| `submodule.<name>.update` | Default update procedure |
|
||||
| `submodule.<name>.shallow` | Recommend shallow clone |
|
||||
|
||||
In `.git/config` (local, after `init`):
|
||||
|
||||
| Key | Purpose |
|
||||
|---|---|
|
||||
| `submodule.<name>.url` | Local URL override |
|
||||
| `submodule.<name>.update` | Local procedure override |
|
||||
| `submodule.fetchJobs` | Default parallelism for `update --jobs` |
|
||||
| `submodule.recurse` | Auto-recurse on `pull`, `push`, etc. |
|
||||
181
plugins/git/docs/research/docs/git/worktrees.md
Normal file
181
plugins/git/docs/research/docs/git/worktrees.md
Normal file
@@ -0,0 +1,181 @@
|
||||
---
|
||||
topic: worktrees
|
||||
source_keys:
|
||||
- git-scm-worktree-docs
|
||||
---
|
||||
|
||||
## Concept Overview
|
||||
|
||||
A worktree lets you check out multiple branches simultaneously from one repository, each in its own directory on disk. All worktrees share the same objects, configuration, and most refs — but each has its own `HEAD`, index, and per-worktree metadata.
|
||||
|
||||
**Main worktree** — the original working tree from `git init` or `git clone`. Exactly one per repo. Cannot be removed or moved via git commands (use `repair` if moved manually).
|
||||
|
||||
**Linked worktree** — any additional worktree created with `git worktree add`. Multiple can coexist. Each gets a private directory at `$GIT_DIR/worktrees/<name>/` holding its `HEAD`, `index`, `gitdir` pointer, and optionally a `locked` file.
|
||||
|
||||
**Shared across worktrees:** everything under `refs/` (branches, tags, remotes), objects, config.
|
||||
|
||||
**Per-worktree (not shared):** `HEAD`, `ORIG_HEAD`, `MERGE_HEAD`, refs under `refs/bisect/`, `refs/worktree/`, `refs/rewritten/`.
|
||||
|
||||
## Key Commands
|
||||
|
||||
### Add a worktree
|
||||
|
||||
```bash
|
||||
git worktree add <path> # create worktree, derive branch from path basename
|
||||
git worktree add <path> <branch> # check out existing branch
|
||||
git worktree add -b <new-branch> <path> # create and check out new branch
|
||||
git worktree add -B <branch> <path> # create or reset branch to HEAD
|
||||
git worktree add -d <path> # detached HEAD
|
||||
git worktree add --orphan -b <branch> <path> # new unborn branch
|
||||
```
|
||||
|
||||
| Flag | Meaning |
|
||||
|---|---|
|
||||
| `-b <branch>` | Create and check out a new branch; fails if it exists |
|
||||
| `-B <branch>` | Like `-b` but resets the branch if it already exists |
|
||||
| `-d` / `--detach` | Detach HEAD; useful for throwaway experiments |
|
||||
| `--orphan` | Create empty unborn branch |
|
||||
| `--no-checkout` | Suppress initial checkout (for sparse-checkout setup) |
|
||||
| `--guess-remote` | Look for a matching remote-tracking branch by path basename |
|
||||
| `--lock [--reason <str>]` | Lock immediately on creation (atomic; avoids race vs. add-then-lock) |
|
||||
| `-f` / `--force` | Allow when branch is already checked out elsewhere |
|
||||
| `--relative-paths` | Link via relative paths (portable across moves) |
|
||||
|
||||
Using "`-`" as `<commit-ish>` is shorthand for `@{-1}` (previous branch).
|
||||
|
||||
### List worktrees
|
||||
|
||||
```bash
|
||||
git worktree list # show all worktrees
|
||||
git worktree list -v # show lock/prune reasons
|
||||
git worktree list --porcelain # machine-readable output
|
||||
git worktree list --porcelain -z # NUL-terminated (for paths with spaces)
|
||||
```
|
||||
|
||||
Output shows path, HEAD commit, branch name, and `locked` or `prunable` status.
|
||||
|
||||
### Lock / Unlock
|
||||
|
||||
```bash
|
||||
git worktree lock <worktree> --reason "on external SSD"
|
||||
git worktree unlock <worktree>
|
||||
```
|
||||
|
||||
Prevents the worktree from being pruned, moved, or deleted. Use for worktrees on removable drives or network mounts.
|
||||
|
||||
### Move a worktree
|
||||
|
||||
```bash
|
||||
git worktree move <worktree> <new-path>
|
||||
git worktree move -f <worktree> <new-path> # override standard safeguards
|
||||
git worktree move -ff <worktree> <new-path> # override locked state too
|
||||
```
|
||||
|
||||
Cannot move the main worktree. Cannot move a worktree that contains submodules.
|
||||
|
||||
### Remove a worktree
|
||||
|
||||
```bash
|
||||
git worktree remove <worktree> # only clean worktrees (no untracked/modified files)
|
||||
git worktree remove -f <worktree> # force-remove unclean
|
||||
git worktree remove -ff <worktree> # force-remove even if locked
|
||||
```
|
||||
|
||||
Deletes the worktree directory and its `$GIT_DIR/worktrees/<name>/` metadata. Main worktree cannot be removed.
|
||||
|
||||
### Prune stale metadata
|
||||
|
||||
```bash
|
||||
git worktree prune # clean up orphaned metadata
|
||||
git worktree prune --dry-run # preview what would be removed
|
||||
git worktree prune --expire <time> # override expiry threshold
|
||||
```
|
||||
|
||||
Cleans up `$GIT_DIR/worktrees/` entries for directories that no longer exist. Also triggered by `git gc`. Controlled by `gc.worktreePruneExpire` config.
|
||||
|
||||
### Repair broken connections
|
||||
|
||||
```bash
|
||||
git worktree repair # fix all broken connections from main worktree
|
||||
git worktree repair <path> # reconnect a specific linked worktree
|
||||
```
|
||||
|
||||
Reestablishes bidirectional pointers after a manual move. Run from the main worktree after it was moved, or from a linked worktree after it was moved.
|
||||
|
||||
## Workflow Patterns
|
||||
|
||||
### Emergency fix without disrupting current work
|
||||
|
||||
```bash
|
||||
git worktree add -b emergency-fix ../temp main
|
||||
cd ../temp
|
||||
# fix, commit
|
||||
git commit -a -m "fix: critical production bug"
|
||||
cd -
|
||||
git worktree remove ../temp
|
||||
```
|
||||
|
||||
No stashing required. Your ongoing work in the main worktree is untouched.
|
||||
|
||||
### Review a PR branch alongside your current work
|
||||
|
||||
```bash
|
||||
git worktree add ../review-pr-123 origin/feature-xyz
|
||||
# open ../review-pr-123 in a second editor window or terminal
|
||||
```
|
||||
|
||||
### Throwaway experiment in detached HEAD
|
||||
|
||||
```bash
|
||||
git worktree add -d ../experiment
|
||||
# experiment freely
|
||||
git worktree remove ../experiment
|
||||
```
|
||||
|
||||
### Sparse-checkout worktree
|
||||
|
||||
```bash
|
||||
git worktree add --no-checkout ../sparse main
|
||||
cd ../sparse
|
||||
git sparse-checkout init --cone
|
||||
git sparse-checkout set src/
|
||||
git checkout main
|
||||
```
|
||||
|
||||
### Worktree on removable media
|
||||
|
||||
```bash
|
||||
git worktree add /mnt/usb/project feature-branch
|
||||
git worktree lock /mnt/usb/project --reason "external SSD"
|
||||
# when device reconnected:
|
||||
git worktree unlock /mnt/usb/project
|
||||
```
|
||||
|
||||
## Common Gotchas
|
||||
|
||||
**A branch can only be checked out in one worktree at a time.** Attempting to add a worktree for an already-checked-out branch fails without `--force`.
|
||||
|
||||
**Submodules are unsupported.** The docs explicitly warn: "Multiple checkout in general is still experimental, and the support for submodules is incomplete. It is NOT recommended to make multiple checkouts of a superproject." Worktrees with submodules cannot be moved and require `--force` to remove.
|
||||
|
||||
**Never `rm -rf` a worktree directory manually.** It leaves stale metadata in `$GIT_DIR/worktrees/`. Use `git worktree remove` instead. If you already deleted manually, run `git worktree prune` or wait for `git gc`.
|
||||
|
||||
**Moving worktrees manually breaks bidirectional pointers.** Fix with `git worktree repair`.
|
||||
|
||||
**`--lock` on `add` is not the same as create-then-lock.** There is a race window between two separate calls. Use `--lock` directly on `add` when the guarantee matters.
|
||||
|
||||
**`extensions.worktreeConfig = true` is a one-way door for older Git.** It enables per-worktree config (`git config --worktree ...`) but makes the repo refuse to open in older Git versions. Also: `core.bare` and `core.worktree` must then live in `config.worktree`, not `config`.
|
||||
|
||||
**Force-flag escalation.** Some operations require `-f` twice (`-ff`) — specifically, removing or moving a locked worktree.
|
||||
|
||||
**Worktree identification.** Worktrees can be referenced by full path, unique basename, or unique partial path. Ambiguous partial paths error.
|
||||
|
||||
**`checkout.defaultRemote`** — if a branch name matches multiple remotes during `worktree add`, Git refuses unless this is configured to disambiguate.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Key | Effect |
|
||||
|---|---|
|
||||
| `worktree.guessRemote` | Default for `--guess-remote` flag on `worktree add` |
|
||||
| `worktree.useRelativePaths` | Default for `--relative-paths` on `worktree add` |
|
||||
| `gc.worktreePruneExpire` | How long before stale worktree metadata is pruned by `git gc` |
|
||||
| `extensions.worktreeConfig` | Enable per-worktree config scope (`config.worktree` file) |
|
||||
Reference in New Issue
Block a user