Advanced Commands
git rebase <branch>→ Reapply commits on top of another base branchgit cherry-pick <commit>→ Apply a specific commit to current branchgit tag <tagname>→ Create a taggit tag→ List tagsgit push origin <tag>→ Push tag to remote
git rebase
git rebase <upstream> [<branch>]
git rebase --onto <newbase> [<upstream>] [<branch>]
git rebase -i [<upstream>] [<branch>]
git rebase (--continue | --skip | --abort | --quit)# Bring feature up to date with main:
git checkout feature
git fetch origin
git rebase origin/main
# Keep base of current branch (fast update if unchanged):
git rebase --keep-base
# Change base arbitrarily with --onto:
git rebase --onto new-base old-base feature
# Meaning: Take commits on feature that come after old-base and replay them onto new-base.
# Continue/resolve after conflicts:
git rebase --continue
git rebase --skip
git rebase --abort
git rebase --quit- Description: The
git rebasereapplies one branch’s commits on top of another base commit, effectively rewriting history to make it linear. - Usage: Keep history linear - It update a feature branch to include the latest changes from main while keeping a straight-line history.
- Think Tank: Instead of merging two histories together, rebase “lifts” your commits and “replays” them on the target base, producing a cleaner, linear sequence of commits.
| Option | Description |
|---|---|
-i, --interactive |
Edit, reorder, squash, or fixup commits before replaying |
--onto |
Rebase selected commits onto a different base commit or branch |
--keep-base |
Rebase onto the branch’s configured upstream only if needed, otherwise keep base |
--rebase-merges |
Preserve or reconstruct branch topology and merges during rebase |
--exec |
Run a command after each commit is applied (e.g., run tests) |
--root |
Rebase all commits starting from the root (use carefully) |
--autosquash |
Automatically reorder and squash commits marked with “fixup!” or “squash!” |
--continue / --skip / --abort / --quit
|
Control the rebase session during conflicts or errors |
- Best Practices:
- Prefer rebase for local feature branches: Keep history linear before opening a PR.
- Coordinate with your team: Agree on merge vs rebase policies; never rebase main or shared long-lived branches.
- Use interactive rebase to polish commits: Squash small fixups, reword messages, and split logical changes.
- Protect collaborators with lease: Use
git push --force-with-leaseafter rebasing to avoid overwriting others’ work. - Automate checks: Use
--execor run tests after each step during complex rebases.
How it works
- Find common ancestor: Git determines the merge base between your branch and the target upstream.
- Collect your commits: Commits on your branch after the merge base are selected to be replayed.
- Replay (apply) commits: Each selected commit’s patch is applied, one by one, onto the upstream tip, creating new commits with new hashes.
- Move branch pointer: Your branch pointer is updated to point to the last newly created commit.
- Outcome: You get a linear history as if your work started from the latest upstream state.
Interactive rebase
Interactive rebase lets you edit the commit list before replaying it, enabling you to squash, reorder, or edit commits for a clean history.
# Start interactive rebase against upstream:
git rebase -i origin/main
# Start interactive rebase for last N commits:
git rebase -i HEAD~5
# Edit the todo list: You’ll see lines like:
pick a1b2c3 Add login button
pick d4e5f6 Fix CSS for header- Change actions:
- pick: Keep commit as-is
- reword: Change commit message
- edit: Pause to amend content
- squash: Combine with previous commit, keep both messages (editable)
- fixup: Combine with previous commit, discard current message
- drop: Remove the commit
- Finish flow: After resolving edits or conflicts, run
git rebase --continue
Advanced workflows
Autosquash with fixup commits:
git commit --fixup=<hash>
git rebase -i --autosquash origin/main
→ Automatically places fixup/squash commits next to their targets for cleaner history.
Preserve merges:
git rebase --rebase-merges origin/main
→ Reconstructs merge commits rather than flattening them.
Split a commit into multiple:
git rebase -i HEAD~1
# change action to 'edit', then:
git reset HEAD^
# stage and commit pieces separately, then:
git rebase --continue
Change base of a topic chain:
git rebase --onto feature-base old-base topic
→ Useful when the original base becomes obsolete or must be replaced.
Risks, limitations, and etiquette
- History rewrite: Rebasing changes commit hashes. Avoid rebasing public/shared branches that others have already pulled.
- Force push requirement: After rebasing a branch that’s pushed, you must update the remote with
git push --force-with-lease. - Lost context risk: Squashing and reordering may obscure how code evolved; balance cleanliness with traceability.
- Complex merges: Rebasing through merge-heavy histories can be difficult; consider
git mergeor--rebase-merges. - Binary changes and large diffs: Manual conflict resolution can be tedious; plan rebases before major refactors land.
Git - git-rebase Documentation

