git-advanced

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Git Advanced

Git 高级用法

Worktrees

Worktrees

bash
undefined
bash
undefined

Create a worktree for a feature branch (avoids stashing)

Create a worktree for a feature branch (avoids stashing)

git worktree add ../feature-auth feature/auth
git worktree add ../feature-auth feature/auth

Create a worktree with a new branch

Create a worktree with a new branch

git worktree add ../hotfix-123 -b hotfix/123 origin/main
git worktree add ../hotfix-123 -b hotfix/123 origin/main

List all worktrees

List all worktrees

git worktree list
git worktree list

Remove a worktree after merging

Remove a worktree after merging

git worktree remove ../feature-auth

Worktrees let you work on multiple branches simultaneously without stashing or committing WIP. Each worktree has its own working directory but shares the same `.git` repository.
git worktree remove ../feature-auth

Worktrees 允许你同时处理多个分支,无需执行暂存(stash)或提交未完成工作(WIP)的操作。每个工作树都有独立的工作目录,但共享同一个 `.git` 仓库。

Bisect

Bisect

bash
undefined
bash
undefined

Start bisect, mark current as bad and known good commit

Start bisect, mark current as bad and known good commit

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

Git checks out a midpoint commit. Test it, then mark:

Git checks out a midpoint commit. Test it, then mark:

git bisect good # if this commit works git bisect bad # if this commit is broken
git bisect good # if this commit works git bisect bad # if this commit is broken

Automate with a test script

Automate with a test script

git bisect start HEAD v1.5.0 git bisect run npm test
git bisect start HEAD v1.5.0 git bisect run npm test

When done, reset

When done, reset

git bisect reset

Bisect performs binary search across commits to find which commit introduced a bug. Automated bisect with `run` is the fastest approach.
git bisect reset

Bisect 会在提交记录中执行二分查找,帮你定位是哪次提交引入了 Bug。搭配 `run` 参数实现自动化 Bisect 是最快的排查方式。

Interactive Rebase

Interactive Rebase

bash
undefined
bash
undefined

Rebase last 5 commits interactively

Rebase last 5 commits interactively

git rebase -i HEAD~5
git rebase -i HEAD~5

Common operations in the editor:

Common operations in the editor:

pick - keep commit as-is

pick - keep commit as-is

reword - change commit message

reword - change commit message

edit - stop to amend the commit

edit - stop to amend the commit

squash - merge into previous commit, keep both messages

squash - merge into previous commit, keep both messages

fixup - merge into previous commit, discard this message

fixup - merge into previous commit, discard this message

drop - remove the commit entirely

drop - remove the commit entirely

Rebase feature branch onto latest main

Rebase feature branch onto latest main

git fetch origin git rebase origin/main
git fetch origin git rebase origin/main

Continue after resolving conflicts

Continue after resolving conflicts

git rebase --continue
git rebase --continue

Abort if things go wrong

Abort if things go wrong

git rebase --abort
undefined
git rebase --abort
undefined

Git Hooks

Git Hooks

bash
#!/bin/sh
bash
#!/bin/sh

.git/hooks/pre-commit

.git/hooks/pre-commit

Run linter on staged files only

Run linter on staged files only

STAGED_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '.(ts|tsx|js|jsx)$') if [ -n "$STAGED_FILES" ]; then npx eslint $STAGED_FILES --fix git add $STAGED_FILES fi

```bash
#!/bin/sh
STAGED_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '.(ts|tsx|js|jsx)$') if [ -n "$STAGED_FILES" ]; then npx eslint $STAGED_FILES --fix git add $STAGED_FILES fi

```bash
#!/bin/sh

.git/hooks/commit-msg

.git/hooks/commit-msg

Enforce conventional commit format

Enforce conventional commit format

COMMIT_MSG=$(cat "$1") PATTERN="^(feat|fix|docs|style|refactor|test|chore)((.+))?: .{1,72}$"
if ! echo "$COMMIT_MSG" | head -1 | grep -qE "$PATTERN"; then echo "Error: Commit message must follow Conventional Commits format" echo "Example: feat(auth): add OAuth2 login flow" exit 1 fi

