git实践新感悟分享
我在平时和多次面试里表达我在第一次实习中没有参与到规范的git工作流的遗憾,在那个暑假我也写了一篇git的知识总结,将过往学习到的以及我认为重要的git命令写了上去。
但我长久以来都认为学习git必须要到工作流中去,因为现代代码管理和技术管理不仅仅是一个工具,而是从远程到本地,从团队到个人的一整套工作流程,只有在团队性技术实践中我们才能接触到规模化的、生产化的代码管理,进而理解git在这当中发挥的意义。
我会从工作场景、工作流两个方面分享我在最近的实践中对git的新理解。当然,实践时间尚不长久,内容多有误解,望读者包含且指正。最后也会从git作为最流行的版本控制程序的发展历程来讲一讲我对git本身的理解。
工作场景中的常用指令组
如果你仅仅是看了几篇教程或git命令文档,请把“熟悉git工具使用”从你的简历上去掉,或者改为“了解git基本命令”,否则这会害了你。
git本地配置
你可以通过git命令或直接修改git配置文件的方式对git本地配置进行修改,如果你从公司得到一台电脑或新安装了git服务,请务必首先配置您的基本信息,以保证IDE或其他代码编辑工具获取到正确的开发者信息。
通过命令的方式:
# 查看当前git配置清单
git config --list
# 配置全局git用户名称和邮箱,这将用于标识代码的作者信息
git config --global user.name "username"
git config --global user.email [email protected]
修改git配置文件(通常情况下全局配置文件所在位置):
- Windows:
C:\Users\username\.gitconfig
- MacOS:
/Users/username/.gitconfig
即~/.gitconfig
- Linux:
/home/username/.gitconfig
即~/.gitconfig
若有需求需要为某个项目配置独立的git信息,则应在项目的.git目录下找到相关配置并对应修改。
创建与链接远程仓库
基本操作
创建本地仓库:
# 项目目录下
git init
git add .
git add README
git commit -m '首次提交的备注信息'
首次配置远程仓库密钥并创建远程仓库:
# 在本地生成ssh密钥对
ssh-keygen -t rsa -C "[email protected]"
# 复制你的公钥到gitlab或github账户中进行配置,不讲细节了
cat ~/.ssh/id_rsa.pub
# 向本地 Git 仓库添加一个新的远程仓库配置
git remote add origin https://github.com/user/repo.git
常见场景
1.本地有项目,远程空仓库
我们在工作中常见的情形之一便是给你一个项目,然后有权限的管理者在托管平台新建空仓库,随后需首先将本地的框架或demo代码同远程仓库进行关联。
即本地已经存在代码但尚未初始化为git仓库,远程有已建立的空仓库。
进入项目目录,操作示例如下:
git init # 初始化git仓库
git checkout -b dev-branch # 签出开发分支
git add . # 添加文件到暂存区
git commit -m "first commit" # 首次提交
git remote add origin https://remote-repo-url.git # 关联到远程仓库
git push - u origin dev-branch # 推送并关联当前分支
2. 本地尚空,远程项目仓库
这是最常见也最简单的情形,即需要从公司托管平台clone已有代码到本地进行开发。
进入需要存放项目的父目录,操作示例如下:
git clone [email protected] local-project # clone ssh或https的仓库链接
git checkout -b feature-branch # 签出开发分支
git add . # 注意按需添加
git commit -m "Made some changes" # 提交代码
git push origin feature-branch # 推送并关联当前分支
合并与变基
合并(merge)和变基(rebase)都是进行分支合并处理时的选项,其特性和应用没有限制性规范,但需要根据技术团队的需求和风格进行具体选择,例如我所在的团队就倾向于在MR时进行变基,以便于保持master的清晰简洁。
对比 | 合并(Merge) | 变基(Rebase) |
---|---|---|
目的 | 将多个分支的修改整合在一起 | 修改提交历史,使分支的提交看起来是基于另一个分支的最新提交线性开发的 |
提交历史呈现 | 保留分支合并的痕迹,有明显的分支结构,可能会出现合并提交 | 使提交历史更加线性、整洁,没有分支合并的痕迹 |
冲突处理方式 | 冲突发生时,标记冲突部分,解决后使用git add 和git commit 完成合并 | 冲突发生时,标记冲突部分,解决后使用git add 和git rebase --continue 继续变基过程,可能需要多次解决冲突 |
对远程分支的影响 | 比较直观,远程分支不受本地操作影响,除非推送合并后的分支 | 如果已推送分支到远程,变基后推送可能会导致远程分支提交历史改变,影响其他开发者 |
整体来分别总结两者的应用场景是这样的:
- 合并:团队希望保留完整的分支开发历史,相对不注重被提交结果的线性历史
- 分支:团队不关注前期开发细节,注重提交结果的线性、简洁
MR
MR即Merge Request,合并请求,实现分支的合并。在github平台下通常被称为PR(Pull Request),词语不同但其含义是一致的,都是开发者向仓库管理者提请的合并请求。
之所以要单独提出来讲一下MR,因为它在工作当中是一个非常重要的操作,是衡量开发者工作效果的重要指标之一。
开发者应当在完成自己分支功能的开发后,将功能分支向指定分支合并,即提请MR,这是企业中的仓库管理者会收到开发者的MR请求,启动MR审核程序。其在团队中的大致流程如下:
- 开发者创建MR
- MR自动流水线检查、构建测试(如果有的话)
- 团队或项目负责的,对该仓库有权限的同学对其进行审核
- 对MR的核心功能和影响进行测试
- 最终合并MR(变基或合并)
工作流程及其中的注意事项
我将简单梳理一个开发工作流程中的git情景,并依据自己的理解标注其中的注意事项。
1. 创建仓库和链接远程仓库
- 注意确认公司对ssh或http的要求;
- 特别关注仓库关联的分支,不应在master分支下进行开发或提交
- 注意修改README
2. 提交并推送代码
- 编写代码或提交代码前应先使用
git pull
将当前代码更新至分支最新状态并处理冲突 - 经常提交代码,完成一部分修改就提交,不要一股脑交一大堆代码
- 提交代码时注意编写清晰简洁的说明
3. 完成开发提请MR
- 谨慎提交MR,自己审查明白先
- 注意选择合适的审核和指派人员,其需要有相关权限
- 及时处理其他成员对MR提出的问题并给出回应
题外话:理解git和它的发展历程密不可分
在git诞生前,就已有了成熟的版本控制应用,例如Linus在进行Linux开发时使用的Bitkeeper,它们存在专有化、集中式等问题。
Linus 在开发 git 的时候,目标是设计一个简单而强大的系统。他从一开始就采用了分布式的设计理念。在传统的集中式版本控制系统中,如 CVS 和 Subversion,存在一个中央服务器,所有的开发者都需要从这个中央服务器获取和提交代码。而 git 采用分布式模型,每个开发者的本地仓库都是一个完整的版本库,包含了项目的完整历史记录。
由此,我们在应用中着重关注git带来的独有特性或优化能力:
- 分布式理念:每一个开发者的本地仓库都是一份完整的仓库;
- 分支处理:git带来了强大而简洁的分支创建、切换和合并能力,进而引入了丰富的分支管理策略;
- 快照存储:git会以快照形式存储每一个文件的状态,由此带来极为高效的版本切换能力;
- 离线工作:由于git本地仓库的完整结构设计,开发者可以再不链接远程仓库的情况下,在本地持续开发和提交代码,进行版本管理。