Git 基础知识、常用指令、分支管理策略

一、 Git 简介

1. Git 诞生
  • Linus在1991年创建了开源的Linux,此后Linux系统不断发展,已经成为最大的服务器系统软件了

  • 很长一段时间内,Linux的代码管理:由世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码(虽然一些商用的版本控制系统比 CVS、SVN 等好用,但Linux没有使用,这与Linux的开源精神不符)

  • 随着 Linux系统 的发展,其代码管理由人工手动合并难以维持;这时,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统

  • 2005年,双方合作局面被打破;原因是:Linux社区牛人聚集,试图开发Samba的Andrew试图破解BitKeeper的协议,BitMover公司怒了,要收回Linux社区的免费使用权。

  • Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了

  • Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等

2. Git 是一个 分布式版本控制系统
3. 集中式 和 分布式版本控制系统的 区别
  • 集中式 版本控制系统:

    • 版本库是集中存放在中央服务器的,工作时,先从中央服务器取得最新的版本;工作后,再把代码推送给中央服务器

    • 弊病:传输速度相对较慢;需要联网才能工作(不联网不能提交等操作)

    • 常见的集中式版本控制系统:CVS、 SVN

  • 分布式 版本控制系统:

    • 分布式 版本控制系统 没有中央服务器,每个人的电脑上都是一个完整的版本库;不联网即可完成代码提交等操作

    • 分布式版本控制系统,通常也有一台充当 “中央服务器” 的电脑;协同办公时,将各自代码推送到远程,其他开发人员可将远程最新代码拉取到本地仓库

    • 常见的分布式版本控制系统:Git

4. 常用的版本控制对比
  • VSS

    • 微软开发的版本控制系统,全程 Visual Source Safe ;作为 Microsoft Visual Studio 的一名成员,它主要任务就是负责项目文件的管理;

    • 早期扛起了版本管理系统方面的大旗;能帮助解决一部分版本控制方面的问题,也在一定程度上帮助解决代码共享方面的难题

    • 不足:没有分支功能;同一文档在同一时间内只允许一人修改;文件存储,服务器必须共享文件夹,对文件的安全性没有足够保障

  • SVN

    • 全称:Subversion;集中式版本控制系统;是一个开放源代码的版本控制系统,相较于RCS、CVS,它采用了分支管理系统,它的设计目标就是取代CVS

    • 革新:提供了分支的功能,从而解决了VSS文件独占的问题,提供开发人员的工作效率

    • 不足:必须联网,如果不能连接到服务器上,基本上不可以工作(不能提交,还原,对比等等)

  • Git

    • 分布式版本控制系统,适合分布式开发,每一个个体都可以作为服务器(即一个完整的版本库);每一次Clone就是从远程服务器上pull到了所有的内容,包括版本信息

    • 革新:操作速度快;可离线工作;远程仓库维持这一个原始版本库(杀手锏之一),每个开发人员本地有自己的版本库,开发人员在不联网的情况下,即可工作,在本地版本库进行提交、还原、对比等操作

    • 版本的分支(branch)和合并(merge)十分方便

二、 Git 相关概念

1. 版本库、版本、版本号
  • 版本库:又称仓库(repository)

    • 可以把其简单的看成一个目录(文件夹);这个目录下的文件都由Git管理,当我们对文件进行修改、删除等操作,Git都会对其进行跟踪

    • Git的版本库里存了很多东西:其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支 master,以及指向master的一个指针叫 HEAD

  • 版本:对版本库中的文件进行修改,并已提交日志的方式(相关Git提交指令)让Git记录下此次操作,就是一个版本

  • 版本号:每一个版本的唯一标识;每次提交日志,Git都会生成一个版本号;和SVN不一样,Git的commit id不是1,2,3……递增的数字;而是一个SHA1计算出来的一个非常大的数字,用十六进制表示

  • **当前版本:**Git中,用 HEAD 表示当前版本; HEAD 是指向 master 分支的指针

2. 工作区、暂存区
  • 工作区:简单理解为,我们工作时所在的目录(文件夹)

  • 暂存区:

    • Git版本库中,暂时存放修改的文件的区域

    • Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念

  • 工作区 、暂存区 、版本库的对应关系:

三、获取 Git 仓库

方式一:在现有文件夹中 Git 初始化 git init
  • 现有文件夹中,执行 git init 后,版本库中会创建一个文件 .git ;这个文件是Git来跟踪管理版本库的;千万不要动
方式二:克隆远程 Git 仓库 git clone 远程仓库地址
  • 命令: 默认本地仓库名字 git clone https://github.com/ZXvictory/myTest.git

  • 命令: 自定义本地仓库名字;git clone https://github.com/ZXvictory/myTest.git 自定义仓库名

四、Git 在本地仓库 记录每次更新

第一步:查看 仓库中被改动文件的 状态:git status
  • 状态1:未放到暂存区的文件(下图:红色部分)

  • 状态2:放到暂存区 且 未被提交的文件(下图:绿色部分)

