git

Commits, branches, merges, and rebases Git repositories, resolves conflicts, and recovers lost history. Use when the work touches a repo, commit, branch, merge, rebase, stash, tag,…

Iván

@ivangdavila

Install

$ openclaw skills install @ivangdavila/git

User preferences and memory live in ~/Clawic/data/git/ (see setup.md on first use, memory-template.md for the file format). If you have data at an old location (~/git/ or ~/clawic/git/), move it to ~/Clawic/data/git/.

Configuration

User-dependent variables. Defaults apply until the user states a preference; store them in ~/Clawic/data/git/config.yaml.

VariableTypeDefaultEffect
integration_stylerebase | merge | squash | repo-defaultrepo-defaultHow branches get combined and what pull does; repo-default reads the last 20 merges (git log --merges --oneline -20) and follows what the repo already does
commit_styleconventional | plain | repo-defaultrepo-defaultShape of every generated commit subject (Commit Discipline); repo-default copies the style found in git log --oneline -20
branch_namingtext (pattern)type/topicTemplate used when creating branches, lowercase and hierarchical by default
protected_brancheslistmain, masterBranches never committed to, rewritten, or force-pushed (Core Rule 2, Push gate); a request that targets one becomes "branch first, then propose the merge"
force_push_policynever | own-branches | anyown-branchesGoverns the Push gate: never turns every rewrite into a git revert; any still requires --force-with-lease
subject_maxnumber (chars, 50-100)72Hard stop for every generated commit subject (Core Rule 6) and the length any commit-msg gate enforces
message_languagetext (language) | repo-defaultrepo-defaultLanguage of generated commit subjects, bodies, and tag messages; repo-default copies the language already in git log --oneline -20
remote_hostgithub | gitlab | bitbucket | gitea | othergithubSelects PR-vs-MR wording, blob size limits, and squash-merge semantics quoted in review and release guidance
signingoff | ssh | gpgoffAdds signing flags and commit.gpgsign setup to commit and tag flows

Preference areas to record as the user reveals them:

  • tooling — CLI vs GUI vs IDE Git, hosting CLI in use, pre-commit framework, mergetool of choice
  • conventions — subject format, ticket-ID placement, tag scheme, trailers such as Co-authored-by, monorepo tag prefixes
  • thresholds — body-length and file-count limits a commit may reach, the large-file guard's size (--above=), reflog retention (gc.reflogExpireUnreachable), clone depth and filter in CI
  • restrictions — repos, paths, or file types the agent must leave alone; operations banned outright (no rebase, no filter-repo); compliance regimes demanding signed or reviewed commits
  • platform — hosting provider, SSH vs HTTPS, monorepo vs polyrepo, Windows/macOS line-ending and case sensitivity constraints
  • safety posture — whether the agent may commit or push unprompted, confirmation before --hard/clean -f/history rewrites
  • work order — commit granularity, whether to sync before starting, review gates expected before a push
  • cadence — how often to fetch/prune, when to run maintenance on large clones

When To Use

  • Any task touching a Git repository: staging, commits, branches, merges, rebases, tags, stashes, submodules.
  • Something looks lost — deleted branch, bad rebase, hard reset, vanished stash: recovery is a first-class use (→ Recovery Playbook, recovery.md).
  • Git refuses to run and the message is opaque (index.lock, non-fast-forward, dubious ownership, detached HEAD) → errors.md.
  • Before any history rewrite or force push: run the Output Gates below first.
  • Investigating when a behavior broke, who changed a line, or where code came from → forensics.md.
  • Not for CI pipeline configuration — GitHub workflows are github-actions, GitLab pipelines are gitlab; writing the PR description itself is pull-request.

Quick Reference

