git及工作流总结

177 阅读15分钟

简介

Git 是一个分布式版本控制系统,由 Linus Torvalds 于 2005 年创建,最初用于管理 Linux 内核开发。它帮助开发者跟踪代码变更、协作和管理项目。

核心概念

  1. 仓库(Repository)
    存储项目所有文件和历史记录的地方,分为本地仓库和远程仓库。
  2. 提交(Commit)
    每次代码变更是通过提交记录的,包含变更内容、作者、时间等信息。
  3. 分支(Branch)
    分支用于并行开发,默认分支通常是 mainmaster,开发者可以创建新分支进行独立开发。
  4. 合并(Merge)
    将一个分支的变更整合到另一个分支,通常在功能完成后合并回主分支。
  5. 克隆(Clone)
    从远程仓库复制整个项目到本地。
  6. 拉取(Pull)
    从远程仓库获取最新变更并合并到本地分支。
  7. 推送(Push)
    将本地提交上传到远程仓库。
  8. 冲突(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:查看提交历史。

工作流程

  1. 克隆仓库git clone <url>
  2. 创建分支git branch feature-branch
  3. 切换分支git checkout feature-branch
  4. 修改代码:编辑文件。
  5. 提交变更git add .git commit -m "message"
  6. 推送分支git push origin feature-branch
  7. 创建合并请求:在远程仓库创建合并请求(如 GitHub 的 Pull Request)。
  8. 解决冲突:如有冲突,手动解决后提交。
  9. 合并分支:通过合并请求将分支合并到主分支。

优势

  • 分布式:每个开发者都有完整的仓库副本。
  • 高效:本地操作快速,减少对远程服务器的依赖。
  • 灵活:支持多种工作流程,适合不同团队需求。
  • 强大:丰富的命令和功能,满足复杂开发需求。

Git 是现代软件开发中不可或缺的工具,掌握它能显著提升开发效率和协作能力。

规范

Git 提交规范是为了让提交信息清晰、一致,便于团队协作和项目维护。常见的规范包括 约定式提交(Conventional Commits)和 Angular 提交规范。以下是常见的提交规范建议:


1. 提交信息格式

提交信息通常分为 标题正文 两部分,格式如下:

<类型>(<范围>): <主题>
<空行>
<正文>
<空行>
<脚注>
  • 标题:简明扼要,描述本次提交的目的。
  • 正文(可选):详细说明提交的内容和原因。
  • 脚注(可选):用于关联 Issue 或 Breaking Changes。

2. 提交类型

提交类型用于说明提交的目的,常见的类型包括:

类型说明
feat新增功能
fix修复 bug
docs文档更新(如 README、注释等)
style代码样式调整(如空格、格式化等,不改变逻辑)
refactor代码重构(既不修复 bug 也不新增功能)
perf性能优化
test测试相关(如新增测试用例)
chore构建过程或辅助工具的变动(如依赖更新、配置文件修改等)
ciCI 配置或脚本的变动(如 GitHub Actions、Travis CI 等)
revert回滚之前的提交
build构建相关的变动(如打包工具、依赖库等)

3. 范围(可选)

范围用于说明提交影响的部分,通常是模块、组件或文件。例如:

  • feat(user): 新增用户登录功能
  • fix(api): 修复接口返回错误

4. 主题

主题是对提交内容的简短描述,需遵循以下规则:

  • 使用现在时(如“新增”而不是“新增了”)。
  • 首字母小写。
  • 不加句号。

5. 正文(可选)

正文是对提交的详细说明,可以包括:

  • 提交的背景或原因。
  • 解决的问题。
  • 对代码的具体改动。

6. 脚注(可选)

脚注用于关联 Issue 或说明 Breaking Changes,例如:

  • 关联 Issue:Closes #123Fixes #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 mergegit rebase 是 Git 中用于整合分支变更的两种主要方式。它们的目标相同,但实现方式和结果不同。以下是它们的详细对比和使用场景:


1. 合并(Merge)

概念

git merge 将两个分支的历史记录合并,并生成一个新的 合并提交(Merge Commit)。合并会保留两个分支的完整历史记录。

使用场景

  • 需要保留完整的分支历史记录。
  • 合并公共分支(如 mainmaster)时。
  • 适合团队协作,避免重写历史记录。

命令

git checkout main         # 切换到目标分支(如 main)
git merge feature-branch  # 将 feature-branch 合并到 main

示例

假设有两个分支:

  • main 分支:A -> B -> C
  • feature-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 的编辑界面中,每个提交前面都有一个命令(如 picksquashedit 等)。你可以修改这些命令来整理提交历史。

  • pick: 保留该提交(默认操作)。
  • reword: 保留该提交,但修改提交信息。
  • edit: 保留该提交,但暂停 rebase 以便你修改提交内容。
  • squash: 将该提交与前一个提交合并,并合并提交信息。
  • fixup: 将该提交与前一个提交合并,但丢弃该提交的提交信息。
  • drop: 删除该提交。

示例

假设有两个分支:

  • main 分支:A -> B -> C
  • feature-branch 分支:A -> B -> D -> E

执行 git rebase 后,历史记录如下:

A -> B -> C -> D' -> E'

D'E' 是重新应用的提交,哈希值会改变。


3. 合并 vs 变基

特性合并(Merge)变基(Rebase)
历史记录保留完整历史,生成合并提交线性历史,重写提交记录
提交哈希不改变原有提交的哈希值重新生成提交哈希值
适用场景公共分支合并,团队协作本地分支整理,保持干净历史
冲突处理在合并提交时解决冲突在每次提交重新应用时解决冲突
风险历史记录可能复杂重写历史可能导致问题(需谨慎使用)

4. 如何选择?

使用合并(Merge)的情况

  • 合并公共分支(如 mainmaster)。
  • 需要保留完整的历史记录。
  • 团队协作时,避免重写历史。

使用变基(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 的工作方式,所有开发者共享一个中央仓库。

流程

  1. 开发者从中央仓库克隆代码。
  2. 在本地分支上开发。
  3. 将本地更改推送到中央仓库。

优点

  • 简单易用,适合小型团队。
  • 无需复杂的分支管理。

缺点

  • 容易产生冲突。
  • 缺乏并行开发的支持。

2. 功能分支工作流(Feature Branch Workflow)

每个功能或任务都在独立的分支上开发,完成后合并到主分支。

流程

  1. 从主分支(如 main)创建功能分支。
git checkout -b feature-branch
  1. 在功能分支上开发并提交代码。
  2. 完成开发后,将功能分支合并到主分支。
git checkout main
git merge feature-branch

优点

  • 支持并行开发。
  • 隔离功能代码,减少冲突。

缺点

  • 需要管理多个分支。
  • 合并时可能产生冲突。

3. Gitflow 工作流

由 Vincent Driessen 提出,适合有固定发布周期的项目。

分支结构

  • 主分支(main/master) :稳定版本。
  • 开发分支(develop) :集成开发代码。
  • 功能分支(feature/ *)**:开发新功能。
  • 发布分支(release/ *)**:准备发布。
  • 热修复分支(hotfix/ *)**:修复生产环境问题。

流程

  1. develop 分支创建功能分支。
git checkout -b feature/new-feature develop
  1. 完成功能后合并到 develop 分支。
git checkout develop
git merge feature/new-feature
  1. 创建发布分支准备发布。
git checkout -b release/1.0 develop
  1. 发布完成后合并到 maindevelop 分支。
git checkout main
git merge release/1.0
git checkout develop
git merge release/1.0
  1. 修复生产环境问题时,从 main 分支创建热修复分支。
git checkout -b hotfix/1.0.1 main

优点

  • 适合有固定发布周期的项目。
  • 严格的分支管理,减少冲突。

缺点

  • 流程复杂,适合中大型团队。
  • 需要维护多个长期分支。

4. Forking 工作流

常用于开源项目,开发者 fork 中央仓库并在自己的仓库中开发。

流程

  1. 开发者 fork 中央仓库到自己的账户。
  2. 克隆自己的仓库到本地。
git clone https://github.com/your-username/repo.git
  1. 在本地开发并推送到自己的仓库。
  2. 创建 Pull Request(PR)请求合并到中央仓库。

优点

  • 适合开源项目,保护中央仓库。
  • 开发者独立开发,减少冲突。

缺点

  • 需要手动同步中央仓库的更新。
  • PR 审核流程可能较慢。

5. GitHub Flow

由 GitHub 提出,适合持续交付的项目。

流程

  1. main 分支创建功能分支。
git checkout -b feature-branch
  1. 在功能分支上开发并提交代码。
  2. 创建 Pull Request(PR)请求合并到 main 分支。
  3. 代码审核通过后合并到 main 分支。

优点

  • 简单高效,适合持续交付。
  • 强调代码审核和自动化测试。

缺点

  • 需要完善的 CI/CD 工具支持。
  • 不适合有固定发布周期的项目。

6. GitLab Flow

由 GitLab 提出,结合了 Gitflow 和 GitHub Flow 的优点。

分支结构

  • 主分支(main) :稳定版本。
  • 环境分支(production/staging) :对应不同环境。
  • 功能分支(feature/ *)**:开发新功能。

流程

  1. main 分支创建功能分支。
git checkout -b feature/new-feature main
  1. 完成功能后合并到 main 分支。
  2. main 分支合并到环境分支(如 stagingproduction)。

优点

  • 灵活,适合不同开发模式。
  • 强调环境分支,便于部署。

缺点

  • 需要维护多个环境分支。
  • 流程稍复杂。

7. Trunk-Based Development(基于主干的开发)

所有开发者都在主分支(trunk)上开发,适合持续集成和持续交付。

流程

  1. 开发者直接在主分支上开发。
  2. 通过特性开关(Feature Toggles)控制未完成功能的发布。
  3. 频繁提交和集成。

优点

  • 简单高效,适合持续交付。
  • 减少分支管理成本。

缺点

  • 需要完善的 CI/CD 工具支持。
  • 特性开关可能增加代码复杂度。

工作流适用场景优点缺点
集中式工作流小型团队简单易用容易冲突,不支持并行开发
功能分支工作流中小型团队支持并行开发需要管理多个分支
Gitflow 工作流中大型团队,固定发布周期严格分支管理,减少冲突流程复杂
Forking 工作流开源项目保护中央仓库,独立开发需要手动同步中央仓库
GitHub Flow持续交付项目简单高效,强调代码审核需要 CI/CD 工具支持
GitLab Flow灵活开发模式灵活,强调环境分支需要维护多个环境分支
Trunk-Based Development持续集成和持续交付简单高效,减少分支管理成本需要完善的 CI/CD 工具支持

根据团队规模、项目需求和开发模式选择合适的工作流,可以显著提升开发效率和代码质量。