(1) 查看文件变化:尚未暂存的文件 git diff
(2) 查看文件变化:已暂存 将要添加到下次提交的文件 git diff --cahced
(3) 一键还原的命令 git checkout -- 文件:三种情况,如下
  • 情况1:工作区的文件被修改,但没推到暂存区,执行 git checkout -- 文件,会撤销修改,回到和版本库一模一样的状态

  • 情况2:文件已添加到暂存区,但又被修改,执行 git checkout -- 文件,会撤销修改,回到添加到暂存区后的状态

  • 情况3:将暂存区 或 仓库上的文件被删除,执行 git checkout -- 文件,可还原删除的文件;若文件没有被暂存,不能还原

(4) 未暂存的的文件最好 及时 暂存/提交;否则一旦删除或修改,将无法撤回
  • 工作区 和 版本库的文件 最好保持一致;举例说明:版本库中 处于暂存区 或 master分支上的一个文件,在本地(工作区)手动删除,即造成:工作区中没有此文件;版本库中有此文件;此时,处理方案有两种:

    • 方案一:在版本库中,删除该文件 git rm 文件

    • 方案二:执行 git checkout --文件 还原工作区中删除的文件

第二步:将有变动的文件 放到 缓存区:git add *git add -A
  • 添加单个文件到暂存区:git add 单个文件

  • 添加所有文件到暂存区:git add *git add -A

  • 执行上面的命令,没有任何显示,这就对了,Unix的哲学是 “没有消息就是好消息”,说明添加成功;再查看文件状态如下

第三步:将缓存区文件 提交到 本地仓库:git commit -m "日志"
  • 执行完以上第一、二、三步后,意味着 将版本库中文件的修改,提交到了本地仓库的当前分支上了

  • 图示步骤如下:

    • 将有改动的文件添加到暂存区

    • 将暂存区文件提交到本地仓库

五、 Git 日志 与 版本回退

1. 查看详细日志 git log

2. 查看简要日志(常用) git log --oneline

3. 查看详细版本号日志 git log --pretty=oneline

4. 查看所有日志(含回退前的日志) git reflog

5. 版本回退 git reset --hard 版本号前几位git reset --hard HEAD^
  • 当前版本:用 HEAD 表示

  • 方式一:

    • git reset --hard HEAD^ 表示退回上一个版本;
    • 实际上有几个^ 就退回几个版本;退回到前100个版本的命令:git reset --hard HEAD~100
  • 方式二:

    • git reet --hard 版本号 其中版本号前几位即可,Git会自动去找
6. 版本回退后 强行上推 git push -f origin master
  • 注意:

    • 本地版本回退后,如果执行 git push origin master 推到远程;结果是 推不上去,提示 远程代码 比 本地代码 新,建议 先 pullpush

    • 这时候执行 git push origin master 可以将本地代码 强行 推到线上;线上代码 更新后会和本地代码一致

六、 Git 分支操作

1. Git 分支开发工作流
  • 什么是分支:
    • 每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支
    • HEAD 总是指向当前分支

2. Git 分支 常见操作
(1) 查看所有分支(当前分支前面有 * 表示) git branch
(2) 查看本地分支 和 所有远程分支 git branch -a
(3) 创建分支 git branch 分支名
(4) 删除 本地分支 git branch -d 分支名、 删除 远程分支 git push origin --d 分支名
  • 前提: 在所在分支上不能删除本分支;需要切换到零一个分支上,再删除要删除的分支

  • 指令:

    • 删除 本地分支: git branch -d 分支名

    • 强行 删除本地分支: git branch -D 分支名

      • 分支上修改后,没合并到主分支,删除会报错,需强行删除本地分支
    • 删除 远程分支: git push origin --d 分支名

(5) 切换分支 git checkout 分支名
(6) 创建 并 切换分支 git checkout -b 分支名
(7) 分支 合并: 指定分支 到 当前分支 git merge 分支名git merge --no-ff 分支名(推荐使用) 【重要】
  • 快进式 合并:

    • 命令 格式: git merge 分支名

    • 解释:

      • 如果是将 dev 合并到 master 上,执行 git merge 分支名 命令,Git 会直接将 Master 分支指向 dev 分支

      • 合并代码,不会出现提交日志(实际上是 分支指向)

    • 结果: master 分支上代码更新,但没有提交记录(没有 dev 分支上的日志提交记录)

  • 创建新节点 合并:(项目中 推荐使用)

    • 命令 格式: git merge --no-ff 分支名

    • 解释:

      • 如果是将 dev 合并到 master 上,执行 git merge --no-ff 分支名 命令,Git 会在Master 上创建一个新的节点,然后 dev 分支 指向 Master 分支创建的新节点

      • 合并代码,会出现日志提交(默认形式 或 自定义)

    • 结果: master 分支上代码更新,同时会 dev 分支上的日志提交记录

