commit b25c20bddbf0fa100fa7ff021cdafa1002315224 Author: zlei9 Date: Sun Mar 29 09:49:59 2026 +0800 Initial commit with translated description diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..ef0a0dc --- /dev/null +++ b/SKILL.md @@ -0,0 +1,141 @@ +--- +name: Git +slug: git +version: 1.0.8 +description: "Git提交、分支、变基、合并等操作。" +homepage: https://clawic.com/skills/git +changelog: Simplified the skill name and kept the stateless activation guidance +metadata: {"clawdbot":{"emoji":"📚","requires":{"bins":["git"]},"os":["linux","darwin","win32"]}} +--- + +## When to Use + +Use when the task involves Git repositories, branches, commits, merges, rebases, pull requests, conflict resolution, history inspection, or recovery. This skill is stateless and should be applied by default whenever Git work is part of the job. + +## Quick Reference + +| Topic | File | +|-------|------| +| Essential commands | `commands.md` | +| Advanced operations | `advanced.md` | +| Branch strategies | `branching.md` | +| Conflict resolution | `conflicts.md` | +| History and recovery | `history.md` | +| Team workflows | `collaboration.md` | + +## Core Rules + +1. **Never force push to shared branches** — Use `--force-with-lease` on feature branches only +2. **Commit early, commit often** — Small commits are easier to review, revert, and bisect +3. **Write meaningful commit messages** — First line under 72 chars, imperative mood +4. **Pull before push** — Always `git pull --rebase` before pushing to avoid merge commits +5. **Clean up before merging** — Use `git rebase -i` to squash fixup commits + +## Team Workflows + +**Feature Branch Flow:** +1. `git checkout -b feature/name` from main +2. Make commits, push regularly +3. Open PR, get review +4. Squash and merge to main +5. Delete feature branch + +**Hotfix Flow:** +1. `git checkout -b hotfix/issue` from main +2. Fix, test, commit +3. Merge to main AND develop (if exists) +4. Tag the release + +**Daily Sync:** +```bash +git fetch --all --prune +git rebase origin/main # or merge if team prefers +``` + +## Commit Messages + +- Use conventional commit format: `type(scope): description` +- Keep first line under 72 characters +- Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore` + +## Push Safety + +- Use `git push --force-with-lease` instead of `--force` — prevents overwriting others' work +- If push rejected, run `git pull --rebase` before retrying +- Never force push to main/master branch + +## Conflict Resolution + +- After editing conflicted files, verify no markers remain: `grep -r "<<<\|>>>\|===" .` +- Test that code builds before completing merge +- If merge becomes complex, abort with `git merge --abort` and try `git rebase` instead + +## Branch Hygiene + +- Delete merged branches locally: `git branch -d branch-name` +- Clean remote tracking: `git fetch --prune` +- Before creating PR, rebase feature branch onto latest main +- Use `git rebase -i` to squash messy commits before pushing + +## Safety Checklist + +Before destructive operations (`reset --hard`, `rebase`, `force push`): + +- [ ] Is this a shared branch? → Don't rewrite history +- [ ] Do I have uncommitted changes? → Stash or commit first +- [ ] Am I on the right branch? → `git branch` to verify +- [ ] Is remote up to date? → `git fetch` first + +## Common Traps + +- **git user.email wrong** — Verify with `git config user.email` before important commits +- **Empty directories** — Git doesn't track them, add `.gitkeep` +- **Submodules** — Always clone with `--recurse-submodules` +- **Detached HEAD** — Use `git switch -` to return to previous branch +- **Push rejected** — Usually needs `git pull --rebase` first +- **stash pop on conflict** — Stash disappears. Use `stash apply` instead +- **Large files** — Use Git LFS for files >50MB, never commit secrets +- **Case sensitivity** — Mac/Windows ignore case, Linux doesn't — causes CI failures + +## Recovery Commands + +- Undo last commit keeping changes: `git reset --soft HEAD~1` +- Discard unstaged changes: `git restore filename` +- Find lost commits: `git reflog` (keeps ~90 days of history) +- Recover deleted branch: `git checkout -b branch-name ` +- Use `git add -p` for partial staging when commit mixes multiple changes + +## Debugging with Bisect + +Find the commit that introduced a bug: +```bash +git bisect start +git bisect bad # current commit is broken +git bisect good v1.0.0 # this version worked +# Git checks out middle commit, test it, then: +git bisect good # or git bisect bad +# Repeat until Git finds the culprit +git bisect reset # return to original branch +``` + +## Quick Summary + +```bash +git status -sb # short status with branch +git log --oneline -5 # last 5 commits +git shortlog -sn # contributors by commit count +git diff --stat HEAD~5 # changes summary last 5 commits +git branch -vv # branches with tracking info +git stash list # pending stashes +``` + +## Related Skills +Install with `clawhub install ` if user confirms: +- `gitlab` — GitLab CI/CD and merge requests +- `docker` — Containerization workflows +- `code` — Code quality and best practices + +## Feedback + +- If useful: `clawhub star git` +- Stay updated: `clawhub sync` diff --git a/_meta.json b/_meta.json new file mode 100644 index 0000000..015db9c --- /dev/null +++ b/_meta.json @@ -0,0 +1,6 @@ +{ + "ownerId": "kn73vp5rarc3b14rc7wjcw8f8580t5d1", + "slug": "git", + "version": "1.0.8", + "publishedAt": 1773255795217 +} \ No newline at end of file diff --git a/advanced.md b/advanced.md new file mode 100644 index 0000000..22fb726 --- /dev/null +++ b/advanced.md @@ -0,0 +1,153 @@ +# Advanced Operations + +## Interactive Rebase + +```bash +git rebase -i HEAD~5 # edit last 5 commits +git rebase -i main # edit all since diverging from main +``` + +Commands in editor: +- `pick` = keep as-is +- `reword` = edit message +- `squash` = merge into previous, keep message +- `fixup` = merge into previous, discard message +- `drop` = remove commit + +```bash +git rebase --continue # after resolving conflicts +git rebase --abort # cancel and restore +git rebase --skip # skip problematic commit +``` + +## Bisect (Find Bug) + +```bash +git bisect start +git bisect bad # current has bug +git bisect good v1.0.0 # known good version + +# Git checks out middle commit. Test, then: +git bisect good # no bug here +git bisect bad # bug here +# Repeat until found + +git bisect reset # done, return to branch +``` + +Automated bisect: +```bash +git bisect start HEAD v1.0.0 +git bisect run ./test-script.sh # exit 0 = good, 1 = bad +``` + +## Worktree (Parallel Work) + +```bash +git worktree add ../hotfix hotfix-branch # new dir with branch +git worktree add ../feature -b new-feature # create new branch +git worktree list # show all worktrees +git worktree remove ../hotfix # clean up +``` + +Use cases: +- Review PR while keeping current work +- Run tests on main while developing +- Compare behavior between versions + +## Reflog (Recovery) + +```bash +git reflog # all HEAD movements +git reflog show branch # specific branch history +``` + +Recovery patterns: +```bash +# After bad rebase +git reflog +git reset --hard HEAD@{5} # go back 5 reflog entries + +# Recover deleted branch +git reflog +git branch recovered commit-hash + +# Recover dropped stash +git fsck --unreachable | grep commit +``` + +## Sparse Checkout (Large Repos) + +```bash +git sparse-checkout init --cone +git sparse-checkout set packages/my-app packages/shared +git sparse-checkout add packages/another +git sparse-checkout disable # checkout everything again +``` + +Clone with sparse: +```bash +git clone --filter=blob:none --sparse URL +cd repo +git sparse-checkout set path/to/need +``` + +## Subtree vs Submodule + +**Subtree** (copies code into repo): +```bash +git subtree add --prefix=lib/shared URL main --squash +git subtree pull --prefix=lib/shared URL main --squash +git subtree push --prefix=lib/shared URL main +``` + +**Submodule** (pointer to commit): +```bash +git submodule add URL path +git submodule update --init --recursive +git submodule update --remote +``` + +Choose subtree for: simpler workflow, infrequent updates +Choose submodule for: large deps, independent release cycles + +## Merge vs Rebase + +**Merge** (preserves history): +```bash +git checkout main +git merge feature # creates merge commit +git merge --no-ff feature # always create merge commit +``` + +**Rebase** (linear history): +```bash +git checkout feature +git rebase main # replay commits on top of main +git checkout main +git merge feature # fast-forward +``` + +Rule: Rebase local unpublished commits. Never rebase published branches. + +## Conflict Resolution Tools + +```bash +git mergetool # launch configured tool +git checkout --ours file # take current branch version +git checkout --theirs file # take incoming version +``` + +See all versions: +```bash +git show :1:file # common ancestor +git show :2:file # ours +git show :3:file # theirs +``` + +## Rerere (Remember Resolution) + +```bash +git config --global rerere.enabled true # remember conflict resolutions +git rerere forget file # forget bad resolution +``` diff --git a/branching.md b/branching.md new file mode 100644 index 0000000..adedd2d --- /dev/null +++ b/branching.md @@ -0,0 +1,42 @@ +# Branching Traps + +## Branch Creation + +- `git checkout -b feature` from wrong branch = incorrect base +- `git branch feature` without checkout = you stay on previous branch — commits go there +- Branch name with spaces fails silently in some tools +- `/` in branch name (feature/x) = some systems see it as directory + +## Switching + +- `git checkout branch` with uncommitted changes = they may go to new branch — confusing +- `git switch` is safer but `-f` loses changes without warning +- Auto stash doesn't exist — tracked changes are blocking, untracked get mixed +- Checkout of branch with different submodule = submodule stays in previous state + +## Merge + +- Fast-forward merge doesn't create merge commit — linear history but no context +- `--no-ff` always creates merge commit — useful for features, noise for fixes +- Merge of long branch = mega merge commit hard to review/revert +- Branch deleted after merge = orphan commits if no tag + +## Rebase + +- Rebase of published branch = different history = others must `--force` pull +- Bad interactive rebase can lose commits — use reflog to recover +- Conflicts in rebase: resolve EACH commit, not just once +- Rebase changes SHAs — CI/CD references to old commits broken + +## Remote Tracking + +- `git push -u origin feature` needed first time — without `-u` it doesn't track +- Remote branch deleted doesn't delete local tracking — `git fetch --prune` to clean +- `git pull` without upstream configured = error — `git branch --set-upstream-to` +- Remote rename doesn't update tracking branches — reconfigure manually + +## Naming Conventions + +- Same branch in two remotes (origin/main, upstream/main) = confusion +- Branch name case-insensitive on Mac/Windows, sensitive on Linux — CI bugs +- Branch named same as tag = ambiguity in some commands diff --git a/collaboration.md b/collaboration.md new file mode 100644 index 0000000..d16fad4 --- /dev/null +++ b/collaboration.md @@ -0,0 +1,36 @@ +# Collaboration Traps + +## Push/Pull + +- `git pull` = fetch + merge — can create unexpected merge commits +- `git pull --rebase` avoids merge commits but can have conflicts +- Push rejected for non-fast-forward ≠ you need force — pull first +- `--force` overwrites others' history — `--force-with-lease` is safer + +## Force Push + +- `--force` ignores others' changes — coworkers' commits lost +- `--force-with-lease` fails if remote changed — safer but not foolproof +- Force push to main/master = broken CI/CD references, failed deploys +- Branch protection on GitHub/GitLab prevents force push — always configure + +## Remote Branches + +- `git fetch` doesn't update working directory — only refs +- Branch tracking doesn't update automatically if remote renames +- `origin` is convention, not requirement — other remotes can exist +- `git remote prune origin` cleans refs but not local branches + +## Code Review + +- Push during review = new commits not necessarily reviewed +- Force push during review = diff changes, comments may become obsolete +- Approve before CI complete = bugs merged +- Squash merge loses individual commit history + +## Team Coordination + +- Multiple people on same branch = constant conflicts +- No branch naming convention = chaos in long-running projects +- Forgetting to pull before starting work = divergent history +- Rebasing shared branch without warning = teammates' work broken diff --git a/commands.md b/commands.md new file mode 100644 index 0000000..2d399be --- /dev/null +++ b/commands.md @@ -0,0 +1,125 @@ +# Essential Commands + +## Getting Started + +```bash +git config --global user.name "Your Name" +git config --global user.email "your@email.com" +git init +git clone https://github.com/user/repo.git +``` + +## Daily Workflow + +```bash +git status +git add file.txt +git add . +git commit -m "feat: add feature" +git commit -am "fix: quick fix" +git push +git pull --rebase +``` + +## Viewing Changes + +```bash +git diff # unstaged changes +git diff --staged # staged changes +git log --oneline -10 # recent commits +git log --graph --all # visual history +git show commit-hash # specific commit +git blame file.txt # who changed each line +``` + +## Staging + +```bash +git add -p # interactive staging (partial files) +git restore --staged file # unstage +git restore file # discard changes +git reset # unstage all +``` + +## Stashing + +```bash +git stash # save work temporarily +git stash -m "wip: feature" # with message +git stash list # see stashes +git stash pop # apply and remove +git stash apply # apply and keep +git stash drop # remove without applying +``` + +## Tags + +```bash +git tag # list tags +git tag v1.0.0 # lightweight tag +git tag -a v1.0.0 -m "msg" # annotated tag +git push origin v1.0.0 # push single tag +git push --tags # push all tags +git tag -d v1.0.0 # delete local +git push origin --delete v1.0.0 # delete remote +``` + +## Remote Operations + +```bash +git remote -v # list remotes +git remote add origin URL # add remote +git fetch origin # download without merge +git push -u origin branch # push and track +git push --force-with-lease # safe force push +``` + +## Undoing + +```bash +git reset --soft HEAD~1 # undo commit, keep changes staged +git reset --mixed HEAD~1 # undo commit, keep changes unstaged +git reset --hard HEAD~1 # undo commit, discard changes +git revert commit-hash # create undo commit +git checkout -- file # discard file changes (old) +git restore file # discard file changes (new) +``` + +## Cherry-pick + +```bash +git cherry-pick commit-hash # apply specific commit +git cherry-pick -n commit-hash # apply without committing +git cherry-pick --abort # cancel in progress +``` + +## Clean + +```bash +git clean -n # preview what will be deleted +git clean -f # delete untracked files +git clean -fd # delete untracked files and dirs +git clean -fdx # also delete ignored files +``` + +## Submodules + +```bash +git submodule add URL path # add submodule +git submodule update --init # initialize after clone +git clone --recurse-submodules URL # clone with submodules +git submodule update --remote # update to latest +``` + +## Aliases (add to ~/.gitconfig) + +```ini +[alias] + st = status + co = checkout + br = branch + ci = commit + lg = log --oneline --graph --all + amend = commit --amend --no-edit + unstage = reset HEAD -- +``` diff --git a/conflicts.md b/conflicts.md new file mode 100644 index 0000000..321250b --- /dev/null +++ b/conflicts.md @@ -0,0 +1,36 @@ +# Conflict Traps + +## Detection + +- Binary file conflict = git can't show diff — choose complete version +- "Both modified" vs "both added" conflict — different resolution expected +- Renamed + modified file = git may not detect rename — false conflict +- Whitespace-only conflicts hidden if diff ignores whitespace + +## Resolution + +- Markers `<<<<<<<` forgotten in code = compiles but code is broken +- Resolve "accept theirs" but needed "accept ours" = hard to undo +- Merge commit with badly resolved conflict = bug introduced silently +- `git checkout --ours` during rebase = inverted semantics vs merge + +## During Rebase + +- Each commit can have different conflicts — resolve N times, not 1 +- Skip commit during rebase = commit lost without clear warning +- `--continue` without resolving everything = error, no partial merge +- Abort rebase after several commits = back to start, work lost + +## Tool Issues + +- External merge tool may not save = git thinks you resolved but file unchanged +- Merge tool that deletes markers but doesn't combine code = silently wrong +- `git mergetool` generates `.orig` backups that can be committed by mistake +- Three-way merge tools: "local/remote/base" confusing during rebase (inverted) + +## Prevention + +- Pull frequently to avoid large divergences +- Small, focused commits = smaller conflicts +- Communicate with team about which files you're editing +- Use `git diff main` before merging to preview conflicts diff --git a/history.md b/history.md new file mode 100644 index 0000000..039f1e3 --- /dev/null +++ b/history.md @@ -0,0 +1,43 @@ +# History Traps + +## Reset + +- `git reset --hard` loses uncommitted changes PERMANENTLY — no undo +- `--hard` vs `--soft` vs `--mixed` — each moves different things +- Reset of pushed commit = history diverges — you need force push +- Reset with untracked files = untracked survive — can surprise you + +## Revert + +- Revert creates NEW commit — doesn't delete the original +- Revert of merge commit needs `-m 1` or `-m 2` — without it, error +- Revert of revert = re-applies changes — confusing history +- Revert of old commit can conflict with later commits + +## Amend + +- `--amend` changes SHA — amended commit is DIFFERENT commit +- Amend of pushed commit = same problems as rebase +- `--amend` without staging = only changes message +- Accidental amend on wrong commit = use reflog to recover + +## Reflog + +- Reflog is LOCAL — doesn't sync with remote +- Reflog expires (default 90 days) — old commits lost +- `git gc` can clean unreachable commits before expiration +- Reflog of deleted branch is in HEAD reflog, not branch reflog + +## Cherry-pick + +- Cherry-pick creates new commit with different SHA +- Cherry-picking then merging = duplicate commits in history +- Cherry-pick of merge commit needs `-m` flag +- Conflicts in cherry-pick = resolve same as rebase + +## Blame + +- `git blame` shows last change, not original author +- Blame ignores whitespace changes with `-w` +- `git log -p filename` shows full history of changes +- Blame on moved code: use `git log --follow` for renamed files