Git — 是一个开源分布式版本控制系统,由 Linus Torvalds 于 2005 年为 Linux 内核开发而创建。与 SVN 等集中式系统不同,Git 在每个开发者的设备上存储完整的仓库副本,允许在没有持续服务器连接的情况下工作。根据 Git SCM,2024 的数据,Git 被用于超过 90% 的商业软件开发项目。
要点
Git — 是一个分布式版本控制系统(VCS),它跟踪文件中的变更并允许多个开发者同时处理同一个项目。与集中式系统不同,在 Git 中每个开发者都拥有仓库的完整副本,包括所有变更历史,这使得系统能够抵抗数据丢失,并且不需要持续连接到中央服务器。
Git 的历史始于 2005 年,当时 BitKeeper 公司撤销了其系统对 Linux 内核开发者的免费许可证,Linus Torvalds 创建了新的 VCS。目标是:速度、架构简单、通过分支支持非线性开发以及完全分布式。在 3 个月 内 Torvalds 编写了 Git 的核心,一年后该项目在 Junio Hamano 的领导下转为自我管理。
根据 Stack Overflow 调查(2024),93.9% 的专业开发者使用 Git,使其成为行业中占主导地位的版本控制系统。最接近的竞争对手 — Subversion(SVN)— 仅用于 5.2% 的项目,主要在具有集中式流程的大型企业环境中。
Git 仓库 — 是 Git 跟踪所有文件变更的目录。在目录内部有一个隐藏的 .git 文件夹,其中存储了系统的所有对象:提交、树、数据块和引用。当开发者创建提交时,Git 不会完整复制文件 — 它会创建状态的快照并保存对其的引用。
每个 提交 包含:唯一的 SHA-1 哈希(40 个字符)、指向前一个提交的引用(parent)、作者、日期、提交消息以及描述提交时文件状态的树(tree)的引用。提交链形成一个有向无环图,其中每个提交指向一个或多个父提交。
# 初始化仓库
git init my-project
cd my-project
# 创建提交
echo "Hello, Git" > README.md
git add README.md
git commit -m "Initial commit"
# 查看历史
git log --oneline --graph --all
Git 使用三个主要区域:工作目录(磁盘上的文件)、暂存区(准备就绪的文件进入的索引)和 仓库(提交历史)。git add 命令将变更从工作目录移动到暂存区,git commit 将暂存区的内容记录在仓库中。这种分离允许开发者从一组变更中组合出有意义的提交,而无需单独记录每个修改。
Git 基本命令 涵盖了开发者 90% 的日常操作。git clone 命令创建远程仓库的本地副本,git pull 从服务器获取变更并与当前分支合并,git push 将本地提交发送到服务器。这三个命令构成了使用 Git 的基本工作循环。
查看状态使用 git status — 它显示哪些文件已被修改、哪些已添加到暂存区以及哪些未被跟踪。git diff 在添加到暂存区之前显示文件中的具体变更。以下是常用命令的表格:
| 命令 | 操作 | 示例 |
|---|---|---|
| git clone | 复制远程仓库 | git clone https://example.com/repo |
| git add | 将文件添加到暂存区 | git add src/main.kt |
| git commit | 在历史中记录变更 | git commit -m "Fix login bug" |
| git push | 将提交发送到服务器 | git push origin main |
| git pull | 从服务器获取变更 | git pull origin feature |
Git 提供了多种撤销变更的选项。git reset 将分支指针移动到指定的提交,并可以重置暂存区或工作目录。git revert 创建一个新的提交来撤销指定提交的变更 — 这是共享分支的安全撤销方式,因为 历史 不会被重写。
Git 中的分支 — 是指向特定提交的轻量可移动指针。创建新分支不会复制文件,只创建一个新指针,这使得分支几乎是瞬间完成的。main 分支(以前称为 master)— 项目的主分支,包含稳定、可发布的代码。
标准实践是使用 Git Flow 或 GitHub Flow。在 Git Flow 中使用以下分支:main(发布代码)、develop(集成分支)、feature/*(新功能)、release/*(发布准备)和 hotfix/*(紧急修复)。GitHub Flow 更简单:只有 main 和 feature 分支,所有变更通过 Pull Request 交付。
# 创建和切换分支
git branch feature-auth
git checkout feature-auth
# 或使用一条命令:
git checkout -b feature-auth
# 分支列表
git branch --list
git branch -a # 所有分支,包括远程分支
# 删除分支
git branch -d feature-auth
Git 分支 的一个重要特性 — cherry-pick 功能:使用 git cherry-pick <hash> 命令将单个提交从一个分支转移到另一个分支。当需要将错误修复从 feature 分支转移到 release 而无需合并整个分支时,这非常有用。Git 还支持变基(rebase)和交互式变基(git rebase -i),用于合并、重新排序和编辑提交。
Merge(合并)创建一个具有两个父提交的特殊合并提交。此提交记录了两个分支的合并事实并保留完整历史 — 可以看到合并发生的地点和时间。Merge 以创建时的形式保留历史,这简化了审计,但使提交图更加复杂。
Rebase(变基)不是创建合并提交,而是将当前分支的提交移动到目标分支的顶部。历史变得线性 — 给人一种开发是按顺序进行的印象。然而,rebase 会重写历史,更改提交的 SHA-1 哈希,这使得它对其他开发者可访问的共享分支 危险。
选择建议:对于其他开发者可见历史的公开分支使用 merge(feature → develop),对于在创建 Pull Request 之前需要将 main 中的最新更改应用到自己的 feature 分支的本地工作使用 rebase。规则很简单:如果提交已经发送到服务器 — 不要变基它。
合并冲突 在 Git 无法自动合并一个文件中的更改时发生。Git 使用特殊标记标记文件中的冲突部分:<<<<<<<(我们的更改)、=======(分隔符)、>>>>>>>(他们的更改)。开发者手动编辑文件,选择所需选项或组合两者,并用提交完成合并。
远程仓库(remote) — 位于服务器上的 Git 仓库的副本。GitHub、GitLab 和 Bitbucket 是最流行的远程仓库托管平台。它们提供用于查看代码、管理访问、代码审查和与 CI/CD 系统集成的网页界面。
在 Git 中可以为单个项目配置多个远程仓库。默认情况下,主要 remote 称为 origin。git remote add 命令添加新的 remote,git fetch 在不合并的情况下获取更改,git pull 是 git fetch + git merge 的简写。要通过 Pull Request 进行代码工作,开发者创建仓库的 fork,克隆它,在 feature 分支中工作,并向原始仓库发送合并请求。
# 添加远程仓库
git remote add origin https://github.com/user/repo.git
# 查看远程仓库
git remote -v
# 将分支发送到服务器
git push -u origin feature-auth
# 从远程分支获取更改
git pull origin main
远程仓库支持 标记 用于标记发布版本。标记可以是轻量级(仅指向提交的指针)和带注释的(包含元数据:作者、日期、消息)。建议对发布版本使用带注释的标记,因为它们传递关于版本的完整信息,并且可以使用 GPG 密钥签名以 验证 作者身份。
Git Worktree 允许在不同目录中同时处理多个分支而无需在它们之间切换。git worktree add ../feature-auth feature-auth 命令创建一个新的工作目录 feature-auth,可以在其中编写代码而无需更改主目录中的分支。当主目录忙于长期开发时,Worktree 对于 release 分支中的快速修复非常有用。
Git Submodules — 将一个 Git 仓库包含到另一个仓库中的机制。子模块存储对外部仓库的固定提交的引用,这保证了构建的可重复性。git submodule add https://github.com/example/lib.git 命令将外部库添加为子模块。在克隆带有子模块的项目时,需要执行 git submodule update --init --recursive 来加载所有依赖。
常见问题
Git — 具有本地历史和离线工作能力的分布式 VCS。SVN — 一个集中式系统,除查看文件外所有操作都需要持续连接到服务器。
使用 git revert HEAD 进行安全撤销(会创建新的提交)。如果提交尚未发送到服务器,可以使用 git reset --soft HEAD~1。
.gitignore — 列出 Git 应忽略的文件和目录模式的文件。用于从仓库中排除临时文件、构建产物和 IDE 配置。
git fetch 从服务器下载更改但不与当前分支合并。git pull 执行 fetch 并立即执行 merge。为了控制,请使用 fetch + 查看 diff,然后手动 merge。
使用 git commit --amend — 此命令打开编辑器以更改提交消息。如果提交已在服务器上,将需要 git push --force,这对共享分支是 危险 的。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。