(8) 分支 变基 — 整合来自不同分支 代码 的另一种形式 【重要】
  • 变基:使得提交历史更加整洁;这两种整合方法的最终结果没有任何区别

  • 实践: 若 rebase 前(合并 commit 前)已向远程仓库提交过该分支:则需先在远程仓库删除之前提交的分支后,再rebase 、commit

  • 对别 merge 与 rebase:

    • 场景需求: 需要将 dev 分支上的内容,整合到 master 分支上

    • git merge --no-ff dev 命令:

      • master 分支上 整合过程: 将两个分支的祖先节点、各自的最新节点,三个节点整合;在 分支链的 最顶端 创建一个新节点

      • master上 整合后的节点顺序是: 祖先节点 —> master 分支上祖先节点之后 master 提交的 commit —> merge 后的最新提交节点

    • git merge rebase dev 命令:

      • master 分支上 整合过程:master 分支上祖先节点之后 master 提交的 commit 抽离出来;祖先节点之后 指向 dev 分支上提交的节点;将master 分支上祖先节点之后 master 提交的 commit,置于 dev 分支上提交的节点(可合并 commit)

      • master上 整合后的节点顺序是: 祖先节点 —> dev 分支提交的节点 —> aster 分支上祖先节点之后 master 提交的 commit(可合并 commit)

  • 参考一

  • 参考二

  • 代码冲突:merge 与 rebase 不同的解决策略

    • merge:遇见冲突后会 直接停止(手动解决冲突);重新提交 commit 后,才能完成 merge

    • rebase:遇见冲突后会 暂停当前操作(手动解决冲突)

      • 处理一:解决完冲突后 git rebase --continue 继续 rebase

      • 处理二:直接 git rebase --skip 跳过冲突,强行 rebase(当前分支的修改会直接覆盖目标分支的冲突部分)

      • 处理三:直接 git rebase --abort 停止此次 rebase 操作

七、 Git 分支管理策略 及 工作场景

1. Git 分支管理策略
(1) 主分支 master
  • 代码库应该有一个、且仅有一个主分支。所有提供给用户使用的正式版本,都在这个主分支上发布, 即 用来分布重大版本

  • Git主分支的名字,默认叫做Master。它是自动建立的,版本库初始化以后,默认就是在主分支在进行开发

(2) 开发分支 dev
  • 这个分支可以用来生成代码的最新隔夜版本(nightly)。如果想正式对外发布,就在Master分支上,对Develop分支进行”合并”(merge),下图为master分支多次合并dev的图示
(3) 功能分支 feature(临时)
  • 为了开发某种特定功能,从Develop分支上新建 feature 功能分支;开发完成后,再将 feature 分支合并到 develop 分支上

  • 命名:可以采用 feature-* 的形式

  • 测试稳定后,删除 feature分支,将 develop 分支合并到 master 分支上

git checkout -b feature-x develop

git checkout develop
git merge --no-ff feature-x  # 开发完成后,将功能分支合并到develop分支

git branch -d feature-x  # 删除feature分支
(4) 预发布分支 release(临时)
  • 发布正式版本之前(即合并到Master分支之前),我们可能需要有一个预发布的版本进行测试

  • 预发布分支是从Develop分支上面分出来的,预发布结束以后,必须合并进Develop和Master分支

  • 命名:可以采用 release-* 的形式

git checkout -b release-1.2 develop

git checkout master
git merge --no-ff release-1.2 # 确认没有问题后,合并到master分支
git tag -a 1.2  # 对合并生成的新节点,做一个标签

git checkout develop
git merge --no-ff release-1.2  # 再合并到develop分支

git branch -d release-1.2 # 删除预发布分支
(5) bug分支(临时)
  • 软件正式发布以后,难免会出现bug。这时就需要创建一个分支,进行bug修补

  • 修补bug分支是从Master分支上面分出来的;修补结束以后,再合并进Master和Develop分支

  • 命名:可以采用 fixbug-* 的形式

git checkout -b fixbug-0.1 master

git checkout master
git merge --no-ff fixbug-0.1    # 修补结束后,合并到master分支
git tag -a 0.1.1

git checkout develop
git merge --no-ff fixbug-0.1    # 合并到develop分支

git branch -d fixbug-0.1    # 删除"修补bug分支"
2. 解决:分支冲突
  • 多人分别在自己的分支上,开发同一个文件中的代码,在合并时可能会造成分支冲突

  • 合并分支,若有冲突,会出现如下提示:

  • Git用<<<<<<<=======>>>>>>> 标记出不同分支的内容,如下图;需要手动解决冲突

3. 解决:紧急bug
  • 场景:在自己的开发分支上,代码写到一半,需要要解决紧急bug;但有不想提交现在的代码,因为还没开发完

  • 解决:此时,可以将开发分支上的代码储藏起来 git stash;现在工作区是干净的,不会影响解决bug;可以看看储藏区git stash list,刚才的代码在 储藏区里了;解决完bug后,需要恢复储藏的代码,有两个命令:

    • 命令一:git stash apply;此时代码已恢复,但储藏区的内容并没有清除,需要git stash drop 手动清除

    • 命令二:git stash pop;恢复代码的同时,把储藏区的内容也删除了

4. 开发:不确定的功能
  • 场景:*master上引出一个分支,来开发新功能;开发完了但还没合并*到其他分支上;此时需求不要了,需要删除新分支,执行git branch -d 分支名;会报错error: The branch 'feature' is not fully merged.

  • 解决:此时可以使用 git branch -D 分支名;来强行删除新分支

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值