用动图助你在2020年彻底搞懂Git

2,247 阅读9分钟


工作区:平时coding的区域,新增,更改,删除文件这些动作,都发生在这里。
暂存区:通过git add命令把工作区代码提交到暂存区,意思是暂时存储到某个区域,等待上传到本地仓库。


上面这张图可以先收藏,不理解没关系,建议先看完下面的基础部分。

敲黑板,git的精髓在于两个指针(HEAD指针,分支指针)

【HEAD指针】

简介:1. HEAD指针是一个可以在任何分支和版本移动的指针。
     2. 如果我们没有切换到某个分支,而是切换到某一次提交,HEAD就会处于「detached」状态,也就是游离状态。
     3. 游离状态好处是可以很便捷的回到某次提交。
     4. 游离状态坏处, 这种状态下是无法保存的。
     5. HEAD指针默认指向当前的分支指针


git checkout 命令 用于检出分支或者检出快照 也可以用来恢复工作树的文件

检出分支或快照:git checkout [快照commitId | 分支指针branchName]

恢复文件:git checkout 文件名

如图,head指向从某分支checkout到某个版本号(commit)时就会进入游离模式了

【分支(branch)指针】

切换分支命令: git branch -f [需要切换的分支][快照commitId|分支指针branchName]

创建新分支

git branch 分支名

切换分支

git checkout dev 

合体命令用起来,新建并切换到新建分支:

git checkout -b = git branch + git checkout

提交记录

git commit -m '提交信息摘要'
当HEAD指向的branch提交时,提交后HEAD指针会和branch指针一起移动。

在实际开发中,仅使用默认分支难以满足工作里遇到的复(qi)杂(pa)需求。这时候,我们通常会建立起多个分支,这些分支各司其职,共同担负起对项目的支撑与维护工作的大任,以下是现阶段大家公认且比较常用的分支:

master分支:发布重大版本

dev分支:日常开发

test分支:测试 例如 test-login

bug分支:修补bug 例如: issue-007

feature分支:开发新功能 例如: feature-chat

合并dev分支到master

在dev分支研发完毕后,想要将dev上的代码整合到master分支,可以在master分支下使用git merge dev命令,需要注意的是,git merge根据不同情况,有两种不同的合并模式,一种称作fast-forward,另一种我们暂且称之为no-fast-forward

git merge 分支名 

no-fast-forward

我们暂且将下图重的2号称之为分叉点,由分叉点创建了dev分支,某天研发,我们完毕将dev分支合并进master。 这个过程中, Git将通过dev分支的首次提交点对master分支进行追溯,如果master分支最新一次的提交就是dev分支的分叉点,则判定为fast-forward,否则no-fast-forward.

no-fast-forward 将对dev分支进行合并后产生一个新的merge commit,将其并入在master分支上,如下图:

fast-forward

fast-forward的情况下,master相对于dev分支,其实仅仅是落后了几个版本,这时候只需要简单的将HEAD与其所指向的分支移动一下就行了。

你也可以给git merge 加上--no-ff 参数来强制启用no-fast-forward模式,这种情况下即使判定为fast forward,也会生产一个新的merge commit。

删除分支

合并完成之后,通过git branch -d 分支名将分支删除

需要注意的是无法删除当前所在分支

挑拣提交

如果只想将分支上的某一次提交单独合并到当前分支上,那么可以使用git cherry-pick。

git cherry-pick 版本号

变基操作,重定基底

git rebase dev 

git rebase 俗称变基,意思是重新定义新的基底。

什么是基底? 在面向对象设计中,被定义为包含所有实体共性的class类型,被称为“基类”,基类又叫做父类。而git中的基底是指两个分支的共同祖先,在git的主要功能就是把某个分支的单个或多个commit提取出来作为‘补丁’,然后把这个补丁提交到你的基底分支(通常是master分支)。 这样你会发现你的分支提交已经在master分支的前面了。

no-fast-forward 模式下的merge会将分支上所有的提交合并生成一个merge commit,这种合并方式抹去了大量的提交信息,而rebase可以避免如此

小伙伴们注意了!!! 这里rebase之后是处于游离模式的,记得使用上面我们提到过的
git branch -f master 6  把master分支移动到相应的快照上

reset


下面介绍几个常用的git reset命令:
  1. git rebase --soft commitId 回退到指定版本号,把修改移动到暂存区

  1. git rebase --mixed commitId 回退到指定版本号,把修改移动到工作区

  1. git rebase --hard commitId 回退到指定版本号,把修改删除

  1. git rebase -i HEAD~3 查看最近3次提交的commit倒序排列
  1. git rebase -i --root 查看提交的所有commit倒序排列
  1. git reflog 查看历史操作

