Rebase for clean history

Interactive rebase

Reorder, squash, or rewrite a range of commits:

git rebase -i HEAD~5

Common directives:

  • pick: keep the commit
  • reword: edit the message
  • squash: merge into the previous commit
  • edit: pause to adjust content

Resolve conflicts and continue

git status
# fix conflict markers <<<<<<< ======= >>>>>>>
git add <resolved-file>
git rebase --continue
git rebase --abort

Coordinate with the team

Rewriting shared history requires coordination. Prefer git push --force-with-lease to avoid overwriting teammates’ work.

Combining rebase and merge

  • git pull --rebase: replay local commits on top of fetched history.
  • git rebase origin/master: update a feature branch with the latest mainline.
  • git merge --no-ff: keep a merge node to document feature boundaries.

Bisect: binary-search bugs

Quickly locate the commit that introduced a regression:

git bisect start
git bisect bad HEAD
git bisect good v1.1.0

Run the relevant tests at each step:

<run test suite>
# mark the result
git bisect good
git bisect bad

Reset afterwards:

git bisect reset

Worktree: parallel checkouts

Keep multiple branches checked out without cloning again:

git worktree add ../repo-hotfix hotfix/20251010
  • Inspect with git worktree list.
  • Remove when done via git worktree remove ../repo-hotfix.

Advanced stash usage

  • Stash specific paths: git stash push -m "wip" -- src/service
  • Inspect a stash: git stash show -p stash@{1}
  • Export as a patch: git stash show -p > fix.patch

Submodules

Link external repositories inside the main project:

git submodule add https://github.com/org/lib libs/lib

Initialise or update recursive dependencies:

git submodule update --init --recursive

When removing, clean up .gitmodules and .git/config entries as well.

Sparse checkout

Fetch a huge repository but only check out specific directories:

git sparse-checkout init --cone
git sparse-checkout set services/api services/common

Restore the full tree with git sparse-checkout disable.

Hooks and automation

Scripts under .git/hooks run at various lifecycle events. Example pre-commit hook:

#!/bin/sh
npm run lint && npm test

Save as .git/hooks/pre-commit and make executable with chmod +x. For shared hooks, tools like Husky or lefthook keep scripts versioned.

Credentials and security

  • Use git credential-manager or git-credential-osxkeychain to store tokens.
  • Revoke cached credentials via git credential reject.
  • Manage multiple SSH identities with the ~/.ssh/config file.

Multi-remote workflows

Add additional remotes for upstream synchronisation or backups:

git remote add upstream [email protected]:org/main.git
git remote add backup [email protected]:org/mirror.git

Sync strategy:

git fetch upstream
git merge upstream/master      # or cherry-pick selected commits
git push backup main

Inspect repository internals

Useful plumbing commands for debugging:

git rev-list --count HEAD
git cat-file -p <object>
git fsck

Final notes

Paired with the essentials guide, these commands cover most collaboration pain points—from keeping history tidy to diagnosing tricky regressions. When in doubt, reach for git help <command> and practice on throwaway branches before touching production history.