SituationFile
Staging surgery, splitting a mixed change, wording a message, stashingcommits.md
Creating or switching branches, merge vs rebase, stacked branchesbranching.md
A merge or rebase stopped on conflictsconflicts.md
Undoing: reset, revert, amend, rewriting a branch before reviewhistory.md
Work looks lost: bad reset, dropped stash, deleted branch, detached commitsrecovery.md
Git printed an error and refuses to proceederrors.md
"When did this break", "who wrote this line", "where did this code go"forensics.md
Push/pull friction, review flow, force-pushing on a shared branchcollaboration.md
Forks, upstreams, mirrors, moving or splitting a repositoryremotes.md
Two checkouts at once: hotfix mid-refactor, parallel agent tasksworktrees.md
Nested repositories: submodules, subtrees, vendored codesubmodules.md
Slow clone or status, monorepo scale, huge files, LFSlarge-repos.md
Pre-commit/pre-push automation, lint gates, a hook that never runshooks.md
A credential or a giant blob reached the historysecrets.md
Wrong author identity, auth failures, ignore rules, CRLF churnconfig.md
Tags, version bumps, backports, release branches, changelogsreleases.md
A flag or one-time config that removes a whole trap classcommands.md
Git driven from a script, a CI job, or a non-interactive agentscripting.md
User states a workflow preferencesetup.md + memory-template.md
Anything elseStay here — Core Rules, Revision Syntax, and the Recovery Playbook cover the default path

Core Rules

  1. Rewrite only unpushed history. Check: git log @{u}.. lists exactly the commits safe to amend/rebase/squash. A commit missing from that output is published — fix forward with git revert instead.
  2. Force push = --force-with-lease, own branch only, never a branch in protected_branches. The lease is void if anything fetched after the remote moved — IDE auto-fetch does this without warning — so add --force-if-includes (git >=2.30) to close that hole.
  3. Destructive command → name the casualties first. git status before reset --hard, git clean -n before git clean -f, git diff @{u} before force push. If you cannot list what dies, you are not ready to run it. Cheap insurance when you are unsure: git branch backup/$(date +%F-%H%M) costs one ref and zero bytes.
  4. git reflog before panic. Committed work survives 90 days (reachable) / 30 days (unreachable) — those are reflog-entry lifetimes, and a commit some reflog entry still names does not count as unreachable, so gc's shorter two-week prune window never applies to it (→ recovery.md). The only truly unrecoverable losses: never-staged edits killed by reset --hard/restore, and untracked files killed by clean -f.
  5. Conflicts repeat per commit in rebase, once in merge. Same region conflicting across 3+ replayed commits → abort and merge instead (one resolution), or enable rerere so each resolution is recorded once.
  6. Commit = one reviewable change. Mixed changes → git add -p to split. Subject: aim ≤50 chars (convention), hard stop subject_max, default 72 because git log indents bodies by four spaces inside an 80-column terminal — hosts truncate around the same width in list views. Body explains why, not what; subject and body both follow message_language.
  7. A pushed secret is a leaked secret. Rotate the credential first; history rewrite (filter-repo) is cleanup, not containment — forks, clones, and CI caches keep the old objects.
  8. Escalate undo by blast radius; stop at the first tool that reaches the goal. git restore (one file, nothing else moves) → git revert (one commit, safe on shared branches) → git reset (moves your branch pointer only) → git rebase (new SHAs, everyone tracking the branch pays) → git filter-repo (every clone in existence is now wrong). Reaching for the right-hand tools when a left-hand one suffices is the single most common self-inflicted Git incident.

Revision Syntax

Most "Git did something I did not ask for" reports are a misread revision expression. Decoder:

ExpressionMeansTrap
HEAD~2Two commits back along first parentsFollows the mainline through merges, skipping the merged branch
HEAD^2The SECOND PARENT of a merge commitNot "two back": ^ selects a parent, ~ walks generations
HEAD@{2}Where HEAD pointed two reflog moves agoTime, not ancestry — and local to this clone only
@{u} / @{push}The tracked upstream / where a push would landThey differ in triangular setups (fork: pull from upstream, push to origin)
A..BCommits reachable from B but not AIn git diff, the same expression means the plain A-to-B diff
A...Blog: commits on either side but not both. diff: B against the MERGE-BASEThe one expression whose meaning changes between log and diff — the source of "my diff shows unrelated files"
:/fix loginMost recent commit whose message contains that textSearches all reachable history, not just this branch
:1:file :2:file :3:fileDuring a conflict: base, ours, theirsNumbering is fixed; "ours/theirs" inverts under rebase (→ Conflict Basics)
main@{yesterday}Branch tip as of yesterdayReflog-based: empty in a fresh clone, and gone after reflog expiry
v1.2^{}The commit an annotated tag points atWithout peeling, a tag is its own object — git diff v1.2 compares against the tag object's target, scripts that assume a commit break

Ambiguity between a branch and a path is resolved with --: git checkout -- config is always the file.

