应用技术
Git

Git

一、Git 基础概念

1. 什么是 Git?

Git 是一个分布式版本控制系统,用于追踪文件(尤其是源代码)的变化。

每个开发者的本地仓库都包含完整的版本历史,可以独立进行提交、分支和合并操作。

2. Git 和 SVN 有什么区别?

  • 架构:Git 是分布式的,SVN 是集中式的。
  • 分支操作:Git 的分支轻量快速;SVN 分支是目录复制,较重。
  • 离线能力:Git 支持离线提交、查看日志;SVN 需要网络连接。
  • 性能:Git 基于快照(snapshot),SVN 基于增量(delta)。
  • 安全性:Git 通过哈希值(SHA-1)校验完整性。

二、常见操作与命令

1. Git 的常用命令有哪些?

git init            # 初始化仓库
git clone <url>     # 克隆远程仓库
git add <file>      # 添加文件到暂存区
git commit -m "msg" # 提交代码
git status          # 查看状态
git diff            # 查看修改内容
git log             # 查看提交历史
git branch          # 查看分支
git checkout <branch> # 切换分支
git merge <branch>  # 合并分支
git rebase <branch> # 变基操作
git stash           # 暂存未提交的更改
git reset           # 撤销提交或回退版本

三、分支管理

1. Git 分支的工作原理

Git 的分支本质上是一个指针,指向某次提交(commit)。

创建新分支只是创建一个新的指针,因此操作极快。

2. merge 和 rebase 的区别

  • merge:将目标分支的修改合并到当前分支,保留所有历史记录。

  • rebase:将当前分支的提交“移植”到目标分支上,生成线性历史。

    使用建议:

  • 团队协作时用 merge,安全且保留上下文;

  • 私有分支上可用 rebase,保持历史整洁。


四、版本回退与修正

1. 如何撤销一次提交?

  • 回退但保留记录:
git revert <commit_id>
  • 彻底回退(危险):
git reset --hard <commit_id>

2. 如何撤销已提交但未推送的修改?

git reset --soft HEAD~1   # 撤销提交但保留修改
git reset --hard HEAD~1   # 撤销提交并丢弃修改

3. 如何修改最近一次提交信息?

git commit --amend

五、远程协作

1. push 和 pull 的区别

  • git push:将本地提交推送到远程仓库。

  • git pull:拉取远程更新并自动合并。

    (相当于 git fetch + git merge)

2. fetch 和 pull 的区别

  • git fetch:只拉取远程更新,不自动合并;
  • git pull:拉取并自动合并,风险较高。

六、冲突解决

1. Git 冲突出现的原因

多名开发者修改了同一文件的同一行,并尝试合并时会发生冲突。

2. 冲突的解决流程

  1. Git 标记出冲突位置(<<<<<<<、=======、>>>>>>>)
  2. 手动编辑文件,保留正确内容
  3. 执行:
git add <file>
git commit

七、标签与发布

1. 如何创建和推送标签?

git tag v1.0.0
git push origin v1.0.0

标签用于标记特定版本(如发布点)。

2. 轻量标签 vs 注释标签

  • 轻量标签:仅指向一个提交。
  • 注释标签:包含创建者、时间、信息,更常用于发布。

八、Git 工作流(Workflow)

1. Git Flow

