1. 前言
在协作开发与版本管理中,Git 几乎可以说是非常常见了,大量的组织与相应的代码托管平台都依赖于 Git 来运作,如 Linux、GitHub 等。这篇文章中,我们就来学习一下 Git 的基本概念与常用操作、实践用法。
2. Git 简介
简单来说,Git 就是一个分布式版本控制系统。其一大特点就是分布式:与集中式的 SVN 的高度依赖中央服务器相比,Git 对中央服务器的地位进行了弱化,每个人往往在本地电脑中都会保存一份完整的代码库,包括其他所有人的工作记录等。在 Git 中,中央服务器只用来简化每个人的代码块的同步过程,因此即使在离线的情况下,你也完全可以继续在本地的代码库继续工作,等到恢复在线后再将自己的工作同步到中央服务器即可。由于 Git 的流行程度,现在 Git 也拥有许多的可视化客户端,如 GitHub Desktop、Sublime Merge 等,它们能够一定程度上简化操作。不过这里我们还是会聚焦到命令行的 Git 使用上。
3. Git 基本配置
首先在你的本地电脑上安装 Git,具体过程略过不表。接下来,你需要先为 Git 配置自己的用户名与邮箱,这些信息会在你向代码库提交代码的时候被用于标识提交者。
git config --global user.name "名字"
git config --global user.email "邮箱@example.com"
如果你需要向云端提交代码,而本地的网络受到限制、无法直接访问远程服务器的话,Git 还支持你配置代理:
git config --global https.proxy 代理地址
git config --global https.proxy 代理地址
# 如果需要解除代理设置,执行:
git config --global --unset http.proxy
git config --global --unset https.proxy
然后执行 git config --list,如果一切无误的话,你可以看到自己设置的信息已经被 Git 保存了。当然,除了手动设置之外,我们还常常会用到 GitHub 等代码托管平台,这时候可以直接使用平台提供的方式进行设置,如 GitHub 就提供了 GitHub CLI,安装之后只需要执行 gh auth login,然后根据提示登录到 GitHub,登录完成后你的 user.name 和 user.email 就会自动被设置为 GitHub 提供的值。
4. Git 基本使用
要将云端的 Git 代码库(即 repository)下载到本地,只需要执行 git clone 仓库地址 即可。有时候,仓库可能很大,你并不希望下载项目的全部历史信息,这时候可以执行 git clone --depth=1,它会只下载最新的仓库提交数据。如果下载的代码库有 submodule(可以粗略理解为仓库的快捷方式),则你还需要在本地的仓库目录中执行 git submodule update --init --recursive 来下载 submodule,以获取完整的代码环境。执行效果如图:
这就表示你成功地 clone 了一个项目。如果你需要从头开始一个新项目的话,直接新建一个文件夹,然后在文件夹内执行 git init,效果如下:
这样,你便得到了一个空的仓库。在继续之前,先来了解一下 Git 的一些概念:工作区、暂存区、版本库。工作区很好理解:你双击打开仓库文件夹,看到的就是工作区内容。版本库则记录了所有已经提交的数据。暂存区是介于工作区与版本库间的区域:你在工作区的修改会先被上传到暂存区(这个过程称作 stage),然后你可以选择将暂存区的修改打包作为一次提交同步到版本库,也可以选择从版本库或工作区来覆写暂存区的内容(丢弃之前的修改)。这么看来或许有些晦涩难懂,我们不妨用具体的操作来讲解:
git add 文件可以将工作区的指定文件的修改同步至暂存区;特别地,在仓库根目录下执行git add .可以将所有修改同步至暂存区;git commit [-m "提交消息"]可以将暂存区的修改作为一次提交,追加到当前分支的最新提交(即 HEAD);git checkout可以将版本库的特定提交与分支同步到暂存区与工作区,这使得你可以随时随地切换到历史代码现场或者是其他人的最新开发进度git push会将本地的版本库的分支推送至远程仓库;git fetch则相反,会从远程仓库下载最新的分支数据到本地;git pull则还会覆写你的工作区。
掌握了这些命令,其实你就已经能够简单地对你的代码进行版本管理了。
5. Git 高级实践
在实践中,你可能会遇到一些平时不会接触的 Git 操作,如 branch、merge、rebase 等,而他们往往在团队合作中十分常用。下面来分别进行说明:
git branch可以创建和管理新的分支。在实践中,修改往往不会直接在主分支上进行,这样可以确保主分支永远拥有稳定的代码。当我们开始一个新功能的研发或是 bug 修复时,会先创建一个新分支(如果是别人的仓库,那么往往还伴随着一个 fork 操作),然后在上面进行开发,在确定无误后再将修改提交到主分支,最后删除新建的分支即可。每个人都可以同时在各自的分支上进行开发,并在最后进行合并,这十分利好团队合作。git merge则负责实现上面提到的分支的合并。这条指令会生成一条merge commit,其中包括了整个分支上的提交记录,然后将其提交到指定的分支,此时你用git log会看到一个分叉的 Git 提交关系;git rebase叫变基,也负责分支修改的合并,不过原理不太一样:它会基于目标分支的最新状态重写当前分支的所有提交(相当于从目标分支合并到当前分支),然后修改主分支的指针,使它直接指向重写后的最新提交,在git log中看来就是一条笔直清爽的线。但使提交记录更整洁是有代价的:它会破坏当前分支的历史记录,此时如果有人已经依赖于当前分支的提交进行开发,则他们的工作很可能会作废,无法再提交,从而带来麻烦。因此 Git 官网给出了一条准则:如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。
6. 总结
Git 是一个很强大的工具,只要充分地理解、正确地运用它,我们的开发效率就能得到很大提升。我本人也在 Git 的学习过程中收获了许多宝贵的知识、实践经验与思想。