主题
分支操作
git 分支分为 “本地分支” 和 “远程分支” 两种。
同步
git remote update:更新所有远程仓库的引用信息,不会修改本地分支内容。git fetch:从指定的远程仓库获取更新的引用信息,不会修改本地分支内容。git pull:从指定的远程仓库获取更新并合并到当前分支,直接影响本地分支内容。
查看分支
bash
# 查看本地分支
git branch
git branch -v
# 查看远程分支
git branch -r
# 查看所有分支
git branch -a创建新分支
bash
# 创建新分支
git branch <new-branch-name>
# 创建新分支(基于特定版本)
git branch <new-branch-name> <commit-hash>切换分支
bash
# 切换分支
git switch <other-branch>
# 创建分支并切换到新分支
git switch -c <new-branch-name>
# 创建分支(基于特定版本)并切换到新分支
git switch -c <new-branch-name> <commit-hash>bash
# 切换分支
git checkout <other-branch>
# 创建分支并切换到新分支
git checkout -b <new-branch-name>
# 创建分支(基于特定版本)并切换到新分支
git checkout -b <new-branch-name> <commit-hash>重命名分支
bash
# 重命名当前 HEAD 分支名
git branch -m <new-name>
# 重命名任何本地分支名
git branch -m <old-name> <new-name>
# “重命名”远程分支名
# 注意:本地无法给远程分支进行重命名,不过,我们可以先删除掉远程分支,再将本地分支推送到远程仓库,以达到“重命名”的效果。
git push origin --delete <old-name>
git push origin <new-name>发布分支
注意:本地无法直接给远程仓库创建分支,不过,我们可以将本地的分支上传至远程仓库。
bash
# “上传”本地分支
git push origin <local-branch>
# “上传”本地分支并建立关联
git push -u origin <local-branch>关联分支
bash
# 查看当前关联
git branch -vv
# 手动绑定
# -u 是 "set-upstream" 的缩写,属于一次性配置。
git branch -u origin/ccc
# 解除绑定
git branch --unset-upstream删除分支
bash
# 删除远程分支
git push origin --delete <branch-name>
# 删除本地分支
git branch -d <branch-name>
# 删除远程仓库中已删除的分支
git fetch --prune
git fetch -p合并分支
merge
简单、安全,会生成一个合并提交(保持完整的交织历史):
正确流程:
确保本地
main是最新的bashgit switch main git pull origin main回到特性分支,先在本地模拟合并(可选,但推荐)
bashgit switch <your-branch> git merge main如果没有冲突:皆大欢喜,直接看下一步。
如果有冲突:解决后:
bashgit add . git commit -m "chore: 解决与 main 分支的冲突"
正式合并到
main此时,你的特性分支已经包含了
main的最新代码,且冲突已在本地分支解完。回到main执行合并会非常丝滑:bashgit switch main git merge <your-branch>(注:如果执行了第 2 步,此时合并会自动触发 Fast-forward(快进合并),不会产生双向交叉的混乱线)
推送到远程,收工
bashgit push origin main
rebase(变基)
使提交历史保持一条线,非常整洁。
注意:永远不要在公共分支(如 main)上执行以个人分支为目标的 rebase!
正确流程:
先在自己的分支上,把
main的新改动垫在底部:bashgit switch <your-branch> git rebase main如果有冲突,解决后继续;放弃则回到变基前:
bashgit add . git rebase --continue git rebase --abort # 回到变基前;命令里指定了分支时,回到该分支推送特征分支(因为改变了历史,需强制推送):
bashgit push origin <your-branch> --force-with-lease最后回到
main进行快进合并(此时是一条直线):bashgit switch main git merge <your-branch>
--onto <newbase> <upstream> [<branch>] 把 <branch>(默认当前分支)上有、<upstream> 上没有的提交,接到 <newbase>。不写 --onto 时,新基点就是 <upstream>。
bash
# feature 基于 topic,只重放相对 topic 多出来的提交,改接到 main
git rebase --onto main topic feature
# 丢掉提交 C,将其后的提交接到 C 的父提交
git rebase --onto C^ C特殊场景
cherry-pick
把已有提交的改动应用到当前分支,每个提交生成一个新提交。工作区必须干净。
bash
git switch <your-branch>
git log # 复制需要的 commit_id
git switch main
git cherry-pick <commit1> <commit2>多个独立提交按参数顺序应用,不遍历历史。范围走一次版本遍历,从旧到新应用。
bash
# 不含 A,含 B。等价于 ^A B
git cherry-pick A..B
# 含 A。A^ 是 A 的第一个父提交,范围左端本身不包含
git cherry-pick A^..B
# 目标上有、当前 HEAD 没有的提交。两条等价
git cherry-pick ..<branch>
git cherry-pick ^HEAD <branch>A...B 是对称差:两边各自独有的提交,公共祖先上的不算。A 是 B 的祖先时与 A..B 相同;两边已分叉时会带上另一侧独有提交。A^...B 同理,只在线性历史上等于 A^..B。
合并提交必须指定主线父提交,否则无法判断相对哪一侧计算差异:
bash
git cherry-pick -m 1 <merge-commit>bash
# 写入工作区和暂存区,不提交
git cherry-pick -n <commit>
# 说明末尾追加来源提交,仅无冲突时写入
git cherry-pick -x <commit>
# 提交前改说明
git cherry-pick -e <commit>
# HEAD 正好是被摘提交的父提交时快进
git cherry-pick --ff <commit>原本为空的提交默认失败,--allow-empty 才保留。因目标分支已有相同改动而变空的提交由 --empty=drop|keep|stop 处理,默认 stop。
冲突后:
bash
git cherry-pick --continue
git cherry-pick --skip
git cherry-pick --abort # 回到操作前
git cherry-pick --quit # 只清除进行中的状态压缩提交记录 (squash)
将源分支的所有提交“压缩”成一个单独的合并提交,保持主干干净。
bash
git switch main
git merge --squash <your-branch>
git commit -m "feat: 合并 <your-branch> 的所有更改"同步上游开源项目 (PR 场景)
bash
git fetch upstream
git switch main
git rebase upstream/main
git push origin main --force-with-lease # 安全更新自己的远程 main 仓库