$npx -y skills add chaterm/terminal-skills --skill git-advancedGit 高级操作
| 1 | # Git 高级操作 |
| 2 | |
| 3 | ## 概述 |
| 4 | 分支策略、rebase、cherry-pick、hooks 等高级 Git 技能。 |
| 5 | |
| 6 | ## 分支管理 |
| 7 | |
| 8 | ### 分支操作 |
| 9 | ```bash |
| 10 | # 创建分支 |
| 11 | git branch feature/new-feature |
| 12 | git checkout -b feature/new-feature |
| 13 | git switch -c feature/new-feature |
| 14 | |
| 15 | # 切换分支 |
| 16 | git checkout main |
| 17 | git switch main |
| 18 | |
| 19 | # 删除分支 |
| 20 | git branch -d feature/merged |
| 21 | git branch -D feature/unmerged # 强制删除 |
| 22 | |
| 23 | # 删除远程分支 |
| 24 | git push origin --delete feature/old |
| 25 | |
| 26 | # 重命名分支 |
| 27 | git branch -m old-name new-name |
| 28 | |
| 29 | # 查看分支 |
| 30 | git branch -a # 所有分支 |
| 31 | git branch -v # 带最后提交 |
| 32 | git branch --merged # 已合并分支 |
| 33 | git branch --no-merged # 未合并分支 |
| 34 | ``` |
| 35 | |
| 36 | ### 分支追踪 |
| 37 | ```bash |
| 38 | # 设置上游分支 |
| 39 | git branch --set-upstream-to=origin/main main |
| 40 | git push -u origin feature/new |
| 41 | |
| 42 | # 查看追踪关系 |
| 43 | git branch -vv |
| 44 | ``` |
| 45 | |
| 46 | ## Rebase 操作 |
| 47 | |
| 48 | ### 基础 rebase |
| 49 | ```bash |
| 50 | # 变基到 main |
| 51 | git checkout feature |
| 52 | git rebase main |
| 53 | |
| 54 | # 交互式 rebase |
| 55 | git rebase -i HEAD~5 |
| 56 | git rebase -i main |
| 57 | |
| 58 | # 交互式命令 |
| 59 | # pick - 保留提交 |
| 60 | # reword - 修改提交信息 |
| 61 | # edit - 修改提交内容 |
| 62 | # squash - 合并到上一个提交 |
| 63 | # fixup - 合并但丢弃提交信息 |
| 64 | # drop - 删除提交 |
| 65 | |
| 66 | # 继续/中止 rebase |
| 67 | git rebase --continue |
| 68 | git rebase --abort |
| 69 | git rebase --skip |
| 70 | ``` |
| 71 | |
| 72 | ### 合并提交 |
| 73 | ```bash |
| 74 | # 合并最近 3 个提交 |
| 75 | git rebase -i HEAD~3 |
| 76 | # 将后两个 pick 改为 squash 或 fixup |
| 77 | |
| 78 | # 修改历史提交信息 |
| 79 | git rebase -i HEAD~3 |
| 80 | # 将 pick 改为 reword |
| 81 | ``` |
| 82 | |
| 83 | ## Cherry-pick |
| 84 | |
| 85 | ```bash |
| 86 | # 选择单个提交 |
| 87 | git cherry-pick commit-hash |
| 88 | |
| 89 | # 选择多个提交 |
| 90 | git cherry-pick commit1 commit2 commit3 |
| 91 | |
| 92 | # 选择范围(不包含起始) |
| 93 | git cherry-pick start-commit..end-commit |
| 94 | |
| 95 | # 不自动提交 |
| 96 | git cherry-pick -n commit-hash |
| 97 | |
| 98 | # 解决冲突后继续 |
| 99 | git cherry-pick --continue |
| 100 | git cherry-pick --abort |
| 101 | ``` |
| 102 | |
| 103 | ## Stash 暂存 |
| 104 | |
| 105 | ```bash |
| 106 | # 暂存修改 |
| 107 | git stash |
| 108 | git stash push -m "work in progress" |
| 109 | |
| 110 | # 暂存包括未跟踪文件 |
| 111 | git stash -u |
| 112 | git stash --include-untracked |
| 113 | |
| 114 | # 查看暂存列表 |
| 115 | git stash list |
| 116 | |
| 117 | # 恢复暂存 |
| 118 | git stash pop # 恢复并删除 |
| 119 | git stash apply # 恢复但保留 |
| 120 | git stash apply stash@{2} # 指定暂存 |
| 121 | |
| 122 | # 查看暂存内容 |
| 123 | git stash show -p stash@{0} |
| 124 | |
| 125 | # 删除暂存 |
| 126 | git stash drop stash@{0} |
| 127 | git stash clear # 清空所有 |
| 128 | ``` |
| 129 | |
| 130 | ## 撤销操作 |
| 131 | |
| 132 | ### 撤销工作区修改 |
| 133 | ```bash |
| 134 | # 撤销单个文件 |
| 135 | git checkout -- file.txt |
| 136 | git restore file.txt |
| 137 | |
| 138 | # 撤销所有修改 |
| 139 | git checkout -- . |
| 140 | git restore . |
| 141 | ``` |
| 142 | |
| 143 | ### 撤销暂存区 |
| 144 | ```bash |
| 145 | # 取消暂存 |
| 146 | git reset HEAD file.txt |
| 147 | git restore --staged file.txt |
| 148 | |
| 149 | # 取消所有暂存 |
| 150 | git reset HEAD |
| 151 | ``` |
| 152 | |
| 153 | ### 撤销提交 |
| 154 | ```bash |
| 155 | # 撤销最后一次提交(保留修改) |
| 156 | git reset --soft HEAD~1 |
| 157 | |
| 158 | # 撤销最后一次提交(丢弃修改) |
| 159 | git reset --hard HEAD~1 |
| 160 | |
| 161 | # 创建撤销提交 |
| 162 | git revert commit-hash |
| 163 | git revert HEAD |
| 164 | |
| 165 | # 撤销多个提交 |
| 166 | git revert HEAD~3..HEAD |
| 167 | ``` |
| 168 | |
| 169 | ### 修改提交 |
| 170 | ```bash |
| 171 | # 修改最后一次提交 |
| 172 | git commit --amend |
| 173 | git commit --amend -m "new message" |
| 174 | git commit --amend --no-edit # 不修改信息 |
| 175 | |
| 176 | # 添加遗漏文件 |
| 177 | git add forgotten-file |
| 178 | git commit --amend --no-edit |
| 179 | ``` |
| 180 | |
| 181 | ## 远程操作 |
| 182 | |
| 183 | ```bash |
| 184 | # 查看远程 |
| 185 | git remote -v |
| 186 | |
| 187 | # 添加远程 |
| 188 | git remote add upstream https://github.com/original/repo.git |
| 189 | |
| 190 | # 获取远程更新 |
| 191 | git fetch origin |
| 192 | git fetch --all |
| 193 | |
| 194 | # 拉取并变基 |
| 195 | git pull --rebase origin main |
| 196 | |
| 197 | # 强制推送(谨慎使用) |
| 198 | git push --force-with-lease origin feature |
| 199 | ``` |
| 200 | |
| 201 | ## Git Hooks |
| 202 | |
| 203 | ### 常用 hooks |
| 204 | ```bash |
| 205 | # hooks 位置 |
| 206 | .git/hooks/ |
| 207 | |
| 208 | # 常用 hooks |
| 209 | pre-commit # 提交前 |
| 210 | prepare-commit-msg # 准备提交信息 |
| 211 | commit-msg # 提交信息验证 |
| 212 | post-commit # 提交后 |
| 213 | pre-push # 推送前 |
| 214 | ``` |
| 215 | |
| 216 | ### pre-commit 示例 |
| 217 | ```bash |
| 218 | #!/bin/bash |
| 219 | # .git/hooks/pre-commit |
| 220 | |
| 221 | # 运行 lint |
| 222 | npm run lint |
| 223 | if [ $? -ne 0 ]; then |
| 224 | echo "Lint failed. Commit aborted." |
| 225 | exit 1 |
| 226 | fi |
| 227 | |
| 228 | # 运行测试 |
| 229 | npm test |
| 230 | if [ $? -ne 0 ]; then |
| 231 | echo "Tests failed. Commit aborted." |
| 232 | exit 1 |
| 233 | fi |
| 234 | |
| 235 | exit 0 |
| 236 | ``` |
| 237 | |
| 238 | ### commit-msg 示例 |
| 239 | ```bash |
| 240 | #!/bin/bash |
| 241 | # .git/hooks/commit-msg |
| 242 | |
| 243 | commit_msg=$(cat "$1") |
| 244 | |
| 245 | # 检查提交信息格式 |
| 246 | if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}"; then |
| 247 | echo "Invalid commit message format." |
| 248 | echo "Format: type(scope): message" |
| 249 | exit 1 |
| 250 | fi |
| 251 | |
| 252 | exit 0 |
| 253 | ``` |
| 254 | |
| 255 | ## 常见场景 |
| 256 | |
| 257 | ### 场景 1:同步 fork 仓库 |
| 258 | ```bash |
| 259 | # 添加上游仓库 |
| 260 | git remote add upstream https://github.com/original/repo.git |
| 261 | |
| 262 | # 获取上游更新 |
| 263 | git fetch upstream |
| 264 | |
| 265 | # 合并到本地 |
| 266 | git checkout main |
| 267 | git merge upstream/main |
| 268 | |
| 269 | # 推送到 fork |
| 270 | git push origin main |
| 271 | ``` |
| 272 | |
| 273 | ### 场景 2:清理历史中的大文件 |
| 274 | ```bash |
| 275 | # 使用 git-filter-repo(推荐) |
| 276 | git filter-repo --path large-file.zip --invert-paths |
| 277 | |
| 278 | # 或使用 BFG |
| 279 | bfg --delete-files large-file.zip |
| 280 | git reflog expire --expire=now --all |
| 281 | git gc --prune=now --aggressive |
| 282 | ``` |
| 283 | |
| 284 | ### 场景 3:二分查找 bug |
| 285 | ```bash |
| 286 | # 开始二分 |
| 287 | git bisect start |
| 288 | |
| 289 | # 标记当前为坏 |
| 290 | git bisect bad |
| 291 | |
| 292 | # 标记已知好的提交 |
| 293 | git bisect good v1.0.0 |
| 294 | |
| 295 | # Git 会自动切换到中间提交 |
| 296 | # 测试后标记 |
| 297 | git bisect good # 或 git bisect bad |
| 298 | |
| 299 | # 找到后重置 |
| 300 | git bisect reset |
| 301 | ``` |
| 302 | |
| 303 | ### 场景 4:子模块管理 |
| 304 | ```bash |
| 305 | # 添加子模块 |
| 306 | git submodule add https://github.com/user/repo.git path/to/submodule |
| 307 | |
| 308 | # 初始化子模块 |
| 309 | git submodule init |
| 310 | git submodule update |
| 311 | |
| 312 | # 克隆时包含子模块 |
| 313 | git clone --recursive https://github.com/user/repo.git |
| 314 | |
| 315 | # 更新子模块 |
| 316 | git submodule update --remote |
| 317 | ``` |
| 318 | |
| 319 | ## 故障排查 |
| 320 | |
| 321 | | 问题 | 解决方法 | |
| 322 | |------|----------| |
| 323 | | 合并冲突 | 手动解决后 `git add` + `git commit` | |
| 324 | | rebase 冲突 | 解决后 `git rebase --continue` | |
| 325 | | 误删分支 | `git reflog` 找回 | |
| 326 | | 推送被拒绝 | `git pull --rebase` 后重试 | |
| 327 | |
| 328 | ```bash |
| 329 | # 查看操作历史 |
| 330 | git reflog |
| 331 | |
| 332 | # 恢复误删的提交 |
| 333 | git checkout -b recovery commit-hash |
| 334 | ``` |