Skip to content

分支操作 ​

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 ​

简单、安全,会生成一个合并提交(保持完整的交织历史):

正确流程:

  1. 确保本地 main 是最新的

    bash
    git switch main
    git pull origin main
  2. 回到特性分支,先在本地模拟合并(可选,但推荐)

    bash
    git switch <your-branch>
    git merge main
    • 如果没有冲突:皆大欢喜,直接看下一步。

    • 如果有冲突:解决后:

      bash
      git add .
      git commit -m "chore: 解决与 main 分支的冲突"
  3. 正式合并到 main

    此时,你的特性分支已经包含了 main 的最新代码,且冲突已在本地分支解完。回到 main 执行合并会非常丝滑:

    bash
    git switch main
    git merge <your-branch>

    (注:如果执行了第 2 步,此时合并会自动触发 Fast-forward(快进合并),不会产生双向交叉的混乱线)

  4. 推送到远程,收工

    bash
    git push origin main

rebase(变基) ​

使提交历史保持一条线,非常整洁。

注意:永远不要在公共分支(如 main)上执行以个人分支为目标的 rebase!

正确流程:

  1. 先在自己的分支上,把 main 的新改动垫在底部:

    bash
    git switch <your-branch>
    git rebase main
  2. 如果有冲突,解决后继续;放弃则回到变基前:

    bash
    git add .
    git rebase --continue
    git rebase --abort # 回到变基前;命令里指定了分支时,回到该分支
  3. 推送特征分支(因为改变了历史,需强制推送):

    bash
    git push origin <your-branch> --force-with-lease
  4. 最后回到 main 进行快进合并(此时是一条直线):

    bash
    git 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 仓库

基于 MIT 许可发布