v1.0.0

Git Workflows

gitgoodordietrying gitgoodordietrying ← All skills

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.

Downloads
2.3k
Stars
0
Versions
1
Updated
2026-02-24

Install

npx clawhub@latest install git-workflows

Documentation

Git Workflows

Advanced git operations for real-world development. Covers interactive rebase, bisect, worktree, reflog recovery, subtrees, submodules, sparse checkout, conflict resolution, and monorepo patterns.

When to Use

  • -Cleaning up commit history before merging (interactive rebase)
  • -Finding which commit introduced a bug (bisect)
  • -Working on multiple branches simultaneously (worktree)
  • -Recovering lost commits or undoing mistakes (reflog)
  • -Managing shared code across repos (subtree/submodule)
  • -Resolving complex merge conflicts
  • -Cherry-picking commits across branches or forks
  • -Working with large monorepos (sparse checkout)

Interactive Rebase

Squash, reorder, edit commits

Rebase last 5 commits interactively

git rebase -i HEAD~5

Rebase onto main (all commits since diverging)

git rebase -i main

The editor opens with a pick list:

pick a1b2c3d Add user model

pick e4f5g6h Fix typo in user model

pick i7j8k9l Add user controller

pick m0n1o2p Add user routes

pick q3r4s5t Fix import in controller

Commands available:

pick   = use commit as-is

reword = use commit but edit the message

edit = stop after this commit to amend it

squash = merge into previous commit (keep both messages)

fixup = merge into previous commit (discard this message)

drop = remove the commit entirely

Common patterns

Squash fix commits into their parent

Change "pick" to "fixup" for the fix commits:

pick a1b2c3d Add user model

fixup e4f5g6h Fix typo in user model

pick i7j8k9l Add user controller

fixup q3r4s5t Fix import in controller

pick m0n1o2p Add user routes

Reorder commits (just move lines)

pick i7j8k9l Add user controller

pick m0n1o2p Add user routes

pick a1b2c3d Add user model

Split a commit into two

Mark as "edit", then when it stops:

git reset HEAD~

git add src/model.ts

git commit -m "Add user model"

git add src/controller.ts

git commit -m "Add user controller"

git rebase --continue

Autosquash (commit messages that auto-arrange)

When committing a fix, reference the commit to squash into

git commit --fixup=a1b2c3d -m "Fix typo"

or

git commit --squash=a1b2c3d -m "Additional changes"

Later, rebase with autosquash

git rebase -i --autosquash main

fixup/squash commits are automatically placed after their targets

Abort or continue

git rebase --abort      # Cancel and restore original state

git rebase --continue # Continue after resolving conflicts or editing

git rebase --skip # Skip the current commit and continue

Bisect (Find the Bug)

Binary search through commits

Start bisect

git bisect start

Mark current commit as bad (has the bug)

git bisect bad

Mark a known-good commit (before the bug existed)

git bisect good v1.2.0

or: git bisect good abc123

Git checks out a middle commit. Test it, then:

git bisect good # if this commit doesn't have the bug

git bisect bad # if this commit has the bug

Repeat until git identifies the exact commit

"abc123 is the first bad commit"

Done — return to original branch

git bisect reset

Automated bisect (with a test script)

Fully automatic: git runs the script on each commit

Script must exit 0 for good, 1 for bad

git bisect start HEAD v1.2.0

git bisect run ./test-for-bug.sh

Example test script

cat > /tmp/test-for-bug.sh << 'EOF'

#!/bin/bash

Return 0 if bug is NOT present, 1 if it IS

npm test -- --grep "login should redirect" 2>/dev/null

EOF

chmod +x /tmp/test-for-bug.sh

git bisect run /tmp/test-for-bug.sh

Bisect with build failures

If a commit doesn't compile, skip it

git bisect skip

Skip a range of known-broken commits

git bisect skip v1.3.0..v1.3.5

Worktree (Parallel Branches)

Work on multiple branches simultaneously

Add a worktree for a different branch

git worktree add ../myproject-hotfix hotfix/urgent-fix

Creates a new directory with that branch checked out

Add a worktree with a new branch

git worktree add ../myproject-feature -b feature/new-thing

