git-advanced
Use this skill when performing advanced git operations, rebase strategies, bisecting bugs, managing worktrees, configuring hooks, or handling complex merge scenarios. Triggers on interactive rebase, git bisect, worktrees, pre-commit hooks, cherry-pick, reflog recovery, stash management, and any task requiring advanced git workflows.
devtools gitrebasebisectworktreeshooksversion-controlWhat is git-advanced?
Use this skill when performing advanced git operations, rebase strategies, bisecting bugs, managing worktrees, configuring hooks, or handling complex merge scenarios. Triggers on interactive rebase, git bisect, worktrees, pre-commit hooks, cherry-pick, reflog recovery, stash management, and any task requiring advanced git workflows.
git-advanced
git-advanced is a production-ready AI agent skill for claude-code, gemini-cli, openai-codex. Performing advanced git operations, rebase strategies, bisecting bugs, managing worktrees, configuring hooks, or handling complex merge scenarios.
Quick Facts
| Field | Value |
|---|---|
| Category | devtools |
| Version | 0.1.0 |
| Platforms | claude-code, gemini-cli, openai-codex |
| License | MIT |
How to Install
- Make sure you have Node.js installed on your machine.
- Run the following command in your terminal:
npx skills add AbsolutelySkilled/AbsolutelySkilled --skill git-advanced- The git-advanced skill is now available in your AI coding agent (Claude Code, Gemini CLI, OpenAI Codex, etc.).
Overview
Git is a distributed version control system built on a directed acyclic graph (DAG) of immutable commit objects. Most developers use only 20% of git's power - add, commit, push, pull. The remaining 80% covers the workflows that separate a junior from a senior: precise history rewriting with interactive rebase, surgical bug hunting with bisect, parallel development with worktrees, automated quality gates with hooks, and safe history recovery with reflog. This skill equips an agent to handle any advanced git task with confidence.
Tags
git rebase bisect worktrees hooks version-control
Platforms
- claude-code
- gemini-cli
- openai-codex
Related Skills
Pair git-advanced with these complementary skills:
Frequently Asked Questions
What is git-advanced?
Use this skill when performing advanced git operations, rebase strategies, bisecting bugs, managing worktrees, configuring hooks, or handling complex merge scenarios. Triggers on interactive rebase, git bisect, worktrees, pre-commit hooks, cherry-pick, reflog recovery, stash management, and any task requiring advanced git workflows.
How do I install git-advanced?
Run npx skills add AbsolutelySkilled/AbsolutelySkilled --skill git-advanced in your terminal. The skill will be immediately available in your AI coding agent.
What AI agents support git-advanced?
This skill works with claude-code, gemini-cli, openai-codex. Install it once and use it across any supported AI coding agent.
Maintainers
Generated from AbsolutelySkilled
SKILL.md
Git Advanced
Git is a distributed version control system built on a directed acyclic graph (DAG) of immutable commit objects. Most developers use only 20% of git's power - add, commit, push, pull. The remaining 80% covers the workflows that separate a junior from a senior: precise history rewriting with interactive rebase, surgical bug hunting with bisect, parallel development with worktrees, automated quality gates with hooks, and safe history recovery with reflog. This skill equips an agent to handle any advanced git task with confidence.
When to use this skill
Trigger this skill when the user:
- Wants to squash, fixup, reorder, or edit commits with interactive rebase
- Needs to find the exact commit that introduced a bug (git bisect)
- Wants to work on multiple branches simultaneously without stashing (worktrees)
- Needs to set up pre-commit, commit-msg, or other git hooks
- Wants to cherry-pick specific commits across branches
- Has lost commits, stashes, or rebased away work and needs recovery
- Needs to handle a complex merge conflict with diverged histories
- Asks about stash management, patch workflows, or reflog navigation
Do NOT trigger this skill for:
- Basic git operations (add, commit, push, pull, clone) - no skill needed
- Repository hosting platform features (GitHub PRs, GitLab MRs, Bitbucket pipelines)
Key principles
Commit often, rebase before push - Small, frequent commits preserve context and make bisect effective. Before pushing to a shared branch, use interactive rebase to clean the history into logical, reviewable units.
Never rewrite shared history - Any branch that others have checked out must not be force-pushed. Rebase and amend only on local branches or feature branches you own.
git push --force-with-leaseover--forceif you must.Atomic commits - Each commit should represent one logical change that leaves the codebase in a working state. An atomic commit can be reverted or cherry-picked without side effects. If your commit message needs "and", split the commit.
Branch naming conventions - Use prefixes to communicate intent:
feat/,fix/,chore/,refactor/,docs/. Include a ticket number when applicable:feat/PROJ-123-user-auth. Lowercase, hyphens, no spaces.Hooks prevent bad commits - Git hooks are the last line of defense before code enters the repository. Pre-commit hooks run linters and formatters; commit-msg hooks enforce message conventions; pre-push hooks run tests. Automate quality at the source.
Core concepts
DAG model - Git history is a directed acyclic graph where each commit points to its parent(s). A commit is identified by a SHA-1 hash of its content, parent hashes, author, and message. Branches are just named pointers to commits. Understanding the DAG explains why rebasing "moves" commits (it creates new ones) and why merge creates a commit with two parents.
Refs, HEAD, and detached HEAD - HEAD is a pointer to the currently checked-out
commit. Normally it points to a branch ref (refs/heads/main), which points to a
commit. "Detached HEAD" means HEAD points directly to a commit SHA, not a branch.
This happens during rebase, bisect, and git checkout <sha>. Always create a branch
before committing in detached HEAD state.
Rebase vs merge - Both integrate changes from one branch into another, but with
different history shapes. Merge preserves the true history with a merge commit (two
parents). Rebase replays commits on top of the target, producing a linear history but
rewriting SHAs. Use merge for integrating shared branches (main, develop); use rebase
to keep feature branches current and clean before merging. See
references/rebase-strategies.md for detailed decision guidance.
Reflog as safety net - The reflog (git reflog) records every position HEAD has
been at, including rebases, resets, and amends. It retains entries for 90 days by
default. Any commit that was ever reachable is recoverable via reflog - it is the
ultimate undo mechanism. Nothing is truly lost until git gc runs and the reflog
entries expire.
Common tasks
Interactive rebase - squash, fixup, and reorder commits
Use interactive rebase to clean up local history before pushing. Always target a commit that is not on a shared branch.
# Rebase last N commits interactively
git rebase -i HEAD~5
# Rebase all commits since branching from main
git rebase -i $(git merge-base HEAD main)In the editor that opens, each line is a commit with an action keyword:
pick a1b2c3 feat: add login page
pick d4e5f6 wip: half-done validation
pick g7h8i9 fix typo
pick j0k1l2 fix: complete validation logic
pick m3n4o5 chore: remove console.logsChange keywords to reshape history:
squash(s) - merge into previous commit, combine messagesfixup(f) - merge into previous commit, discard this messagereword(r) - keep commit but edit the messageedit(e) - pause rebase to amend the commitdrop(d) - delete the commit entirely- Reorder lines to reorder commits
pick a1b2c3 feat: add login page
fixup g7h8i9 fix typo
squash j0k1l2 fix: complete validation logic
fixup d4e5f6 wip: half-done validation
drop m3n4o5 chore: remove console.logsIf conflicts arise during rebase:
# Resolve conflicts in the marked files, then:
git add <resolved-files>
git rebase --continue
# To abort and return to original state:
git rebase --abortGit bisect to find the commit that introduced a bug
Bisect performs a binary search through commit history to find the first bad commit. It requires you to identify one good commit and one bad commit.
# Start bisect session
git bisect start
# Mark the current commit as bad (has the bug)
git bisect bad
# Mark a known-good commit (before the bug existed)
git bisect good v2.1.0
# or by SHA:
git bisect good a1b2c3d
# Git checks out the midpoint - test, then mark:
git bisect good # if this commit does NOT have the bug
git bisect bad # if this commit DOES have the bug
# Repeat until git identifies the first bad commit.
# When done, reset to original branch:
git bisect resetAutomate bisect with a test script (exit 0 = good, exit 1 = bad):
git bisect start
git bisect bad HEAD
git bisect good v2.1.0
git bisect run npm test -- --testNamePattern="the failing test"
git bisect resetManage worktrees for parallel work
Worktrees allow multiple working directories from a single repository, each on a different branch. No stashing needed to switch context.
# List existing worktrees
git worktree list
# Add a new worktree for a feature branch (sibling directory)
git worktree add ../project-hotfix fix/PROJ-456-crash
# Add a worktree for a new branch that doesn't exist yet
git worktree add -b feat/PROJ-789-search ../project-search main
# Work in the worktree directory normally - all git operations are branch-specific
cd ../project-hotfix
git log --oneline -5
# Remove a worktree when done
git worktree remove ../project-hotfix
# Prune stale worktree references (if directory was manually deleted)
git worktree pruneSet up pre-commit hooks with Husky
Husky manages git hooks via npm scripts, checked into the repository so all team members share the same hooks.
# Install husky
npm install --save-dev husky
# Initialize husky (creates .husky/ directory and sets core.hooksPath)
npx husky initCreate .husky/pre-commit:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-stagedConfigure lint-staged in package.json:
{
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{css,md,json}": ["prettier --write"]
}
}Create .husky/commit-msg to enforce conventional commits:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no -- commitlint --edit "$1"# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# commitlint.config.js
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.jsRecover lost commits with reflog
The reflog records every HEAD movement. Use it when a rebase, reset, or amend discards commits you still need.
# View full reflog with timestamps
git reflog --date=relative
# Example reflog output:
# a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feat/search
# d4e5f6g HEAD@{1}: rebase (pick): fix: handle empty results
# e7f8g9h HEAD@{2}: rebase (start): checkout main
# f0a1b2c HEAD@{3}: commit: feat: add search indexing <-- the lost commit
# Recover by creating a branch at the lost commit SHA or reflog entry:
git checkout -b recovery/lost-search-indexing HEAD@{3}
# or
git checkout -b recovery/lost-search-indexing f0a1b2c
# Cherry-pick recovered commit onto your branch:
git checkout feat/search
git cherry-pick f0a1b2cTo recover a dropped stash:
# Find dangling commits (stashes are commits)
git fsck --lost-found | grep commit
# Inspect each dangling commit to find your stash content:
git show <dangling-sha>
# Apply the recovered stash:
git stash apply <dangling-sha>Cherry-pick specific commits across branches
Cherry-pick copies a commit (or range of commits) onto the current branch by replaying its diff.
# Cherry-pick a single commit by SHA
git cherry-pick a1b2c3d
# Cherry-pick a range (inclusive on both ends)
git cherry-pick a1b2c3d^..f0e9d8c
# Cherry-pick without immediately committing (stage only)
git cherry-pick --no-commit a1b2c3d
# If cherry-pick conflicts, resolve then:
git add <resolved-files>
git cherry-pick --continue
# Abort cherry-pick:
git cherry-pick --abortUse -x to annotate the cherry-picked commit message with the original SHA:
git cherry-pick -x a1b2c3d
# Adds "(cherry picked from commit a1b2c3d)" to the commit messageResolve complex merge conflicts
When branches have diverged significantly, use a three-way merge tool.
# See all conflicted files
git diff --name-only --diff-filter=U
# Open a visual merge tool (configured via git config merge.tool)
git mergetool
# For a specific file, compare all three versions:
git show :1:src/app.ts # common ancestor
git show :2:src/app.ts # ours (current branch)
git show :3:src/app.ts # theirs (incoming branch)
# Accept ours or theirs entirely for a file:
git checkout --ours src/app.ts
git checkout --theirs src/app.ts
# After resolving all conflicts:
git add .
git merge --continue
# If the merge is unrecoverable:
git merge --abortFor a long-lived feature branch, prefer rebase over merge to replay commits on top of main one at a time - resolving smaller, isolated conflicts rather than one massive merge conflict.
Error handling
| Error | Cause | Resolution |
|---|---|---|
CONFLICT (content): Merge conflict in <file> |
Two branches modified the same lines differently | Open file, resolve <<<<<<< markers, git add <file>, then git rebase --continue or git merge --continue |
error: cannot rebase: You have unstaged changes |
Working tree is dirty when starting rebase | git stash, rebase, then git stash pop |
fatal: refusing to merge unrelated histories |
Two repos with no common ancestor being merged | Use git merge --allow-unrelated-histories once; investigate why histories diverged |
error: failed to push some refs after rebase |
Remote has diverged (rebased shared history) | If the branch is yours alone: git push --force-with-lease. If shared: do not force-push, merge instead |
detached HEAD state after bisect/checkout |
HEAD points to commit SHA, not a branch | git checkout -b <new-branch> to save work, or git checkout <branch-name> to return |
Your local changes would be overwritten by checkout |
Uncommitted changes conflict with target branch | Commit or stash changes first: git stash push -m "wip: context", then switch branches |
Gotchas
Interactive rebase on commits already pushed to a shared branch will break teammates -
git rebase -irewrites SHAs. If anyone has already pulled those commits, their history diverges and they face painful force-merge situations. Only interactively rebase commits that exist solely on your local or personal feature branch. Usegit push --force-with-lease(never bare--force) if you must update a remote branch you own.git bisect resetis not optional - If you forget to rungit bisect resetafter a bisect session, HEAD remains detached at whatever commit bisect last checked out. Any work you commit in this state is not on any branch and is easily lost. Always rungit bisect resetbefore returning to normal development.Worktrees sharing the same branch causes confusing conflicts - Git prevents two worktrees from checking out the exact same branch simultaneously, but it's easy to accidentally make changes in one worktree that affect the index visible in another. Keep one branch per worktree and run
git worktree pruneafter removing worktree directories to prevent stale lock files.Reflog entries expire - you cannot recover commits after
git gcruns - The default reflog expiry is 90 days, butgit gcmay run automatically. Once a commit's reflog entry is gone and it's unreachable from any branch,git fsck --lost-foundis your last hope. When recovering, create a new branch immediately rather than cherry-picking from a detached state.Cherry-picking merge commits requires
-mto specify the mainline - Runninggit cherry-pick <merge-commit-sha>without specifying a parent number will fail with an error. You must supply-m 1(or-m 2) to tell git which side of the merge is the mainline. For most cases,-m 1picks the changes relative to the first parent (the branch that was merged into).
References
For detailed content on specific topics, read the relevant file from references/:
references/rebase-strategies.md- Rebase workflows, when to rebase vs merge, interactive rebase recipes for common scenarios
Only load a references file if the current task requires deep detail on that topic.
References
rebase-strategies.md
Rebase Strategies
Rebasing rewrites commit history by replaying commits on top of a new base. This produces a linear history but changes commit SHAs. Knowing when to rebase, when to merge, and how to compose interactive rebase sequences is the difference between clean, reviewable history and a tangled mess.
Rebase vs merge: the decision framework
Both integrate changes from one branch into another. The difference is in what the resulting history looks like and what guarantees you have.
| Dimension | Merge | Rebase |
|---|---|---|
| History shape | Non-linear; preserves true timeline | Linear; commit SHAs are rewritten |
| Merge commit | Yes - one commit with two parents | No - no merge commit |
| Conflict resolution | Once per merge | Once per replayed commit |
| Safety on shared branches | Always safe | Never safe (rewrites SHAs) |
| Bisect friendliness | Harder (merge commits clutter) | Excellent (linear = fast binary search) |
| Blame accuracy | Accurate (original dates preserved) | Dates change to replay time |
Rule of thumb:
git rebase- feature branches onto their target before pushing; local cleanupgit merge- integrating completed features into main/develop; shared branch updates
Workflow: keeping a feature branch current
When main advances while you are developing a feature, use rebase (not merge) to stay current. This avoids merge commits that clutter history with "Merge branch 'main' into feat/foo" noise.
# Fetch latest changes without checking out main
git fetch origin
# Rebase your feature branch on top of the updated main
git checkout feat/my-feature
git rebase origin/main
# Resolve any conflicts commit-by-commit, then:
git rebase --continueIf the feature branch has already been pushed and you are the only author:
# Force-push with a safety check (fails if someone else has pushed)
git push --force-with-lease origin feat/my-featureWorkflow: preparing a clean PR
Before opening a pull request, compress and organize your working commits into a set of logical, reviewable units using interactive rebase.
Goal: transform implementation commits into a readable story.
# See how many commits ahead of main you are
git log --oneline main..HEAD
# Start interactive rebase against the branch point
git rebase -i $(git merge-base HEAD origin/main)Typical raw history:
pick 1a2b3c4 feat: scaffold auth module
pick 5d6e7f8 wip
pick 9a0b1c2 fix lint
pick 3d4e5f6 add password hashing
pick 7a8b9c0 actually fix lint
pick 1b2c3d4 add tests
pick 5e6f7a8 fix test typo
pick 9b0c1d2 pr feedback: rename methodTarget clean history:
pick 1a2b3c4 feat: scaffold auth module
fixup 5d6e7f8 wip
fixup 9a0b1c2 fix lint
fixup 7a8b9c0 actually fix lint
squash 3d4e5f6 add password hashing
squash 1b2c3d4 add tests
fixup 5e6f7a8 fix test typo
fixup 9b0c1d2 pr feedback: rename methodResult: 2 clean commits - one for the module scaffold, one for the implementation with tests. Combined squash messages are edited to be descriptive.
Interactive rebase recipes
Recipe: combine all commits into one
Useful for experiments or trivial features with many micro-commits.
git rebase -i HEAD~8
# In editor: change all but the first 'pick' to 'fixup'
# Result: one commit with the message from the first pickRecipe: split a commit into two
Use edit to pause at a commit and amend it into multiple commits.
git rebase -i HEAD~3
# Change the target commit from 'pick' to 'edit'
# Git pauses at that commit - you are now in a mid-rebase state
# Undo the commit but keep the changes staged
git reset HEAD~
# Now selectively stage and commit parts:
git add src/auth.ts
git commit -m "feat: add authentication service"
git add src/auth.test.ts
git commit -m "test: add auth service unit tests"
# Continue the rebase
git rebase --continueRecipe: move a commit to a different position
Simply reorder lines in the interactive rebase editor. Git replays them in the order listed.
git rebase -i HEAD~5
# Move the line for the commit you want to reposition
# up or down relative to other commits
# Save and close - git replays in new orderRecipe: remove a debug commit before merging
git rebase -i HEAD~4
# Change 'pick' to 'drop' on the debug commit line
# That commit is deleted from history entirelyRecipe: reword a commit message without changing content
git rebase -i HEAD~3
# Change 'pick' to 'reword' on the target commit
# Git opens editor for just that commit message
# Edit and save - commit SHA changes, content unchangedRebase onto a different base
git rebase --onto lets you transplant a sequence of commits onto any base,
not just the current parent.
Scenario: You branched off a feature branch instead of main by mistake.
# Branch structure:
# main --- A --- B --- C (feat/base)
# \--- D --- E (feat/my-feature)
# Transplant feat/my-feature (D, E) onto main directly:
git rebase --onto main feat/base feat/my-feature
# Result:
# main --- A --- B --- C (feat/base)
# \--- D' --- E' (feat/my-feature)General syntax: git rebase --onto <new-base> <old-base> <branch>
Handling rebase conflicts
When replaying commits, git may encounter conflicts on any individual commit. Conflicts during rebase are smaller and more focused than merge conflicts because each replayed commit is a single unit of change.
# When a conflict occurs, git pauses and shows:
# CONFLICT (content): Merge conflict in src/config.ts
# error: could not apply a1b2c3... feat: update config schema
# 1. See the current state
git status
git diff
# 2. Resolve the conflict in each file
# 3. Stage the resolved files
git add src/config.ts
# 4. Do NOT commit - continue the rebase
git rebase --continue
# If a conflict makes you want to skip a commit entirely:
git rebase --skip
# If the rebase is unrecoverable, abort entirely:
git rebase --abort
# This returns HEAD to exactly where it was before the rebase startedMerge strategies for complex scenarios
When merging, git supports different merge strategies for special cases.
# Default recursive strategy (most cases)
git merge feat/my-feature
# Squash merge: bring in all changes as a single unstaged diff
# (common in GitHub/GitLab "squash and merge" workflows)
git merge --squash feat/my-feature
git commit -m "feat: add user authentication (#123)"
# No fast-forward: always create a merge commit even when FF is possible
# Preserves the branch topology in history
git merge --no-ff feat/my-feature
# Accept all changes from the incoming branch (theirs) on conflict
git merge -X theirs feat/my-feature
# Accept all changes from the current branch (ours) on conflict
git merge -X ours feat/my-featureCommon mistakes with rebase
| Mistake | Consequence | Prevention |
|---|---|---|
| Rebasing a branch others have checked out | Diverged history; teammates' pushes rejected | Never rebase branches on remotes that others track |
Using --force instead of --force-with-lease |
Silently overwrites teammates' pushes | Always use --force-with-lease when force-pushing |
| Rebasing a merge commit | Merge commit is replayed as a regular commit, losing parent structure | Use --rebase-merges flag to preserve merge commits |
Forgetting git rebase --abort on a bad conflict |
Left in partial rebase state | Always abort or continue - never leave a rebase half-done |
| Interactive rebasing past a pushed commit | Must force-push, risks losing others' work | Only rebase commits that have not been pushed to shared refs |
Frequently Asked Questions
What is git-advanced?
Use this skill when performing advanced git operations, rebase strategies, bisecting bugs, managing worktrees, configuring hooks, or handling complex merge scenarios. Triggers on interactive rebase, git bisect, worktrees, pre-commit hooks, cherry-pick, reflog recovery, stash management, and any task requiring advanced git workflows.
How do I install git-advanced?
Run npx skills add AbsolutelySkilled/AbsolutelySkilled --skill git-advanced in your terminal. The skill will be immediately available in your AI coding agent.
What AI agents support git-advanced?
git-advanced works with claude-code, gemini-cli, openai-codex. Install it once and use it across any supported AI coding agent.