Recovery Playbook

SymptomPlay
Just finished a bad rebase/merge/resetgit reset --hard ORIG_HEAD — Git saved your pre-operation position
Commits vanished after a rewritegit refloggit reset --hard HEAD@{n} (the entry just before the damage)
Deleted a branchgit refloggit branch restored <sha>
Committed on the wrong branch (unpushed)git switch right-branch && git cherry-pick <sha>, then git switch - && git reset --hard HEAD~1
Committed on detached HEAD, then switched awayCommit stays in git reflog for 30 days → git branch rescue <sha>
Need one file as it was N commits agogit restore --source HEAD~N -- path — nothing else moves
reset --hard ate staged-but-uncommitted workgit fsck --lost-found — staged content survives as dangling blobs; never-staged edits are gone
Dropped a stashgit fsck --unreachable | grep commitgit stash apply <sha>
Bad commit already on a shared branchgit revert <sha> — never rewrite shared history
Unsure what happened / anything elsegit reflog first; before experimenting, git branch backup — a branch is free insurance

Deeper chains (deleted file archaeology, corrupted index, post-filter-repo rescue, what expiry actually deletes): recovery.md.

Commit Discipline

  • One reviewable change per commit; git add -p splits mixed work. git commit --fixup <sha> + git rebase -i --autosquash batches corrections without "fix typo" noise.
  • Match the repo's existing message style before imposing one — check git log --oneline -20, or follow commit_style and message_language when the user set them. Conventional commits (type(scope): description) only where the log or release tooling already uses them.
  • git pull --rebase --autostash before push: no surprise merge commits, works with a dirty tree.
  • First push: git push -u origin HEAD, or set push.autoSetupRemote (git >=2.37) once and never type -u again.

Conflict Basics

  • Set merge.conflictStyle zdiff3 (git >=2.35) once: markers include the base version, so you see what each side changed instead of guessing intent.
  • Ours/theirs invert during rebase: "ours" = the branch you are rebasing onto, "theirs" = your own commit being replayed — rebase checks out upstream and applies your commits as patches on top.
  • After resolving: git grep -nE '^(<{7}|={7}|>{7})' must return nothing, then build/tests, then --continue.
  • Everything else → conflicts.md.

Output Gates

Before declaring Git work done:

  • Rewrite gate: every amended/rebased commit appeared in git log @{u}.. before I touched it
  • Deletion gate: I listed the casualties (git status, git clean -n) before any --hard / -f
  • Push gate: target is not in protected_branches and not a shared branch; if forcing at all, --force-with-lease minimum, and within force_push_policy
  • Conflict gate: marker grep is clean AND the project builds after resolution
  • Identity gate: git config user.email is the right identity for this repo (work vs personal)
  • Content gate: git diff --cached --stat reviewed — no credential, no build artifact, no blob the host will reject

Traps

TrapWhy it failsDo instead
git stash before a risky operation, expecting untracked files savedPlain stash skips untracked filesgit stash -u
Assuming stash pop dropped the stash after a conflictPop only drops on clean apply; on conflict the entry staysResolve, then git stash drop
git clean -fdx to "clean build artifacts"-x also deletes ignored files: .env, IDE config, local secretsgit clean -fd, always preview with -n
Renaming Foo.jsfoo.js works locally, breaks CImacOS/Windows filesystems are case-insensitive, Linux is notgit mv Foo.js tmp && git mv tmp foo.js
git branch -d refuses to delete after squash-mergeSquashed commits are unreachable from main, so Git thinks the branch is unmergedVerify the PR merged, then -D
Committing a large binary "just this once"GitHub warns >50 MB, blocks >100 MB — and history keeps the blob foreverGit LFS before first commit; after the fact, git filter-repo (secrets.md)
"Sharing" hooks via .git/hooks.git/hooks is never versionedCommit a hooks dir + git config core.hooksPath (hooks.md)
Cloned repo has empty submodule directoriesSubmodules need explicit initializationgit clone --recurse-submodules, or git submodule update --init
Adding a path to .gitignore to stop tracking itIgnore rules never apply to already-tracked files — the file keeps showing up in every diffgit rm --cached <path>, commit the removal, then ignore it
git reset --hard when the intent was "unstage this"--hard also throws away the working tree; unstaging needs no destructive flaggit restore --staged <path> (index only)
Marking a config file --assume-unchanged so local edits stop appearingGit now lies in status, and any incoming change to that file breaks pull with a confusing errorCommit a .example template, gitignore the real file (config.md)