List worktrees

git worktree list

Remove a worktree when done

git worktree remove ../myproject-hotfix

Prune stale worktree references

git worktree prune

Use cases

Review a PR while keeping your current work untouched

git worktree add ../review-pr-123 origin/pr-123

Run tests on main while developing on feature branch

git worktree add ../main-tests main

cd ../main-tests && npm test

Compare behavior between branches side by side

git worktree add ../compare-old release/v1.0

git worktree add ../compare-new release/v2.0

Reflog (Recovery)

See everything git remembers

Show reflog (all HEAD movements)

git reflog

Output:

abc123 HEAD@{0}: commit: Add feature

def456 HEAD@{1}: rebase: moving to main

ghi789 HEAD@{2}: checkout: moving from feature to main

Show reflog for a specific branch

git reflog show feature/my-branch

Show with timestamps

git reflog --date=relative

Recover from mistakes

Undo a bad rebase (find the commit before rebase in reflog)

git reflog

Find: "ghi789 HEAD@{5}: checkout: moving from feature to main" (pre-rebase)

git reset --hard ghi789

Recover a deleted branch

git reflog

Find the last commit on that branch

git branch recovered-branch abc123

Recover after reset --hard

git reflog

git reset --hard HEAD@{2} # Go back 2 reflog entries

Recover a dropped stash

git fsck --unreachable | grep commit

or

git stash list # if it's still there

git log --walk-reflogs --all -- stash # find dropped stash commits

Cherry-Pick

Copy specific commits to another branch

Pick a single commit

git cherry-pick abc123

Pick multiple commits

git cherry-pick abc123 def456 ghi789

Pick a range (exclusive start, inclusive end)

git cherry-pick abc123..ghi789

Pick without committing (stage changes only)

git cherry-pick --no-commit abc123

Cherry-pick from another remote/fork

git remote add upstream https://github.com/other/repo.git

git fetch upstream

git cherry-pick upstream/main~3 # 3rd commit from upstream's main

Handle conflicts during cherry-pick

If conflicts arise:

1. Resolve conflicts in the files

2. Stage resolved files

git add resolved-file.ts

3. Continue

git cherry-pick --continue

Or abort

git cherry-pick --abort

Subtree and Submodule

Subtree (simpler — copies code into your repo)

Add a subtree

git subtree add --prefix=lib/shared https://github.com/org/shared-lib.git main --squash

Pull updates from upstream

git subtree pull --prefix=lib/shared https://github.com/org/shared-lib.git main --squash

Push local changes back to upstream

git subtree push --prefix=lib/shared https://github.com/org/shared-lib.git main

Split subtree into its own branch (for extraction)

git subtree split --prefix=lib/shared -b shared-lib-standalone

Submodule (pointer to another repo at a specific commit)

Add a submodule

git submodule add https://github.com/org/shared-lib.git lib/shared

Clone a repo with submodules

git clone --recurse-submodules https://github.com/org/main-repo.git

Initialize submodules after clone (if forgot --recurse)

git submodule update --init --recursive

Update submodules to latest

git submodule update --remote

Remove a submodule

git rm lib/shared

rm -rf .git/modules/lib/shared

Remove entry from .gitmodules if it persists

When to use which

Subtree: Simpler, no special commands for cloners, code lives in your repo.

Use when: shared library, vendor code, infrequent upstream changes.

Submodule: Pointer to exact commit, smaller repo, clear separation.

Use when: large dependency, independent release cycle, many contributors.

Sparse Checkout (Monorepo)

Check out only the directories you need

Enable sparse checkout

git sparse-checkout init --cone

Select directories

git sparse-checkout set packages/my-app packages/shared-lib

Add another directory

git sparse-checkout add packages/another-lib

List what's checked out

git sparse-checkout list

Disable (check out everything again)

git sparse-checkout disable

Clone with sparse checkout (large monorepos)

Partial clone + sparse checkout (fastest for huge repos)

git clone --filter=blob:none --sparse https://github.com/org/monorepo.git

cd monorepo

git sparse-checkout set packages/my-service

No-checkout clone (just metadata)

git clone --no-checkout https://github.com/org/monorepo.git

cd monorepo

