简介
Git 是一个分布式版本控制系统,由 Linus Torvalds 于 2005 年创建,最初用于管理 Linux 内核开发。它帮助开发者跟踪代码变更、协作和管理项目。
核心概念
- 仓库(Repository)
存储项目所有文件和历史记录的地方,分为本地仓库和远程仓库。 - 提交(Commit)
每次代码变更是通过提交记录的,包含变更内容、作者、时间等信息。 - 分支(Branch)
分支用于并行开发,默认分支通常是main或master,开发者可以创建新分支进行独立开发。 - 合并(Merge)
将一个分支的变更整合到另一个分支,通常在功能完成后合并回主分支。 - 克隆(Clone)
从远程仓库复制整个项目到本地。 - 拉取(Pull)
从远程仓库获取最新变更并合并到本地分支。 - 推送(Push)
将本地提交上传到远程仓库。 - 冲突(Conflict)
当多个开发者修改同一文件时,Git 无法自动合并,需手动解决冲突。
常用命令
git init:初始化新仓库。git clone <url>:克隆远程仓库。git add <file>:将文件添加到暂存区。git commit -m "message":提交变更并添加描述。git status:查看当前状态。git pull:拉取远程变更。git push:推送本地提交。git branch:列出分支。git checkout <branch>:切换分支。git merge <branch>:合并分支。git log:查看提交历史。
工作流程
- 克隆仓库:
git clone <url>。 - 创建分支:
git branch feature-branch。 - 切换分支:
git checkout feature-branch。 - 修改代码:编辑文件。
- 提交变更:
git add .和git commit -m "message"。 - 推送分支:
git push origin feature-branch。 - 创建合并请求:在远程仓库创建合并请求(如 GitHub 的 Pull Request)。
- 解决冲突:如有冲突,手动解决后提交。
- 合并分支:通过合并请求将分支合并到主分支。
优势
- 分布式:每个开发者都有完整的仓库副本。
- 高效:本地操作快速,减少对远程服务器的依赖。
- 灵活:支持多种工作流程,适合不同团队需求。
- 强大:丰富的命令和功能,满足复杂开发需求。
Git 是现代软件开发中不可或缺的工具,掌握它能显著提升开发效率和协作能力。
规范
Git 提交规范是为了让提交信息清晰、一致,便于团队协作和项目维护。常见的规范包括 约定式提交(Conventional Commits)和 Angular 提交规范。以下是常见的提交规范建议:
1. 提交信息格式
提交信息通常分为 标题 和 正文 两部分,格式如下:
<类型>(<范围>): <主题>
<空行>
<正文>
<空行>
<脚注>
- 标题:简明扼要,描述本次提交的目的。
- 正文(可选):详细说明提交的内容和原因。
- 脚注(可选):用于关联 Issue 或 Breaking Changes。
2. 提交类型
提交类型用于说明提交的目的,常见的类型包括:
| 类型 | 说明 |
|---|---|
feat | 新增功能 |
fix | 修复 bug |
docs | 文档更新(如 README、注释等) |
style | 代码样式调整(如空格、格式化等,不改变逻辑) |
refactor | 代码重构(既不修复 bug 也不新增功能) |
perf | 性能优化 |
test | 测试相关(如新增测试用例) |
chore | 构建过程或辅助工具的变动(如依赖更新、配置文件修改等) |
ci | CI 配置或脚本的变动(如 GitHub Actions、Travis CI 等) |
revert | 回滚之前的提交 |
build | 构建相关的变动(如打包工具、依赖库等) |
3. 范围(可选)
范围用于说明提交影响的部分,通常是模块、组件或文件。例如:
feat(user): 新增用户登录功能fix(api): 修复接口返回错误
4. 主题
主题是对提交内容的简短描述,需遵循以下规则:
- 使用现在时(如“新增”而不是“新增了”)。
- 首字母小写。
- 不加句号。
5. 正文(可选)
正文是对提交的详细说明,可以包括:
- 提交的背景或原因。
- 解决的问题。
- 对代码的具体改动。
6. 脚注(可选)
脚注用于关联 Issue 或说明 Breaking Changes,例如:
- 关联 Issue:
Closes #123或Fixes #456。 - Breaking Changes:以
BREAKING CHANGE:开头,说明不兼容的变动。
7. 示例
示例 1:简单提交
feat: 新增用户注册功能
示例 2:带范围和正文的提交
fix(api): 修复用户登录接口返回错误
修复了用户登录接口在密码错误时返回 500 错误的问题,现在会正确返回 401 状态码。
示例 3:带脚注的提交
feat(user): 新增用户注销功能
Closes #123
示例 4:Breaking Changes
refactor(auth): 重构认证模块
BREAKING CHANGE: 删除了旧的认证接口,请使用新的 `/v2/auth` 接口。
8. 工具支持
- Commitizen:交互式提交工具,帮助生成规范的提交信息。
- Husky + Commitlint:在提交时自动检查提交信息是否符合规范。
- Conventional Changelog:根据提交规范自动生成更新日志。
9. 优点
- 清晰易懂:通过类型和范围快速了解提交内容。
- 自动化:便于生成更新日志和版本号。
- 协作友好:统一格式,减少沟通成本。
遵循提交规范可以显著提升代码库的可维护性和团队协作效率。
合并与变基
git merge 和 git rebase 是 Git 中用于整合分支变更的两种主要方式。它们的目标相同,但实现方式和结果不同。以下是它们的详细对比和使用场景:
1. 合并(Merge)
概念
git merge 将两个分支的历史记录合并,并生成一个新的 合并提交(Merge Commit)。合并会保留两个分支的完整历史记录。
使用场景
- 需要保留完整的分支历史记录。
- 合并公共分支(如
main或master)时。 - 适合团队协作,避免重写历史记录。
命令
git checkout main # 切换到目标分支(如 main)
git merge feature-branch # 将 feature-branch 合并到 main
示例
假设有两个分支:
main分支:A -> B -> Cfeature-branch分支:A -> B -> D -> E
执行 git merge 后,历史记录如下:
A -> B -> C -> F
\ /
D -> E
F 是一个新的合并提交。
2. 变基(Rebase)
概念
git rebase 将一个分支的提交“重新应用”到另一个分支上,从而形成一条线性的历史记录。变基会重写提交历史。
使用场景
- 希望保持干净、线性的提交历史。
- 在本地分支上整理提交记录。
- 避免不必要的合并提交。
命令
git checkout feature-branch # 切换到需要变基的分支
git rebase main # 将 feature-branch 的提交变基到 main 上
2. 常见的交互式 Rebase 操作
在交互式 rebase 的编辑界面中,每个提交前面都有一个命令(如 pick、squash、edit 等)。你可以修改这些命令来整理提交历史。
- pick: 保留该提交(默认操作)。
- reword: 保留该提交,但修改提交信息。
- edit: 保留该提交,但暂停 rebase 以便你修改提交内容。
- squash: 将该提交与前一个提交合并,并合并提交信息。
- fixup: 将该提交与前一个提交合并,但丢弃该提交的提交信息。
- drop: 删除该提交。
示例
假设有两个分支:
main分支:A -> B -> Cfeature-branch分支:A -> B -> D -> E
执行 git rebase 后,历史记录如下:
A -> B -> C -> D' -> E'
D' 和 E' 是重新应用的提交,哈希值会改变。
3. 合并 vs 变基
| 特性 | 合并(Merge) | 变基(Rebase) |
|---|---|---|
| 历史记录 | 保留完整历史,生成合并提交 | 线性历史,重写提交记录 |
| 提交哈希 | 不改变原有提交的哈希值 | 重新生成提交哈希值 |
| 适用场景 | 公共分支合并,团队协作 | 本地分支整理,保持干净历史 |
| 冲突处理 | 在合并提交时解决冲突 | 在每次提交重新应用时解决冲突 |
| 风险 | 历史记录可能复杂 | 重写历史可能导致问题(需谨慎使用) |
4. 如何选择?
使用合并(Merge)的情况
- 合并公共分支(如
main或master)。 - 需要保留完整的历史记录。
- 团队协作时,避免重写历史。
使用变基(Rebase)的情况
- 整理本地分支的提交记录。
- 希望保持线性的历史记录。
- 在推送分支之前清理提交。
5. 注意事项
变基的风险
- 重写历史:变基会改变提交的哈希值,如果已经推送到远程仓库,可能会导致冲突或混乱。
- 冲突处理:变基时需要逐个提交解决冲突,可能比合并更复杂。
变基的最佳实践
- 仅在本地分支上使用变基。
- 如果分支已经推送到远程仓库,避免使用变基。
- 使用
git pull --rebase代替git pull,避免不必要的合并提交。
6. 常用命令
合并
git checkout main
git merge feature-branch
变基
git checkout feature-branch
git rebase main
交互式变基(整理提交)
git rebase -i HEAD~3 # 整理最近 3 个提交
强制推送(变基后)
git push --force-with-lease # 安全地强制推送
7. 总结
- 合并:适合团队协作和公共分支,保留完整历史。
- 变基:适合本地分支整理,保持线性历史。
根据实际需求选择合适的工具,避免在公共分支上使用变基,以免影响团队协作。
pick操作
在 Git 中,pick 是 交互式变基(Interactive Rebase) 中的一个操作,用于选择要保留的提交。交互式变基允许你重新排序、编辑、合并或删除提交,而 pick 是其中最常用的操作。
1. 什么是交互式变基?
交互式变基是通过 git rebase -i 命令启动的,它可以让你对一系列提交进行操作。常见的操作包括:
pick:保留提交。reword:保留提交但修改提交信息。edit:保留提交并暂停以修改内容。squash:将提交合并到前一个提交中。fixup:类似squash,但丢弃提交信息。drop:删除提交。
2. pick 的作用
pick 是默认操作,表示保留该提交不变。在交互式变基中,你可以通过调整 pick 的顺序来重新排列提交。
3. 如何使用 pick
步骤 1:启动交互式变基
运行以下命令,对最近的 N 个提交进行交互式变基:
git rebase -i HEAD~N
例如,git rebase -i HEAD~3 会显示最近 3 个提交。
步骤 2:编辑提交列表
Git 会打开一个文本编辑器,显示类似以下内容:
pick abc123 Commit message 1
pick def456 Commit message 2
pick ghi789 Commit message 3
每行代表一个提交,格式为:
<操作> <提交哈希> <提交信息>
步骤 3:选择 pick 操作
默认情况下,所有提交都是 pick 操作。你可以:
- 保留
pick以保留提交。 - 调整
pick的顺序以重新排列提交。
例如:
pick def456 Commit message 2
pick abc123 Commit message 1
pick ghi789 Commit message 3
保存并退出编辑器后,Git 会按照新的顺序重新应用提交。
步骤 4:完成变基
如果没有冲突,Git 会自动完成变基。如果有冲突,Git 会提示你解决冲突,然后运行以下命令继续变基:
git rebase --continue
4. pick 的常见用法
重新排列提交
通过调整 pick 的顺序,可以重新排列提交。例如:
pick abc123 Commit message 1
pick ghi789 Commit message 3
pick def456 Commit message 2
删除提交
将 pick 改为 drop 可以删除提交。例如:
pick abc123 Commit message 1
drop def456 Commit message 2
pick ghi789 Commit message 3
保留提交
如果不需要修改提交,直接保留 pick 即可。
5. 注意事项
- 重写历史:交互式变基会重写提交历史,如果提交已经推送到远程仓库,需要使用
git push --force-with-lease强制推送。 - 冲突解决:在变基过程中可能会遇到冲突,需要手动解决并运行
git rebase --continue。 - 备份分支:在变基之前,建议创建一个备份分支,以防操作失误:
git branch backup-branch
6. 示例
示例 1:重新排列提交
假设有以下提交历史:
A -> B -> C
运行 git rebase -i HEAD~3 后,编辑为:
pick B
pick A
pick C
变基后的历史为:
B -> A -> C
示例 2:删除提交
运行 git rebase -i HEAD~3 后,编辑为:
pick A
drop B
pick C
变基后的历史为:
A -> C
7. 总结
pick 是交互式变基中的核心操作,用于选择保留提交。通过交互式变基,你可以重新排列、编辑或删除提交,从而整理提交历史。注意,变基会重写历史,因此在公共分支上使用时需谨慎。
工作流
Git 工作流(Git Workflow)是团队协作中使用 Git 管理代码的一套规范和流程。不同的团队和项目可能采用不同的工作流,以下是几种常见的 Git 工作流:
1. 集中式工作流(Centralized Workflow)
类似于 SVN 的工作方式,所有开发者共享一个中央仓库。
流程
- 开发者从中央仓库克隆代码。
- 在本地分支上开发。
- 将本地更改推送到中央仓库。
优点
- 简单易用,适合小型团队。
- 无需复杂的分支管理。
缺点
- 容易产生冲突。
- 缺乏并行开发的支持。
2. 功能分支工作流(Feature Branch Workflow)
每个功能或任务都在独立的分支上开发,完成后合并到主分支。
流程
- 从主分支(如
main)创建功能分支。
git checkout -b feature-branch
- 在功能分支上开发并提交代码。
- 完成开发后,将功能分支合并到主分支。
git checkout main
git merge feature-branch
优点
- 支持并行开发。
- 隔离功能代码,减少冲突。
缺点
- 需要管理多个分支。
- 合并时可能产生冲突。
3. Gitflow 工作流
由 Vincent Driessen 提出,适合有固定发布周期的项目。
分支结构
- 主分支(main/master) :稳定版本。
- 开发分支(develop) :集成开发代码。
- 功能分支(feature/ *)**:开发新功能。
- 发布分支(release/ *)**:准备发布。
- 热修复分支(hotfix/ *)**:修复生产环境问题。
流程
- 从
develop分支创建功能分支。
git checkout -b feature/new-feature develop
- 完成功能后合并到
develop分支。
git checkout develop
git merge feature/new-feature
- 创建发布分支准备发布。
git checkout -b release/1.0 develop
- 发布完成后合并到
main和develop分支。
git checkout main
git merge release/1.0
git checkout develop
git merge release/1.0
- 修复生产环境问题时,从
main分支创建热修复分支。
git checkout -b hotfix/1.0.1 main
优点
- 适合有固定发布周期的项目。
- 严格的分支管理,减少冲突。
缺点
- 流程复杂,适合中大型团队。
- 需要维护多个长期分支。
4. Forking 工作流
常用于开源项目,开发者 fork 中央仓库并在自己的仓库中开发。
流程
- 开发者 fork 中央仓库到自己的账户。
- 克隆自己的仓库到本地。
git clone https://github.com/your-username/repo.git
- 在本地开发并推送到自己的仓库。
- 创建 Pull Request(PR)请求合并到中央仓库。
优点
- 适合开源项目,保护中央仓库。
- 开发者独立开发,减少冲突。
缺点
- 需要手动同步中央仓库的更新。
- PR 审核流程可能较慢。
5. GitHub Flow
由 GitHub 提出,适合持续交付的项目。
流程
- 从
main分支创建功能分支。
git checkout -b feature-branch
- 在功能分支上开发并提交代码。
- 创建 Pull Request(PR)请求合并到
main分支。 - 代码审核通过后合并到
main分支。
优点
- 简单高效,适合持续交付。
- 强调代码审核和自动化测试。
缺点
- 需要完善的 CI/CD 工具支持。
- 不适合有固定发布周期的项目。
6. GitLab Flow
由 GitLab 提出,结合了 Gitflow 和 GitHub Flow 的优点。
分支结构
- 主分支(main) :稳定版本。
- 环境分支(production/staging) :对应不同环境。
- 功能分支(feature/ *)**:开发新功能。
流程
- 从
main分支创建功能分支。
git checkout -b feature/new-feature main
- 完成功能后合并到
main分支。 - 将
main分支合并到环境分支(如staging或production)。
优点
- 灵活,适合不同开发模式。
- 强调环境分支,便于部署。
缺点
- 需要维护多个环境分支。
- 流程稍复杂。
7. Trunk-Based Development(基于主干的开发)
所有开发者都在主分支(trunk)上开发,适合持续集成和持续交付。
流程
- 开发者直接在主分支上开发。
- 通过特性开关(Feature Toggles)控制未完成功能的发布。
- 频繁提交和集成。
优点
- 简单高效,适合持续交付。
- 减少分支管理成本。
缺点
- 需要完善的 CI/CD 工具支持。
- 特性开关可能增加代码复杂度。
| 工作流 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 集中式工作流 | 小型团队 | 简单易用 | 容易冲突,不支持并行开发 |
| 功能分支工作流 | 中小型团队 | 支持并行开发 | 需要管理多个分支 |
| Gitflow 工作流 | 中大型团队,固定发布周期 | 严格分支管理,减少冲突 | 流程复杂 |
| Forking 工作流 | 开源项目 | 保护中央仓库,独立开发 | 需要手动同步中央仓库 |
| GitHub Flow | 持续交付项目 | 简单高效,强调代码审核 | 需要 CI/CD 工具支持 |
| GitLab Flow | 灵活开发模式 | 灵活,强调环境分支 | 需要维护多个环境分支 |
| Trunk-Based Development | 持续集成和持续交付 | 简单高效,减少分支管理成本 | 需要完善的 CI/CD 工具支持 |
根据团队规模、项目需求和开发模式选择合适的工作流,可以显著提升开发效率和代码质量。