一文读懂 Git 与工作流

Git 是一个开源的分布式版本控制系统,常用于协同开发和管理项目代码。它由Linus Torvalds在2005年创建,并成为了许多开发团队和开源社区的首选工具。

Git 的主要特点包括:

  1. 分布式: 每个开发者都拥有完整的代码仓库副本,包括完整的历史记录。这意味着即使在离线状态下,开发者仍然可以进行提交、分支切换等操作,不会受到中心化版本控制系统的限制。
  2. 版本控制: Git 记录了项目代码的每个版本和变更。通过提交(commit)操作,开发者可以记录代码的修改并添加相应的注释说明。这样可以轻松地查看和比较不同版本之间的差异,并追踪代码的演进。
  1. 分支: Git 提供强大的分支机制,可以创建新的分支来独立开发特性或修复错误,而不影响主线代码。分支操作快速且轻量,使得团队成员可以并行进行工作,然后再将各自的分支合并到主线上。
  1. 合并: Git 提供了多种合并策略,使得将不同分支的代码合并变得简单。能够智能地处理代码冲突,并提供易于理解的合并历史。
  1. 代码审查: Git 支持团队中的代码审查流程。开发者可以通过查看提交(commit)的变更,并在合并请求(pull request)中进行讨论和评审,改进代码质量和团队协作。
  1. 轻量且高效: Git 的设计简单而高效,具有出色的性能表现。由于每个开发者都拥有完整的代码仓库副本,因此可以快速进行各种操作,如提交、切换分支、查看历史等。

为什么要学习 Git ?

  • 业界绝大多数公司基于 Git 进行代码管理,因此 Git 是一个程序员的必备技能
  • 目前绝大多数开源社区都基于 Git 维护,参与项目开发都需要使用 Git

1 Git 是什么

  • Git 官网

https://git-scm.com/

  • Git 是什么?

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

  • 版本控制是什么?

一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统

  • 为什么需要版本控制?

更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行检查,预防事故发生,也能的够随时切换到不同的版本,回滚误删误改的问题代码:

1.1 版本控制对比

版本控制的方法和工具有很多,它们之间又有什么区别呢?

版本控制类型代表工具解决的问题
本地版本控制RCS本地代码的版本控制
集中式版本控制SVN提供一个远端服务器来维护代码版本,本地不保存代码版本,解决多人协作问题
分布式版本控制Git每个仓库都能记录版本历史,解决只有一个服务器保存版本的问题
1.1.1 本地版本控制
  • 本地版本控制通过复制本地文件夹来完成版本控制,一般可通过不同的文件名来区分版本
  • 基本原理是本地保存所有变更的补丁集,通过这些补丁,我们可以计算出每个版本的实际文件内容
  • 这种版本控制的缺点是只能在本地使用,无法进行团队协作,使用场景十分有限
1.1.2 集中式版本控制

代表工具: SVN

基本原理

  1. 提供一个远端服务来保存文件,所有用户的捉交都捉交到该服务器中
  2. 增量保存每次提交的 diff,如果提交的增量中和远端现存的文件存在冲突,则需要本地提前解决冲突

优点

  1. 学习简单,更容易操作
  2. 支持二进制文件,对大文件支持更友好

缺点

  1. 本地不存储版本管理的概念,所有提交都只能联上服务器后才可以提交
  2. 分支上的支特不好,对于大型项目团队合作比北较困难
  3. 用户本地不保存所有版本的代码,如果服务端故障客易导致历史版本的丢失。
1.1.3 分布式版本控制

代表工具:Git

基本原理

  1. 每个库都存有完整的提交历史,可以直接在本地进行代码提交
  2. 每次提交记录的都是完整的文件快照,而不足记录增量
  3. 通过 Push 等操作来完成和远端代码的同步

优点

  1. 分布式开发,每个库都是完空的提交历史,支持本地提交,强调个体
  2. 分支管理功强大,方便团队合作,多人协同开发
  3. 校验和机制保证完整性,一股只添数据,很少执行删除操作,不容易号致代码丢失

1.2 Git 发展历史

Git 的作者 Linus Torvalds 也是 Linux 项目的作者。由于 BitKeeper (另一种分布式版本控制系统,专有软件)不允许 Linux 团队继续无偿使用,因此 Linux 团队决定自己开发一个分布式版本控制系统,团队大概花了两周时间就完成了 Git 的代码第一个版本,后续Liux项目就开始使用 Git 进行维护。