针对某些 危险操作,Git通过记录HEAD指针的上次所在的位置ORIG_HEAD提供了回退的功能。当你发现某些操作失误了,比如错误的reset到了一个很早很早的版本,可以使用 git reset --hard ORIG_HEAD回退到上一次reset之前。

git中每一次移动HEAD指针,Git都会将移动的路径通过链表串起来作为记录,你可以用git reflog查看这些操作记录, 当然也可以在.git文件夹查看到reset前的版本号。

工作流

git工作流是针对协同开发,流程管理的一系列解决方案
并没有明文规定必须要如何去用,
我们首先要做的是去弄明白工作流解决了什么问题,
之后你大可以针对自己的需求,从众多工作流中挑选其一,
也可定制一个适合自己的。

目前流行的有两种:

Gitflow工作流 Forking工作流

emmmmmmm..
下面属于.git文件系统与底层原理相关的知识点,就比较复杂
虽然还想上动图给大家演示,可惜能(懒)力(癌)有(晚)限(期)哈哈

.git

下面属于课外内容,对git原理有兴趣,想深入研究的朋友,我说一下我个人的学习方法并配上一些心得体会给你们做下参考:

1.使用`git cat-file`查看仓库中对象实体的类型、大小和内容的信息
2.用git cat-file给出的信息对照.git文件夹来作为参考
3.尝试使用commit reset等命令,观察.git文件夹的变化

.git文件夹先截图简要介绍一波~

.git目录清单
橙色=文件夹
介绍 备注
COMMIT_EDITMSG 记录最新的commit massage
branches 没什么用,可忽略 github: git说明
config 代码库级别的配置文件 可通过git config --local --list查看
description 仓库的描述信息,主要用于gitWeb页中的description
FETCH_HEAD 每个分支在服务器上的最新状态 第一次git fetch后将生成这个文件
HEAD 记录当前被checkout的分支,可以理解为所在分支的指针
hooks shell编写的钩子脚本目录,里面包含许多后缀名为.sample文件,可通过删除.sample后缀来启用钩子 方便在git的各个阶段自动运行一些东西,比如在submit时附带分支名等信息
index 二进制文件(暂存区)
info 和.gitignore是互补的, 用于本地配置个人设置,不会提交到服务器被共享
logs 所有分支的引用记录
objects Git本地仓库的所有对象
ORIG_HEAD 记录HEAD指针的前一个版本号,用以回溯一些危险操作,例如reset后文件将保存reset前的版本号
packed-refs 查找引用时,git按先在/refs目录下查找,不存在再去 packed-refs文件查找
refs 包含所有的分支、标签(commit)的引用

Git 与 SVN

小伙伴们可以在命令行使用 git init 来初始化一个.git文件夹(这个文件只有聪明的人才能看到 ),里面定义了关于仓库的配置与历史记录。


SVN Git
仓库 仅有一个中央仓库 每一位开发人员本地都存有一份完整的版本仓库
版本号 仅有一个中央仓库,很容易实现索引的连续性, 每次操作都会使索引号+1 由于分布式的原因, 采用了40字符长度的哈希值作为索引
commit操作 commit会直接记录到中央版本库 commit是本地操作,需要push才会提交到主要版本库
网络依赖 必须要联网才能工作,否则基本不能进行commit、diff等操作 离线也可工作
创建分支 集中管理,没有本地分支,创建新分支会使所有人拥有相同分支, 可创建本地分支,本地分支提交至主要版本库前,不会影响其他开发人员
切换分支 switch checkout
存储方式 元数据 文件
权限 能给用户分配读写的权限,可对文件目录进行授权,子目录默认继承父目录,不可对单一文件授权 需要借助工具才能分配
版本回退 由于仅有一个中央仓库,回退时,可能会导致项目成员clone到老代码,因此SVN比较适合集中管理,不适合开源项目的开发。 可以在本地回退
检出 可根据目录进行部分检出 只能全部检出

有哪些地方有疏漏,欢迎大家指出,避免误导新人,

另外再推荐大家一个网站,非常适合用来入门的呦~ learngitbranching.js.org/?locale=zh_…

参考文章:
1. https://cloud.tencent.com/developer/article/1348992

如何制作Gif

1.使用keynote 制作动画
2.对keynote进行录屏
3.使用GIT Brewery3将其转为gif

下期会做JS词法环境的教程,有兴趣的朋友们可以关注一下