git cherry-pick
git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff] [-S[<keyid>]] <commit>…
git cherry-pick (--continue | --skip | --abort | --quit)# Apply a single commit to the current branch:
git cherry-pick <commit>
# Apply multiple commits in order:
git cherry-pick <commit1> <commit2> <commit3>
# Cherry-pick the latest commit from another branch:
git cherry-pick <branch-name>
# Continue or abort after resolving conflicts:
git cherry-pick --continue
git cherry-pick --abort
git cherry-pick --quit- Description: Apply the changes introduced by one or more existing commits onto your current branch, recording new commits that replicate those changes without merging entire branch histories.
- Usage: Bring one commit without merging whole branch
- Think Tank: Useful for hotfixes - Cherry-pick “replays” a specific commit’s diff on top of your branch, creating a new commit ID; it’s a precise way to transfer fixes or features across branches without merging everything.
- Best Practices:
- Prefer targeted fixes: Use cherry-pick for small, self-contained commits like hotfixes and backports
- Maintain traceability: Include
-xso teammates can map the pick back to its origin - Resolve thoughtfully: After conflicts, run tests and linters; consider amending the commit if adaptation was needed
- Avoid overuse: If you’re porting many commits, consider merging or rebasing instead to reduce duplication and maintenance burden
- Document intent: Add a clear message explaining why the change was cherry-picked (e.g., backport, hotfix, platform-specific fix)
Conflict resolution and flow
- When conflicts occur: Git stops with
CHERRY_PICK_HEADset; resolve conflicts in marked files, stage resolutions withgit add, then resume withgit cherry-pick --continue. Use--skipto drop the problematic commit or--abortto restore the pre-pick state. - What gets updated during a paused pick: Paths that applied cleanly are already updated in the index and working tree; only the conflicting hunks need attention before you continue
Advanced workflows
- Pick multiple related commits: Apply a sequence of commits explicitly to maintain logical order and reduce conflicts; cherry-picking supports selecting and applying several commits one-by-one.
- Cherry-pick into a new branch: Create a branch off the desired base, then cherry-pick the needed commits to port a fix or feature without merging full history.
- Traceability in shared repos: Use
-xto embed the original commit hash in the new commit message, making audit trails clearer across branches.
How it works
- Inverse of merge, targeted: Git locates the specified commit, computes the patch (diff) it introduced relative to its parent, applies that patch to your working tree, then creates a new commit on the current branch with the same changes and new metadata (new hash).
- Clean state required: Your working tree must be clean (no modifications from HEAD) before cherry-pick begins; otherwise Git will refuse to start.
- Conflicts handling: If applying a change isn’t obvious, Git pauses the process: the current branch stays at the last successful cherry-picked commit, sets
CHERRY_PICK_HEADto the problematic commit, and updates files that applied cleanly in the index and working tree until you resolve and continue.
git tag
git tag [options] [<tagname> [<commit>]]
git tag -a <tagname> -m "<message>" [<commit>]
git tag -d <tagname>...
git tag -l [<pattern>]
git tag -v <tagname>
# List all tags:
git tag
git tag -l "v1.*" # filter by pattern
# Create a lightweight tag:
git tag v1.0
# Create an annotated tag:
git tag -a v1.0 -m "Release version 1.0"
Tag a specific commit:
git tag v1.0 <commit-hash>
Delete a tag locally:
git tag -d v1.0
# Push tags to remote:
git push origin v1.0
git push origin --tags # push all tags
# Delete a tag on remote:
git push origin --delete v1.0
# Verify a signed tag:
git tag -v v1.0- Description: Tags are references (like branches) that point to specific commits, but unlike branches, they don’t move. They’re typically used to mark important points in history (e.g., releases, milestones).
- Usage: Create release points - It creates, lists, deletes, or verifies tags in Git.
- Think Tank:
- Lightweight tag: Just a pointer to a commit (like a branch without history).
- Annotated tag: A full object stored in Git database, containing tagger name, email, date, message, and optionally a GPG signature.
| Option | Description |
|---|---|
-a |
Create an annotated tag |
-m "" |
Add a message to annotated tag |
-s |
Create a GPG-signed tag |
-u |
Use specific key for signing |
-d |
Delete a tag |
-l |
List tags matching a pattern |
-v |
Verify a signed tag |
--sort= |
Sort tags (e.g., --sort=creatordate)
|
--column |
Display tags in columns |
- Best Practices:
- Use annotated tags for releases; they carry metadata and can be signed
- Always push tags after creating them if they’re meant to be shared
- Use semantic versioning (
v1.0.0,v2.1.3) for clarity - Keep tag messages descriptive (e.g., “Release candidate for v2.0”)
- Verify signed tags in collaborative projects for authenticity
Advanced Workflows
- Tagging releases: Teams often tag commits that represent release versions, then use those tags to generate release notes or build artifacts.
- Tagging after merge: You can tag a commit after merging a feature branch to mark the release point.
- Lightweight vs annotated:
- Lightweight tags are quick markers.
- Annotated tags are recommended for public releases because they store metadata.
- Tagging history: You can tag older commits to retroactively mark milestones.
# Signed tags for authenticity:
git tag -s v1.0 -m "Signed release"
# Ensures the tag is cryptographically verifiable
Git - git-tag Documentation


Updated on Dec 23, 2025