Git 是当下最流行的版本控制工具,基于 Git 衍生出了很多代码托管平台

  • Github:全球最大的代码托管平台,大部分的开源项目都放在这个平台上
  • Gitlab:全球最大的开源代码托管平台,项目的所有代码都足开源的,便于在自己的服务器上完成 Gitlab 的搭建

2 Git 的基本使用方法

2.1 Git 目录介绍

新建一个文件夹,执行git init命令

git init

# 其他参数
--initial-branch 初始化的分支
--bare 创建一个裸仓库(纯Git目录,没有工作目录)
--template 可以通过模板来创建构建好的自定义 git 目录

文件夹中会生成一个 .git 目录,我们后续的操作都会映射到这个目录中

.git
 ├── config
 ├── HEAD
 ├── hooks
 │   └── commit-msg.sample
 ├── info
 │   └── exclude
 ├── objects
 │   ├── info
 │   └── pack
 └── refs
     ├── heads
     └── tags

2.2 Git 配置

我们看到 .git 目录里面有一个 config 文件,里面的内容就是 git 的配置,我们配置不同级别的配置,每个级别的配置可能重复,低级别的配置会覆盖高级别的配置

2.2.1 Git config 配置

常见的 Git 配置

# 用户名配置
git config --global user.name <username>
git config --global user.email <useremail>

# git 命令别名配置
git config --global alias.cin "commit --amend --no-edit"
2.2.2 Git remote 配置

除了以上基本配置,还有一种 remote 配置,表示本地和远程仓库的关联信息

# 查看 Remote
git remote -v

# 添加 remote
git remote add origin_ssh git@github.com:git/git.git
git remote add origin_http https://github.com/git/git.git

同一个 Origin 可以设置不同的 Push 和 Fetch URL ,可以实现从一个仓库拉取代码并推送到另外一个仓库

git remote add origin git@github.com:git/git
git remote set-url --add --push origin git@github.com:MY_REPOSITY/git
git remote -v

2.3 Git add

git add 的命令是将代码提交到暂存区,执行命令前后变化

2.4 Git commit

git commit 用于向仓库提交暂存代码,提交后 objects 和 refs 文件夹会有变化

2.4.1 Objects

commit/tree/blob在 git 里面都统一称为 Object, 除此之外还有个 tag 的 object.

  • Blob:存储文件的内容
  • Tree:存储文件的目录信息
  • Commit:存储提交信息,一个 Commit 可以对应唯一版本的代码

2.4.2 Refs

refs 的内容就是对应的 Commit ID,因此把 ref 当作指针,指向对应 Commit 来表示当前 ref 对应版本

refs / heads 前缀表示的是分支,除此以外还有其他种类的 ref,比如 refs / tags 表示标签

  • Branch (分支)

利用 git checkout -b可以创建一个分支,用于开发阶段不断 commit 进行迭代

  • Tag (标签)

利用git tag命令生成标签,一般表示一个稳定版本,指向的 commit 一般不会变更

2.5 Git gc

GC

通过 git gc 命令,可以删除一些不需要的 object,以及会对 object 进行一些打包,压缩来减少仓库的体积。

Reflog

reflog 是用于记录操作日志,防止误操作后数据丢失通过 reflog 来找到丢失的数据,手动将日志设置为过期。

指定时间

git gc prune=now 指定的是修剪多久之前的对象,默认是两周前

2.6 Git clone & pull & fetch

Clone

拉取完整的仓库到本地目录,可以指定分支,深度。

Fetch

将远端某些分支最新代码拉取到本地,不会执行 merge 操作,会修改 refs/remote 内的分支信息,如果需要和本地代码合井需要手动操作。

Pull

拉取远端某分支,并和本地代码进行合并,操作等同于git fetch+git merge,也可以通过 git pull --rebase 完成 git fetch+git rebase 操作。可能存在冲突,需要解决冲突。

2.7 Git push

git push 是将本地代码同步至远端的方式

常用命令

一般使用git push origin master命令即可完成

冲突问题

1.如果本地的 commit 记录和远端的 commit 历史不一致,则会产生冲突,比如 git commit --amend or git rebase 都有可能导致这个问题。

2.如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过 git push origin master -f 来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送。