常见分支模型:

  • master:线上稳定版本
  • develop:开发主分支
  • feature/*:功能开发
  • release/*:预发布版本
  • hotfix/*:线上紧急修复

2. Trunk Based Development

强调短周期、频繁集成,直接在主干上开发小分支,减少复杂度。


九、面试高频问题总结

1. 如何解决多人协作中的代码冲突?

  • 提前 pull 更新,减少冲突;
  • 避免多人改同一文件;
  • 用 rebase 保持历史清晰;
  • 冲突时手动比对修改再提交。

2. Git 的 HEAD、index、working tree 分别是什么?

  • HEAD:指向当前分支的最新提交;
  • index(暂存区):保存已添加、待提交的修改;
  • working tree(工作区):实际文件系统中的代码。

3. 如何查看某行代码是谁写的?

git blame <file>

4. 如何回滚远程仓库版本?

  1. 本地 reset 到指定版本;
  2. 强制推送:
git push origin HEAD --force

十、实战情景题(高频)

场景1:误删文件后发现还没提交

git checkout -- <file>

恢复到上次提交状态。

场景2:想要忽略某个文件的修改但不删除

git update-index --assume-unchanged <file>

场景3:如何在不合并的情况下查看另一个分支的文件

git checkout <branch> -- <file_path>

是否希望我接着输出 「iOS 项目中常见的 Git 分支策略与团队协作最佳实践」 这一部分?

十一、iOS 项目中的 Git 分支策略与协作实践

1. iOS 团队常用分支模型

在实际 iOS 开发中,常见的团队协作分支模型主要包括三种:

(1)Git Flow 模型

适合中大型团队,结构清晰。

主要分支:

  • main(或 master):线上正式发布版本;
  • develop:日常开发主线;
  • feature/*:开发新功能;
  • release/*:预发布;
  • hotfix/*:线上紧急修复。

优点:规范、清晰,适合多人协作。

缺点:分支较多,操作复杂。

(2)GitHub Flow 模型

适合小团队或持续集成频繁的项目。

流程简洁:

  • 从 main 分支创建 feature 分支;
  • 开发并提交 PR;
  • 通过代码审查(Code Review);
  • 合并回 main 并部署。

(3)Trunk Based Development

主张“所有人都在主干上快速迭代”。

分支生命周期极短(通常 <1天),依赖自动化测试与 CI/CD。

适合高频发布、自动化程度高的 iOS 团队。


2. iOS 项目推荐的分支策略

多数中型 iOS 团队采用以下折中方案:

  • main:正式 App Store 版本;
  • develop:主开发分支;
  • feature/xxx:功能分支;
  • release/x.y.z:提测、灰度;
  • hotfix/x.y.z:线上问题紧急修复。

实际操作示例:

git checkout develop
git checkout -b feature/login
# 开发完成后
git merge feature/login
git push origin develop

3. 代码审查与 Pull Request 流程

PR(Pull Request)是团队协作的核心环节。

标准流程如下:

  1. 开发者提交功能分支;
  2. 通过 CI 检查(编译、单测、lint);
  3. Reviewer 进行代码审查;
  4. 合并至主分支或开发分支。

常用审查工具:

  • GitHub / GitLab Merge Request
  • Bitbucket PR
  • Phabricator(部分大厂)

重点关注:命名规范、commit message 规范、代码风格一致性。


4. 提交信息规范(Commit Message)

建议使用 Conventional Commits (opens in a new tab) 格式,便于生成变更日志(changelog):

<type>(scope): <description>

常见类型:

  • feat:新功能;
  • fix:修复问题;
  • refactor:代码重构;
  • perf:性能优化;
  • test:单元测试;
  • docs:文档修改;
  • chore:构建流程或依赖变更。

示例:

feat(login): add Face ID support for iOS 17
fix(coredata): resolve crash on background context merge

5. Tag 与 Release 管理

iOS 项目版本发布通常依赖 Git tag 与 CI/CD 管理:

git tag -a v2.3.0 -m "Release v2.3.0"
git push origin v2.3.0

CI 系统(如 GitHub Actions / Jenkins / Bitrise)监听 tag 事件自动:

  • 构建归档 .ipa;
  • 上传 TestFlight;
  • 发布 Release Notes。

6. 子模块与多组件管理(Submodules & Subtrees)

当 iOS 项目采用模块化架构(如多个 SDK、组件库)时:

  • Git Submodule

    子仓库独立管理,但更新麻烦:

git submodule add <url> Modules/Networking
git submodule update --init --recursive
  • Git Subtree

    合并时更灵活,不需要手动初始化:

git subtree add --prefix=Modules/Networking <url> main --squash

推荐:

  • SDK 组件库 → 独立仓库 + CI 自动打包;
  • 业务模块 → 子模块或 CocoaPods 私有源管理。

7. 常见协作问题与解决方案

(1)冲突频发

  • 规范分支粒度;
  • 合并前及时 pull --rebase;
  • 合并后强制通过 CI 编译验证。

(2)多人改同一文件(如 Info.plist)

  • 统一放置常量文件;
  • 拆分 plist;
  • 或使用脚本动态注入版本号、配置项。

(3)提交历史杂乱

  • 私人分支使用 rebase 整理;
  • 统一通过 squash 合并 PR;
  • 强制 PR 模板要求清晰描述。

8. Git 与 CI/CD 的结合

在 iOS 项目中,Git 通常与自动化平台结合使用:

工具功能常用触发
GitHub Actions持续集成与部署push、PR、tag
Jenkins企业内部 CI 系统定时/触发构建
Bitrise移动端专用自动化PR、分支、tag
Fastlane自动打包与上传工具CI 脚本调用

示例:

# .github/workflows/release.yml
on:
  push:
    tags:
      - 'v*'
jobs:
  build:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - run: fastlane ios release

9. iOS Git 忽略文件配置(.gitignore)

防止上传敏感文件和缓存:

# macOS
.DS_Store

# Xcode
build/
DerivedData/
xcuserdata/

# CocoaPods
Pods/

# Carthage
Carthage/Build/

# Swift Package Manager
.swiftpm/

# Other
*.xcuserstate

10. 面试高频实战题

题1:多人开发同一功能时如何防止冲突?

  • 明确模块责任;
  • 功能分支粒度小;
  • 合并前更新并解决冲突;
  • 使用 PR 审核流程。

题2:如何处理一个错误提交到远程仓库的敏感文件?

  1. 使用 git filter-branch 或 BFG Repo-Cleaner 清除历史;
  2. 强制推送:git push origin --force --all;
  3. 更新 .gitignore 防止再次上传。

题3:如何为 iOS 项目维护稳定的发布分支?

  • 使用 release/x.y.z 分支进行测试与提审;
  • 发布后合并回 main 与 develop;
  • 打标签标记版本,便于回滚。

是否需要我接着输出 「十二、Git 高级技巧与优化(例如子仓库管理、cherry-pick、bisect、reflog 等)」

十二、Git 高级技巧与优化

1. git cherry-pick(挑选提交)

用于从其他分支“复制”特定提交到当前分支。

git cherry-pick <commit_id>

场景:

  • 某个修复在 develop 已提交,但也需要同步到 release 分支。

    优点:

  • 不影响其他提交,精确移植。

    注意:

  • 多个提交可用 git cherry-pick A..B 批量选择。


2. git stash(临时保存修改)

当你需要切换分支但当前修改未提交时:

git stash save "WIP: 调试中"
git checkout other-branch
git stash pop

命令解释:

  • git stash list 查看暂存内容;

  • git stash pop 应用并删除暂存;

  • git stash apply 应用但不删除。

    典型场景:临时修 bug 时保存当前工作状态。


3. git bisect(二分查找 bug 提交)

用于定位引入 bug 的提交。

git bisect start
git bisect bad HEAD          # 标记当前版本为坏
git bisect good <commit_id>  # 标记旧版本为好

Git 会自动切换版本,让你逐步测试,最终输出问题提交。

非常适合 iOS 项目中回溯某个版本引入崩溃或 UI 错误的情况。


4. git reflog(恢复丢失提交)

当误用了 git reset --hard 或强制推送后,可用 reflog 恢复:

git reflog
git reset --hard HEAD@{3}

reflog 记录了本地所有 HEAD 的移动历史,是最后的“保险”。


5. git reset 三种模式

  • -soft:仅回退 commit,保留工作区与暂存区修改。
  • -mixed(默认):回退 commit,保留工作区但清空暂存区。
  • -hard:彻底回退到指定提交,删除所有修改。

示例:

git reset --soft HEAD~1   # 撤销最近提交但保留修改
git reset --hard HEAD~1   # 回退并清空所有修改

6. git rebase –interactive(交互式变基)

整理历史提交、合并多次无意义提交:

git rebase -i HEAD~3

进入编辑界面后可使用:

  • pick 保留提交;
  • squash 合并提交;
  • edit 暂停修改;
  • drop 删除提交。

常用于 PR 前清理 commit 历史,保持提交整洁可读。


7. git tag 与 release notes 自动化

结合 CI 工具(如 GitHub Actions + Fastlane),可自动识别标签并生成变更日志:

fastlane changelog_from_git_commits

自动读取 commit 信息中的 feat, fix 等关键词生成发布说明。

这在 iOS 自动打包与 TestFlight 发布流程中非常常见。


8. git hooks(钩子脚本)

Git 在执行关键操作前后可触发脚本,例如:

  • pre-commit:提交前检查代码格式;
  • commit-msg:校验提交信息格式;
  • pre-push:在推送前运行单元测试。

示例(.git/hooks/pre-commit):

#!/bin/bash
xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15'
if [ $? -ne 0 ]; then
  echo "❌ 单元测试未通过,终止提交。"
  exit 1
fi

在团队中结合 Husky (opens in a new tab)lint-staged (opens in a new tab) 可以保证代码质量。


9. git submodule 与 CocoaPods 对比

  • Submodule:版本完全受控,更新需手动。

  • CocoaPods / Swift Package Manager:更自动化,但依赖集中管理。

    建议:

  • 公共 SDK → 用 SPM / CocoaPods 管理;

  • 特殊内部组件 → 用 Submodule 固定版本。


10. git blame 与 log 调试技巧

  • 查看某行修改来源:
git blame <file>
  • 查看谁在什么时候修改了函数:
git log -L :funcName:file.swift
  • 查看单个文件修改记录:
git log --follow <file>

这些命令在定位某段历史变更导致的 UI 问题或逻辑 Bug 时极其高效。


11. git clean(清理工作区)

清除未追踪的文件(例如 DerivedData 残留或中间产物):

git clean -fd

参数解释:

  • f 强制删除;
  • d 包括文件夹;
  • x 同时删除忽略文件(谨慎使用)。

12. git sparse-checkout(部分检出)

对于大型仓库(如包含多个模块或 demo 的 iOS monorepo),可只检出部分目录:

git sparse-checkout init --cone
git sparse-checkout set App/ModuleA

减少磁盘占用与构建时间,常用于多组件大项目。


13. 常见优化策略

  • 浅克隆
git clone --depth 1 <url>
  • 仅拉取最新一次提交,适用于 CI 构建。

  • 减少提交体积

    不提交二进制文件、缓存、DerivedData。

  • 提交前格式化

    结合 SwiftLint 或 SwiftFormat 保持代码统一。

  • CI 缓存依赖

    利用 Git hash 缓存 Pods 或 DerivedData,加快构建。


14. Git 在 iOS 团队中的最佳实践总结

  1. 小步提交,语义清晰:每次提交只做一件事。
  2. 合并前自测通过:保持分支可随时发布。
  3. 保护 main 分支:启用保护规则、强制 PR。
  4. 使用 tag 管理版本:自动构建与发布。
  5. 定期清理历史:rebase -i + gc 优化仓库体积。
  6. 代码审查必经流程:每次 PR 至少一人审核。

15. iOS 面试高频实战问答总结

问:如何回滚一个已经推送到远程的错误提交?

答:

  1. 使用 git revert 生成反向提交;
  2. 推送到远程;
  3. 避免使用 reset --hard 强制覆盖,除非是私有分支。

问:团队多人在同一分支上开发,如何避免提交混乱?

答:

  • 严格遵循 feature 分支策略;
  • 统一命名规范(feature/xxx、hotfix/xxx);
  • 提交前 rebase 同步最新代码;
  • 启用保护分支防止直接 push。

问:如何在不合并的情况下测试某分支的变更?

答:

git checkout other-branch -- <file>

或用 git worktree 创建并行工作区,独立编译测试。

问:发现某个提交导致构建失败,如何快速定位?

答:使用 git bisect 二分查找问题提交。

问:如何防止机密文件(如 API Key)被上传?

答:

  1. .gitignore 屏蔽;
  2. 使用环境变量或 .xcconfig;
  3. 若已上传,使用 BFG Repo-Cleaner 清理历史。

十三、总结与延伸

Git 是 iOS 开发中不可或缺的核心工具。

面试中考察的不只是命令记忆,更看重:

  • 对分支模型的理解;
  • 团队协作流程意识;
  • 处理冲突与灾难恢复能力;
  • 提交规范与自动化发布经验。

掌握 Git 的本质,就像掌握“时间旅行”的能力:

你能在任何时刻回到过去,也能重写未来。


如果需要,我可以进一步扩展最后一节:「十四、iOS 团队 Git 流程自动化与最佳工程实践(结合 CI/CD、Fastlane、App Store 发布)」,把整套从版本到发布的流程串成体系。是否要继续补全?

十四、iOS 团队 Git 流程自动化与最佳工程实践(CI/CD 集成)

1. Git 与 CI/CD 的角色分工

在现代 iOS 团队中,Git 只是“源头”,

CI/CD(持续集成与持续交付)才是版本发布自动化的“引擎”。

二者关系可以简化为:

Git 提交代码 → CI 自动构建与测试 → 自动生成包并发布至 TestFlight / App Store

典型工具链:

  • 代码托管:GitHub / GitLab / Bitbucket
  • 持续集成:GitHub Actions / Jenkins / Bitrise / CircleCI
  • 自动化打包:Fastlane
  • 版本发布:TestFlight、App Store Connect API

2. CI/CD 流程概览(结合 Git 工作流)

Feature Branch → Pull Request → Review → Merge to Develop

  CI 自动构建 & 单元测试

   Merge to Release

  自动生成 Tag + 上传 TestFlight

   Merge to Main

  自动打正式包 & 发布到 App Store

关键事件触发器(Trigger):

  • push:任意提交时执行基本测试;
  • pull_request:合并前执行代码审查与单测;
  • tag:创建新版本标签时触发打包与发布。

3. Git 标签与自动发布版本

发布新版本推荐使用语义化标签(Semantic Versioning):

v1.0.0  → 初始稳定版
v1.1.0  → 新功能
v1.1.1  → Bug 修复

在 CI 中监听标签事件触发构建脚本:

# .github/workflows/release.yml
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - run: bundle install
      - run: fastlane ios release

4. Fastlane 自动化打包与上传

Fastlane 是 iOS 自动化的核心工具,可完成以下任务:

  • 自动递增版本号;
  • 构建 .ipa 文件;
  • 上传到 TestFlight;
  • 提交 App Store 审核。

示例 Fastfile:

lane :release do
  increment_build_number
  build_app(
    scheme: "MyApp",
    export_method: "app-store"
  )
  upload_to_testflight(
    skip_waiting_for_build_processing: true
  )
end

与 Git tag 结合时,可自动将版本号与 tag 同步:

version = lane_context[SharedValues::VERSION_NUMBER]
add_git_tag(tag: "v#{version}")
push_to_git_remote

5. 自动化测试与质量控制

CI 在每次合并前应执行以下任务:

  1. 编译检查(防止语法错误进入主干);
  2. 单元测试(xcodebuild test 或 fastlane scan);
  3. Lint 检查(SwiftLint / SwiftFormat);
  4. 依赖检查(Pod install 是否通过);
  5. 打包构建(验证能成功生成 .ipa)。

示例(GitHub Actions):

jobs:
  test:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - run: bundle install
      - run: fastlane scan

6. 自动生成 Release Notes 与版本记录

结合 Git 提交信息自动生成版本更新日志:

fastlane changelog_from_git_commits

或使用开源工具:

自动生成:

## v2.3.0
- feat: 新增登录保护
- fix: 修复 CoreData 崩溃问题
- perf: 优化视频加载性能

7. 分支保护与代码审查自动化

保护关键分支(如 main 和 develop):

  • 禁止直接推送;
  • 强制 Pull Request;
  • 强制通过 CI 测试;
  • 要求至少一名 Reviewer 审核。

在 GitHub 中配置:

Settings → Branches → Branch protection rules

启用:

  • Require status checks to pass before merging
  • Require pull request reviews before merging

8. 多 Target / 多环境构建策略

常见 iOS 项目存在多个环境:

  • Debug(开发环境)
  • Staging(测试环境)
  • Release(正式环境)

在 Git 中推荐使用分支对应不同环境配置:

分支环境打包方式
developDebug手动打包或 CI 内测
release/x.y.zStaging自动上传 TestFlight
mainRelease自动上架 App Store

结合 .xcconfig 与环境变量切换不同 API Key 或 Bundle ID。


9. Git 版本号自动同步

避免人工维护 Info.plist 的 CFBundleVersion。

Fastlane 自动脚本:

lane :bump do
  increment_build_number
  commit_version_bump(
    message: "chore: bump build number [skip ci]"
  )
  push_to_git_remote
end

这样,每次构建版本号都会自动加 1,并推送回仓库。


10. 持续部署与灰度发布

  • TestFlight 自动化

    结合 upload_to_testflight,自动上传内测版本给 QA。

  • 灰度发布策略

    可在 CI 中控制上传渠道或受邀用户范围;

  • 自动上架

    Fastlane 提供 deliver 命令直接上传到 App Store 审核队列。


11. 安全与凭证管理

  • 使用 App Store Connect API Key 代替手动输入账号;
  • 使用 GitHub Secrets / Jenkins Credentials 存储密钥;
  • 使用 match 管理证书和描述文件同步;
  • 禁止在代码库中提交 .p12、.mobileprovision 等敏感文件。

12. 自动化回滚与热修复机制

在 CI 流程中保留上一个成功构建版本号:

当新版本发布失败或崩溃率上升时,可自动触发回滚脚本。

企业内部可结合自研 OTA 系统或 Firebase Remote Config 控制灰度比例。

此外:

  • 对热修复方案(如 JSPatch、Dynamic Framework Update)要严格控制签名与审核;
  • 重要分支在合并前必须经过自动化测试全覆盖。

13. 性能与维护优化

  • 使用 shallow clone:git clone --depth=1

    减少 CI 拉取时间;

  • 缓存 Pods 与 DerivedData

    通过哈希缓存,减少重复构建时间;

  • 自动清理旧分支

    定期运行脚本清除已合并的 feature 分支;

git branch --merged | grep -v 'main' | xargs git branch -d

14. iOS 团队 Git 自动化最佳实践总结

阶段工具作用
提交前Husky + SwiftLint格式校验、代码规范
合并前GitHub Actions / Bitrise自动编译与单测
发布前Fastlane + Tag自动打包上传 TestFlight
发布后自动生成 Release Notes保留版本历史与日志
安全match + Secrets 管理自动化签名与证书维护

核心原则:

让开发者专注于写代码,而非重复劳动。


15. 面试高频问答总结(CI/CD 集成类)

问:如何设计一套自动化 iOS 打包发布流程?

答:

  1. Git 打 tag;
  2. CI 检出代码并执行单测;
  3. Fastlane 打包上传 TestFlight;
  4. CI 自动生成 changelog;
  5. 成功后合并回主分支并推送 tag。

问:如何防止错误代码合并到主干?

答:

  • 启用保护分支 + 强制 PR;
  • 所有合并必须通过 CI;
  • Reviewer 至少一人签核。

问:如何在多分支协作下保证版本号一致性?

答:

  • 所有构建通过 Fastlane 自动递增;
  • CI 用环境变量统一版本号源;
  • 禁止手动修改 Info.plist。

问:如何实现“一键打包上传 TestFlight”?

答:

配置 Fastlane:

fastlane ios beta

执行自动:

  1. 编译;
  2. 生成 IPA;
  3. 上传 TestFlight;
  4. 通知团队。

十五、总结:Git 驱动的工程自动化哲学

Git 是整个开发体系的“中枢神经”,每一次提交都是项目演化的节点。

从分支策略到 CI/CD 自动化,关键目标只有一个:

让软件演化变得安全、可控、可重复。

在 iOS 团队中,真正的高手不是会多少命令,

而是能将 Git 作为“时间机器”,

把每一次构建、每一个版本、每一个决策都记录得清清楚楚。

掌握 Git,你就掌握了工程的历史与未来。

——至此,Git 版本控制 + CI/CD 自动化相关的 全部 iOS 面试高频考点 已完整覆盖。