Git Advanced: Rebase, Cherry-Pick, and Bisect

Most developers use 10% of Git’s features 90% of the time. The advanced commands — rebase, cherry-pick, and bisect — solve problems that arise regularly in collaborative codebases, and avoiding them creates the messy merge histories and slow debugging processes that make repositories harder to work with over time.

Rebase

What rebase does: takes the commits on your branch and replays them on top of another branch, producing a linear history without merge commits. Compare: `git merge main` creates a merge commit that records two parents; `git rebase main` moves your branch’s commits to start from the tip of main, rewriting their SHA hashes. When to rebase: before merging a feature branch into main, to incorporate changes from main without creating merge commits; to clean up a messy local branch history before a code review. Interactive rebase (`git rebase -i HEAD~N`): the most powerful tool in Git for history editing. Opens an editor listing the last N commits, each with an action word:
– `pick` — keep the commit as-is
– `reword` — keep the commit but edit the message
– `edit` — pause here to amend the commit
– `squash` — combine this commit with the previous one (keeps both messages)
– `fixup` — combine with previous but discard this commit’s message
– `drop` — delete this commit entirely

Common use: squashing 8 work-in-progress commits into 1 clean commit before merging. The golden rule: never rebase commits that have already been pushed to a shared branch. Rebase rewrites history; if others have based work on the original commits, they will have conflicts. Rebase only commits that are local or on branches you own exclusively. Force-push after rebase: after rebasing a branch you have already pushed, you must force-push (`git push –force-with-lease`). Use `–force-with-lease` not `–force` — it fails if someone else has pushed to the branch since you last fetched, preventing accidental history loss.

Cherry-Pick and Bisect

Cherry-pick (`git cherry-pick `): applies a specific commit from anywhere in the repository onto your current branch. Creates a new commit with the same changes but a new SHA. When to use: backporting a bug fix from main to a release branch; pulling a specific feature commit from a colleague’s branch without merging everything. Multiple commits: `git cherry-pick A..B` picks all commits between A and B (exclusive of A, inclusive of B). With `-n` flag: applies changes without committing, allowing you to modify them first. Conflicts: cherry-pick conflicts are resolved like merge conflicts — edit the files, `git add`, then `git cherry-pick –continue`. Bisect (`git bisect`): a binary search over commit history to find the commit that introduced a bug. Essential for debugging regressions in large codebases where the failing commit is not obvious. The workflow:
“`bash
git bisect start
git bisect bad # current commit is broken
git bisect good v1.2.0 # this tagged version was working

# Git checks out the midpoint commit
# test it, then:
git bisect good # or: git bisect bad
# Git halves the range and checks out the next midpoint
# repeat until Git identifies the first bad commit
git bisect reset # return to original HEAD
“`
Bisect can also be automated: `git bisect run ./test.sh` runs a script on each candidate commit — exit code 0 means good, non-zero means bad. For a 1000-commit range, bisect finds the culprit in ~10 steps (log₂1000 ≈ 10). Reflog (`git reflog`): Git’s safety net — records every position HEAD has been at, including rebases, resets, and checkouts. If you accidentally lose commits to a hard reset or bad rebase, `git reflog` shows the SHA before the operation, and `git checkout` or `git reset` recovers it.

上一篇 印度美食:香料、地区和咖喱的真正含义
下一篇 Git进阶:变基、挑选和二分查找