Where Experts Disagree

  • Squash-merge vs preserve commits. Squash school treats PR commits as WIP noise (small PRs, GitHub-centric teams); preserve school needs atomic commits for bisect and surgical reverts (long-lived repos, kernel-style review). Follow the repo's existing merge style — mixing styles hurts more than either choice.
  • Trunk-based vs long-lived branches. DORA research associates branches merged within about a day with higher delivery performance; git-flow-style release branches pay off only when you maintain multiple released versions in parallel.
  • Conventional commits. Pay off when tooling consumes them (changelog generation, semver automation); pure ceremony otherwise. Detect: release automation in the repo → use them.
  • Mandatory commit signing. Provenance school signs everything (supply-chain audits, OSS releases, regulated code). Skeptics note that a signature proves a key was present, not that the author was — a compromised laptop signs happily. Boundary: sign what outsiders consume; internal application repos gain little beyond noise.

Related Skills

More Clawic skills, get them at https://clawic.com/skills/git (install if the user confirms):

  • pull-request — when the branch is ready and the PR itself has to be written and validated
  • review-code — when the job is judging someone else's diff, not producing it
  • github-actions — when the failure is in workflow YAML rather than in the repository
  • gitlab — GitLab CI/CD pipelines and merge-request settings
  • code — planning, implementing, and verifying the change the commits will carry

Feedback

Part of Clawic, the verified skill library. Get this skill: https://clawic.com/skills/git.

Related skills

Git Workflows

@gitgoodordietrying

Advanced git operations beyond add/commit/push. Use when rebasing, bisecting bugs, using worktrees for parallel development, recovering with reflog, managing subtrees/submodules, resolving merge conflicts, cherry-picking across branches, or working with monorepos.

513k

GitHub

@hith3sh

Work with GitHub repositories, issues, pull requests, commits, branches, releases, and workflows via the GitHub REST and GraphQL APIs. Use this skill when us...

325.8k

Summarizer

@ivangdavila

Summarizes any source without losing the claim: documents, meetings, papers, threads, transcripts, data, and code changes. Use when asked to summarize, condense, shorten, recap, distill, or write a TLDR, abstract, or executive summary; when a source is too long to read or must hit a word count; when summarizing a call, interview, Slack channel, pull request, contract, earnings report, podcast, or a stack of sources on one topic; when a summary dropped something important, invented a detail, turned a hedge into a fact, or reads like the headings; and when the same material must be re-cut for another audience, length, or channel. Covers compression ratios, chunking, faithfulness and omission audits. Not for recurring external feeds (`digest`), decision documents whose point is the recommendation (`brief`), cross-source insight generation rather than compression (`synthesize`), or pulling text or a transcript out of a file or video first (`extract-pdf-text`, `youtube-video-transcript`).

46.9k

SQL

@ivangdavila

Writes, reviews, and optimizes SQL queries; designs schemas, indexes, and constraints; plans migrations for any relational database. Use when a query is slow, EXPLAIN shows a sequential scan, or an index is ignored; when rows come back duplicated, missing, or with inflated totals after a JOIN; on deadlocks, lock timeouts, "too many connections", or transactions that never commit; when designing tables, keys, and column types, normalizing or denormalizing a model, or deciding between a JSON column and real columns; for ALTER TABLE on a live table, expand-migrate-contract rollouts, backups and restores, replication lag, connection pooling, partitioning, bulk CSV imports, and moving data between engines; for window functions, CTEs, keyset pagination, upserts, full-text search, multi-tenancy, row-level security, and timezone handling in MySQL, SQLite, MariaDB, or SQL Server. Not for PostgreSQL server internals such as vacuum tuning and work_mem sizing, and not for ORM schema modeling inside a framework.

84.3k

GitHub

@byungkyu

GitHub API integration with managed OAuth. Access repositories, issues, pull requests, commits, branches, and users. Use this skill when users want to interact with GitHub repositories, manage issues and PRs, search code, or automate workflows. For other third party apps, use the api-gateway skill (

4718k

GitLab

@hith3sh

Work with GitLab projects, issues, merge requests, commits, branches, pipelines, and groups via the GitLab API. Use this skill when users want to list projec...

325.6k