推送规则限制

可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失。

2.8 常见问题

1.为什么我明明配置了Gt配置,但是依然没有办法拉取代码?

  • 免密认证没有配。
  • Instead Of 配置没有配,配的 SSH 免密配置,但是使用的还是 HTTP 协议访问。

2.为什么我 Fetch 了远端分支,但是我看本地当前的分支历史还是没有变化?

  • Fetch 会把代码拉取到本地的远端分支,但是并不会合并到当前分支,所以当前分支历史没有变化。

3 Git 开发流程

3.1 不同的工作流

类型代表平台特点
集中式工作流Gerrit / SVN只依托于主干分支进行开发,不存在其他分支
分支管理工作流Github / Gitlab可以定义不同特性的开发分支,上线分支,在开发分支完成开发后再通过MR/PR合入主干分支
3.1.1 集中式工作流

什么是集中式工作流?

只依托于 master 分支进行研发活动

工作方式

1.获取远端 master 代码

2百接在master分支完成改

3.提交前拉取最新的 master 代码和本地代码进行合并(使用 rebase),如果有冲突需要解决冲突

4.捉交本地代码到 master

3.1.2 分支管理工作流
分支管理工作流特点
Git Flow分支类型丰富,规范严格
Github Flow只有主干分支和开发分支,规则简单
Gitlab Flow在主干分支和开发分支之上构建环境分支,版本分支,满足不同发布 or 环境的需要

Git Flow

  • 包含五种类型的分支

Master: 主干分支

Develop: 开发分支

Feature: 特性分支

Release: 发布分支

Hotfix: 热修复分支

  • 优点

如果能按照定义的标准严格执行,代码会很清晰,并且很难出现混乱。

  • 缺点

流程过于复杂,上线的节奏会比较慢。由于太复杂,研发容易不按标准执行从而导致代码出现混乱。


Github Flow

Github的工作流,只有一个主干分支,基于 Pull Request 往主干分支中提交代码。

选择团队合作的方式

  1. owner 创建好仓库后,其他用户通过Fok的方式来创理自己的仓库,井在 fork 的仓库上进行开发
  2. owner 创建好仓库后,统一给团队内成员分配权限,直接在同一个仓库内进行开发

创建一个Pull Request

  1. 创建一个main主分支
  2. 创建一个 feature 分支
  3. 创建一个 feature 到 main 的 Pull Request
  4. 可以在 Pull Request 页面执行 CI/CA/CR 等操作,都检查通过后,执行合入
  5. 可以通过进行一些保护分支设置,来限制合入的策略,以及限制直接的 push 操作

Gitlab Flow

Gitlab 推荐的工作流是在 Git Flow 和 Github Flow 上做出优化,既保持了单一主分支的简便,又可以适应不同的开发环境。

原则:upstream first上游优先

只有在上游分支采纳的代码才可以进入到下游分支,一般上游分支就是 master.

3.2 代码合并

Fast-Forward

不会产生一个 merge 节点,合井后保持一个线性历史,如保 target 分支有了更新,则需要通过rebase 操作更新,source branch 后才可以合入

Three-Way Merge

三方合并,会产生一个新的 merge 节点

3.3 如何选择合适的开发流

选择原则

没有最好的,只有最合适的

针对小型团队合作,推荐使用Github工作流即可

  1. 尽量保证少量多次,最好不要一次性提交上干行代码
  2. 提交 Pull Request 后最少需要保证有 CR 后再合入
  3. 主干分支尽量保持整洁,使用 fast-forward 合入方式,合入前进行 rebase

3.4 常见问题

  1. 在Gerrit平台上使用Merge的方式合入代码。

Gerrit 是集中式工作流,不推荐使用 Merge 方式合入代码,应该是在主干分支开发后,直接Push。

  1. 不了解保护分支,Code Review,CI 等概念,研发流程不规范。

保护分支:防止用户直接向主干分支提交代码,必须通过 PR 来进行合入。
Code Review, CI: 都是在合入前的检查策略,Code Review 是人工进行检查,CI 则是通过一些定制化的脚本来进行一些校验。

  1. 代码历史混乱,代码合并方式不清晰。

不理解 Fast Forward 和 Three Way Merge 的区别,本地代码更新频繁的使用 Three Way 的方式,导致生成过多的 Merge 节点,使提交历史变得复杂不清晰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值