2026 年维护说明:本文末尾逐字保留了 2019 年的原始导出正文。旧文采用直接操作
master的流程,并含有原文笔误;它是历史档案,不是当前操作指南。下面的维护版假设团队使用支持拉取请求(pull request)或合并请求(merge request)的 Git 托管平台。请把main换成仓库实际的默认分支,并遵守仓库明文规定的团队策略。
Table of Contents
小团队先约定四件事
选择命令之前,团队先同意四条规则:
- 保护默认分支和发布分支,日常开发不直接向它们推送。
- 每项修改都放在短期工作分支上,通过评审集成。
- 请求评审前运行仓库规定的测试,并检查准确的差异。
- 不重写可能已被其他人作为工作基础的分支。
Git 本身不会强制代码评审,托管平台可以。例如,GitHub 的分支保护可以要求拉取请求评审、状态检查通过和对话已解决,也可以阻止强制推送。这些是仓库设置,不是 Git 在任何仓库里的通用行为。
1. 先检查,再从远程默认分支开始
先确认当前位置和是否还有未完成的修改:
git status --short --branch
git branch --show-current
git remote -v
用 git remote show origin 查看远程公布的默认分支,或者在仓库网页确认。下文以 main 为例。
获取远程更新,但不改变当前工作分支或文件:
git fetch origin --prune
git log --oneline --decorate --graph -20 --all
然后从最新的远程默认分支创建目标明确的工作分支:
git switch --create feature/login-timeout origin/main
git fetch 更新远程跟踪引用。相比之下,git pull 会先获取,再把结果集成到当前分支;一次没有参数的 git pull 会按配置执行合并或变基。先获取、再检查能让这个边界清晰可见。
2. 形成便于评审的修改
让一个分支只处理一个问题。提交前分别检查工作区差异和暂存区差异:
git status --short
git diff
git add --patch
git diff --cached
git commit -m "Handle login timeout explicitly"
如果同一文件里既有相关修改又有无关修改,git add --patch 很有用。还要运行项目规定的格式化、测试和安全检查;这些命令因仓库而异,不能由 Git 推断出来。
检查相对于基础分支,拉取请求究竟会包含什么:
git fetch origin
git diff --stat origin/main...HEAD
git diff origin/main...HEAD
git log --oneline origin/main..HEAD
三点差异以两个分支头的合并基础为起点,通常对应拉取请求界面所展示的修改。
3. 发布工作分支并请求评审
推送工作分支,而不是默认分支:
git push --set-upstream origin feature/login-timeout
创建拉取请求或合并请求时,写明:
- 问题与范围;
- 做过的测试及结果;
- 运行或迁移风险;
- 能帮助验证行为的截图或日志;
- 如果存在,对应的问题单链接。
评审者应检查当前差异,而不能只看描述。处理修改请求、重新运行相关检查,并让仓库配置的合并方式和权限决定最后如何集成。
4. 选定一种集成策略
合并、变基和压缩合并解决的是不同问题。团队应在仓库层面确定策略,不要临时随意切换。
| 方法 | 作用 | 合适的边界 | 主要注意事项 |
|---|---|---|---|
| 合并(merge) | 连接两段历史,可能生成合并提交 | 共享分支,或有意保留分支拓扑的仓库 | 机械使用会产生嘈杂的合并提交 |
| 变基(rebase) | 把提交重放到新基础上,生成新的提交 ID | 团队允许时,在别人尚未依赖的个人工作分支上 | 重写共享分支会使其他人的工作失去原来的基础 |
| 压缩合并(squash merge) | 把一个拉取请求作为默认分支上的一个提交集成 | 中间提交没有长期价值的小型修改 | 目标分支上不再保留工作分支的逐个提交边界 |
要把最新 main 纳入工作分支,同时不重写工作分支,使用合并:
git fetch origin
git switch feature/login-timeout
git merge origin/main
只有在团队允许,并且这是你自己的未共享工作分支时,才把它重放到最新 main:
git fetch origin
git switch feature/login-timeout
git rebase origin/main
git push --force-with-lease origin feature/login-timeout
--force-with-lease 会检查预期的远程状态,比盲目的 --force 安全,但它仍然会重写历史。使用前要协调;绝不能对受保护的默认分支使用;如果其他人可能正在使用这个工作分支,也应避免使用。
5. 有意识地解决冲突
合并或变基遇到冲突而停止时,不要盲目删除冲突标记。先找出所有尚未解决的路径:
git status
git diff --name-only --diff-filter=U
把每个文件编辑成预期的最终结果,删除 <<<<<<<、======= 和 >>>>>>> 标记,运行相关测试,再暂存解决结果。
对于合并:
git add path/to/resolved-file
git merge --continue
对于变基:
git add path/to/resolved-file
git rebase --continue
如果选择了错误的集成方式,或者无法确定解决结果,应回到操作之前的状态:
git merge --abort
在变基过程中:
git rebase --abort
这两个中止命令只在相应操作正在进行时适用。
6. 不重写共享历史的恢复方法
根据当前状态,选择破坏性最小的工具:
| 情况 | 先检查 | 较安全的恢复方法 |
|---|---|---|
| 路径被误暂存 | git diff --cached -- path/to/file | git restore --staged path/to/file |
| 确定要丢弃某路径尚未暂存的工作区编辑 | git diff -- path/to/file | git restore --worktree path/to/file |
| 错误提交已经共享 | git show <commit> | git revert <commit>,并评审新生成的反向提交 |
| 本地提交似乎丢失 | git reflog | git branch rescue-work <commit> |
在分离的 HEAD 上提交了工作 | git status 和 git log -1 | 切换离开前执行 git switch --create rescue-work |
git restore --worktree 会丢弃指定路径中未提交的工作区内容;如有需要,先复制到其他地方。git revert 会记录一个新提交,因此保留共享历史。reflog 是本地且有时限的记录,不是永久备份;找到所需提交后,应立即建立救援分支。
不要把 git reset --hard、普通的 git push --force 或删除分支当成常规排错命令。它们可能丢弃仍可访问的工作,或者重写协作者的历史。
7. 诊断常见协作故障
推送因非快进而被拒绝
有人或某个自动化进程推进了远程分支。不要用强制推送覆盖。先获取并检查:
git fetch origin
git status --short --branch
git log --oneline --left-right --graph HEAD...origin/feature/login-timeout
然后根据分支所有权和团队策略选择合并或变基。如果意外提交不是你的,先与其作者协调。
“本地分支与 origin 已分叉”
这表示双方各自拥有对方没有的提交;它并不能告诉你应选合并还是变基。检查提交图,确认提交和作者,再执行约定的集成策略。
分离的 HEAD
在分离状态下查看提交没有问题,但新提交没有分支名称。如果工作需要保留,在离开前把它连接到分支:
git switch --create rescue-detached-work
批准后拉取请求又发生变化
重新检查新差异并运行规定的检查。托管平台规则可以撤销过期批准,或要求最近一次推送由他人批准;不能假设较早的批准覆盖后来的提交。
一套紧凑、可重复的流程
git status --short --branch
git fetch origin --prune
git switch --create feature/login-timeout origin/main
git diff
git add --patch
git diff --cached
git commit -m "Handle login timeout explicitly"
git diff origin/main...HEAD
git push --set-upstream origin feature/login-timeout
创建分支后编辑并运行仓库特有的检查;推送后再打开拉取请求,随后进行评审、必需检查并遵守仓库的合并策略。这只是一条基线,不能代替仓库的 CONTRIBUTING 文件、发布流程、访问控制或事故处理流程。
---
2019 年原始导出(逐字存档)
档案边界:以下是
out/posts/2019-04-20-git-version-control-team-development-1865/index.md中 post 1865 的完整正文,导出内容日期为 2019 年 4 月 20 日。措辞、笔误、命令、分支名和历史说法均未修正。请勿把它当作维护版流程执行。
Pull before edit and push you code
git pull
View your current branch
git branch
Create and switch to created branch
git branch branchname
git checkout branchname
Merge, delete and push your code to server
git checkout master + git merge branchname
git branch -d branchname
git push origin branchname
---