git sparse-checkout set packages/my-service

git checkout main

Conflict Resolution

Understand the conflict markers

<<<<<<< HEAD (or "ours")

Your changes on the current branch

=======

Their changes from the incoming branch

>>>>>>> feature-branch (or "theirs")

Resolution strategies

Accept all of ours (current branch wins)

git checkout --ours path/to/file.ts

git add path/to/file.ts

Accept all of theirs (incoming branch wins)

git checkout --theirs path/to/file.ts

git add path/to/file.ts

Accept ours for ALL files

git checkout --ours .

git add .

Use a merge tool

git mergetool

See the three-way diff (base, ours, theirs)

git diff --cc path/to/file.ts

Show common ancestor version

git show :1:path/to/file.ts # base (common ancestor)

git show :2:path/to/file.ts # ours

git show :3:path/to/file.ts # theirs

Rebase conflict workflow

During rebase, conflicts appear one commit at a time

1. Fix the conflict in the file

2. Stage the fix

git add fixed-file.ts

3. Continue to next commit

git rebase --continue

4. Repeat until done

If a commit is now empty after resolution

git rebase --skip

Rerere (reuse recorded resolutions)

Enable rerere globally

git config --global rerere.enabled true

Git remembers how you resolved conflicts

Next time the same conflict appears, it auto-resolves

See recorded resolutions

ls .git/rr-cache/

Forget a bad resolution

git rerere forget path/to/file.ts

Stash Patterns

Stash with a message

git stash push -m "WIP: refactoring auth flow"

Stash specific files

git stash push -m "partial stash" -- src/auth.ts src/login.ts

Stash including untracked files

git stash push -u -m "with untracked"

List stashes

git stash list

Apply most recent stash (keep in stash list)

git stash apply

Apply and remove from stash list

git stash pop

Apply a specific stash

git stash apply stash@{2}

Show what's in a stash

git stash show -p stash@{0}

Create a branch from a stash

git stash branch new-feature stash@{0}

Drop a specific stash

git stash drop stash@{1}

Clear all stashes

git stash clear

Blame and Log Archaeology

Who changed each line (with date)

git blame src/auth.ts

Blame a specific line range

git blame -L 50,70 src/auth.ts

Ignore whitespace changes in blame

git blame -w src/auth.ts

Find when a line was deleted (search all history)

git log -S "function oldName" --oneline

Find when a regex pattern was added/removed

git log -G "TODO.*hack" --oneline

Follow a file through renames

git log --follow --oneline -- src/new-name.ts

Show the commit that last touched each line, ignoring moves

git blame -M src/auth.ts

Show log with file changes

git log --stat --oneline -20

Show all commits affecting a specific file

git log --oneline -- src/auth.ts

Show diff of a specific commit

git show abc123

Tags and Releases

Create annotated tag (preferred for releases)

git tag -a v1.2.0 -m "Release 1.2.0: Added auth module"

Create lightweight tag

git tag v1.2.0

Tag a past commit

git tag -a v1.1.0 abc123 -m "Retroactive tag for release 1.1.0"

List tags

git tag -l

git tag -l "v1.*"

Push tags

git push origin v1.2.0 # Single tag

git push origin --tags # All tags

Delete a tag

git tag -d v1.2.0 # Local

git push origin --delete v1.2.0 # Remote

Tips

  • -git rebase -i is the single most useful advanced git command. Learn it first.
  • -Never rebase commits that have been pushed to a shared branch. Rebase your local/feature work only.
  • -git reflog is your safety net. If you lose commits, they're almost always recoverable within 90 days.
  • -git bisect run with an automated test is faster than manual binary search and eliminates human error.
  • -Worktrees are cheaper than multiple clones — they share .git storage.
  • -Prefer git subtree over git submodule unless you have a specific reason. Subtrees are simpler for collaborators.
  • -Enable rerere globally. It remembers conflict resolutions so you never solve the same conflict twice.
  • -git stash push -m "description" is much better than bare git stash. You'll thank yourself when you have 5 stashes.
  • -git log -S "string" (pickaxe) is the fastest way to find when a function or variable was added or removed.

Launch an agent with Git Workflows on Termo.