```bash
#!/bin/sh
COMMIT_MSG=$(cat "$1") PATTERN="^(feat|fix|docs|style|refactor|test|chore)((.+))?: .{1,72}$"
if ! echo "$COMMIT_MSG" | head -1 | grep -qE "$PATTERN"; then echo "Error: Commit message must follow Conventional Commits format" echo "Example: feat(auth): add OAuth2 login flow" exit 1 fi

```bash
#!/bin/sh

.git/hooks/pre-push

.git/hooks/pre-push

Run tests before pushing

Run tests before pushing

npm test if [ $? -ne 0 ]; then echo "Tests failed. Push aborted." exit 1 fi
undefined
npm test if [ $? -ne 0 ]; then echo "Tests failed. Push aborted." exit 1 fi
undefined

Recovery Techniques

恢复技巧

bash
undefined
bash
undefined

Undo last commit but keep changes staged

Undo last commit but keep changes staged

git reset --soft HEAD~1
git reset --soft HEAD~1

Recover a deleted branch using reflog

Recover a deleted branch using reflog

git reflog git checkout -b recovered-branch HEAD@{3}
git reflog git checkout -b recovered-branch HEAD@{3}

Recover a file from a specific commit

Recover a file from a specific commit

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

Find lost commits (dangling after reset or rebase)

Find lost commits (dangling after reset or rebase)

git fsck --lost-found git show <dangling-commit-sha>
git fsck --lost-found git show <dangling-commit-sha>

Undo a rebase

Undo a rebase

git reflog git reset --hard HEAD@{5} # point before rebase started
undefined
git reflog git reset --hard HEAD@{5} # point before rebase started
undefined

Useful Aliases

实用别名

bash
undefined
bash
undefined

~/.gitconfig

~/.gitconfig

[alias] lg = log --graph --oneline --decorate --all st = status -sb co = checkout unstage = reset HEAD -- last = log -1 HEAD --stat branches = branch -a --sort=-committerdate stash-all = stash push --include-untracked conflicts = diff --name-only --diff-filter=U
undefined
[alias] lg = log --graph --oneline --decorate --all st = status -sb co = checkout unstage = reset HEAD -- last = log -1 HEAD --stat branches = branch -a --sort=-committerdate stash-all = stash push --include-untracked conflicts = diff --name-only --diff-filter=U
undefined

Anti-Patterns

反模式

  • Force-pushing to shared branches without
    --force-with-lease
  • Rebasing commits that have already been pushed and shared
  • Committing large binary files without Git LFS
  • Using
    git add .
    without reviewing
    git diff --staged
  • Not using
    .gitignore
    for build artifacts, dependencies, and secrets
  • Keeping long-lived feature branches instead of merging frequently
  • 未添加
    --force-with-lease
    参数就向共享分支执行强制推送
  • 对已经推送并共享的提交执行变基操作
  • 不使用 Git LFS 就提交大型二进制文件
  • 未先检查
    git diff --staged
    就直接使用
    git add .
  • 未配置
    .gitignore
    忽略构建产物、依赖和敏感信息
  • 维护生命周期过长的功能分支,而非频繁合并

Checklist

检查清单

  • Worktrees used for parallel branch work instead of stashing
  • git bisect run
    automates bug-finding with a test command
  • Interactive rebase cleans up commits before merging to main
  • Pre-commit hooks run linting on staged files
  • Commit message format enforced via commit-msg hook
  • --force-with-lease
    used instead of
    --force
    when force-pushing
  • Reflog consulted before any destructive operation
  • .gitignore
    covers build outputs, dependencies, and environment files
  • 使用 Worktrees 处理并行分支工作,而非使用暂存
  • 使用
    git bisect run
    搭配测试命令自动化查找引入 Bug 的提交
  • 合并到主分支前使用交互式变基清理提交记录
  • 预提交钩子会对暂存文件执行代码检查
  • 通过 commit-msg 钩子强制规范提交信息格式
  • 强制推送时使用
    --force-with-lease
    替代
    --force
  • 执行任何破坏性操作前先查看 reflog 记录
  • .gitignore
    覆盖了构建输出、依赖和环境变量文件