wkevin

History

2016.7 v1.0 完成 Git 基础
2017.4 v1.1 局部修订
2019.8 v1.2 修订近几年的变化,删除svn对比的内容

Git 基础

源起

VCS (Version Control System)

  • SCCS(Source Code Control System) – 1970+, M.J.Rochkind
  • RCS(Revision Control System) – 1980+, Walter F. Tichy
  • CVS(Concurrent Version System) – 1986, Dick Grune
  • SVN(Subversion) – 2001
  • BitKeeper
  • Mercurial
  • Git – 2005.4, Linus Torvalds

Git从何而来

Git去往何处


  • 2005年7月26日开始,Torvalds把Git托付给了一位日本人:Junio Hamano
  • Torvalds 2012 年说过自己一生最大的成功之一就包括把git托付给Hamano
  • Hamano现在google,他的github帐号为:gitster

官方Specification

Book

Website

github上Git的卓越组织

  • git:
    • 目前有17位成员,牵头人 Scott Chacon,他们充当管理者和传教士的角色
    • 比较重要的贡献是:
      • 维护git源码
        • Hamano(gitster)并没有加入到这个Orgnization中,而只是fork到自己账号下,然后PR到 git/git,看来gitster只是想当程序员,不想当管理者和传教士——大概源于日本人和中国人类似,都比较低调。
        • Hamano 现在已经加入此组织
      • 管理和维护 git-scm.com 网站
  • progit
    • 目前有18位成员,牵头人 Scott ChaconBen Straub,两人目前都供职于github公司,其他人多是从事翻译工作。
    • 比较重要的贡献
      • 写了《Pro git》这本书,此书被翻译成多种语言(中文版),被奉为经典。

Git 常用命令

Practice

快速记忆,请写出至少5个git的命令

Git的逻辑分区及几个关键命令

Practice

请绘出上页的图

Git my diary

一个完整的日记示例

最基本的两个配置:name 和 email

创建一个文件夹并写一篇日记

git init 在文件夹中创建git库

和SVN有.svn类似,git也有.git

git status 查看当前状态

显示一个未被管控的文件(Untracked files) diary.md

git add filename 将文件纳入管理

filename 支持通配符,最常用的就是点(.)表示所有文件

git status

显示此文件待提交(to be committed),此时文件已经开始被git管理了,文件进入一种暂存状态(stage),如果想反悔可以用git rm --cached使其进入unstage状态

git status -sb

-s/–short 短模式

-b/–branch 显示分支

git status不带参数默认就是-b的,所以常和短模式合作,合并为一个sb,哈哈

git commit 将文件从暂存态提交入库

暂存就像回收站(删除前给你一个check的机会,多次操作放入回收站的文件可以一次清空),多次操作放入暂存,最后考虑成熟了,check OK了,再commit提交

编辑 log message

执行 git commit 后会自动打开一个编辑器(编辑器是可配置的,以后再说怎么配置),比如 vi,进行提交log的撰写,保存退出即提交成功,不保存退出即放弃提交

再查 git status,都已经提交干净了

现在可以看log了

每天可以随时写日记、随时git add、适时git commit,经过一段时间,你的diary库就越来越让你爱不释手了

git 和 svn 不同,没有一个数字递增的节点号,而是一串40Bytes的哈希字符,指定一个提交只需要给出这个字符串即可,当然不能让你每次都把40个字符全输入一遍,只需要输入够区分提交的即可(一般是前7位),如果咱的库规模还很小,前4位也行哦(上文中的“6784”)

Practice

请简要的按顺序写出上面例子中用到的git命令

Git Revesion

git revision 的描述

  • <sha1>: e.g. dae86e
  • <describeOutput>: e.g. v1.2.3
  • <refname>: e.g. HEAD,master, heads/master, refs/heads/master
  • @ : HEAD的简写
  • <refname>@{<date>}: data日期之前的第一个revision
  • <refname>@{<n>}: 第n-th个revision
    • git log 出的1-st revision在这里算 2-nd
  • <rev>^: e.g. HEAD^, v1.2.3^, 表示 rev的前一个revision
  • <rev>~<n>: e.g. HEAD~3, master~3,去掉n个,取下一个
    • git log 出的1-st revision开始去掉


详细:git help revisionsman gitrevisions

git revision range 的描述

  • <rev>: 从rev到结束的所有revision都包括进来
  • ^<rev>: 从rev到结束的所有revision都抛弃掉
  • <rev1> <rev2>: “rev1到结束”和“rev2到结束”取并集,即:rev1或rev2到结束最多的那个range
  • <rev1> ^<rev2> == ^<rev2> <rev1>: “rev1到结束”和“rev2到结束”取并集,即:rev1 和 rev2 之间,但不包括rev2,rev1和rev2无时间先后
  • <rev1>..<rev2>: 从rev2往前,到rev1(但不包括rev1)或rev1所在的分支的交汇点,rev1或rev1与rev2分支交汇点要在rev2的时间前面
  • <rev1>...<rev2>:
  • <rev>^@: rev的所有parent,不包括 rev
  • <rev>^!: 仅rev


详细:git help revisionsman gitrevisions

Practice

只看 zte 分支的 revision
从上周三的 revision 开始看
不看近10次的 revision

Practice

只看近一个月的 revision

git config

location

command 说明
git config [–local] 配置项保存到当前git项目(./.git)
仅本项目有效默认
git config –system 配置项保存到系统(/etc/gitconfig)
所有git项目有效
git config –global 配置项保存到用户根目录(~/.git/config)
当前用户的所有项目有效
git config –file 配置项保存到指定文件

alias

语法

举例

使用缩写

别名(alias)是linux系统的基本概念,在git中也如鱼得水。

我的常用别名

git add

原理图

Focal Point

  • git add onefile
  • git add .
  • git add onefolder/.

stage

  1. 名词:舞台、讲台,比如:戏剧表演的舞台、国际政治的舞台;阶段,类似phase,比如:stage one/two意思是第一/二阶段,three-stage rocket意思是三级火箭
  2. 动词:上演、举行、组织,类似play、organize,比如:stage a football match,举办足球赛




stage本身并没有暂存的意思,git中可以理解为把文件放到一个舞台上上演一下,进而文件进入到一个新的阶段。——用这个词可以说是一箭三雕

git help stage

  • help中可以发现: git stage 是同义于 git add
  • staging area: 舞台区、阶段区、进而翻译为暂存区 —— 如果让我翻译,我会译为:检视区

暂存区 ~ 回收站

  • 把文件放在回收站是给操作人一个检视的机会和反悔的机会,操作妥当后再彻底删除,彻底删除后再想反悔就要费劲了。
  • git的staging area也是给用户一个检视的机会反悔的机会,用户可以:
    • 使用git addgit stage命令随时向SA增加文件,和回收站不同的是后进入SA的文件会覆盖前面进入的
    • 使用git checkout命令随时从SA反悔,文件会从SA移除,是否覆盖

.gitignore

  • 当前目录下的忽略文件、目录的列表,如:编译过程文件……
  • 可以存在与git项目的根目录和子目录下,每个文件只影响该目录下的文件和子目录
  • 手工写,没有自动生成
  • 支持shell通配符,如:*
  • #开头表示注释行
  • !开头的表示取反

git commit

Focal Point

  • git commit -a/–all : 提交所有已暂存、未暂存、未追踪的文件
  • git commit -m “xxx”
  • git commit : 没有 -m “xxx”, git 会调用一个外部编辑器
    • 编辑器保存退出 && message不为空: 则算一次成功的提交
    • 不保存退出 || message为空: 提交作废

Ubuntu 的编辑器

git rm

删除文件

  • 直接使用 rm 删除,会让 git 认为文件丢失(missing状态)
  • git rm 才能让 git 争取识别用户意图
  • git rm 操作后文件本地工作目录中的文件即被删除, git commit 时删除对象库中的。

git log

git shortlog

  • 根据提交人分类
  • 每次提交占1行
  • 时间先旧后新

git log –date=short

git log –pretty=xxx

git log –pretty=short

git log –pretty=formate:“xxx”

  • xxx:
    • %h:commit hash
    • %ai: author date
    • %an: author name
    • %ci: commit date
    • %cn: commit name
    • %s: log message

git config –global alias.lg “log …”

gitk

git diff

比较对象

命令 比较对象
git diff 工作目录~索引区
git diff --cached 索引区~对象库
git diff <rev> 工作目录~rev
git diff <rev1> <rev2>
git diff <rev1>..<rev2>
rev1~rev2

结果显示

命令 结果显示
git diff 结果是变更文件,和patch形式的文本
git diff --stat 结果只显示变更文件,和变更的内容幅度
git diff --name-only 结果只显示变更文件的文件名
git diff --name-stat 结果显示变更文件的文件名,和增删改的状态

linux diff

diff f1 f2 == f1与f2之间的差异 == f1 -> f2 的变化过程


diff shell 命令 3种输出格式
$ diff f1 f2 正常格式(normal diff)
$ diff f1 f2 -c 上下文格式(context diff)
$ diff f1 f2 -u 合并格式(unified diff)

diff f1 f2 =X= diff f2 f1

linux diff 2

两个文件: 1.txt、2.txt,并列显示内容如下:

  • 3c3: 1.txt的第3行 change 为2.txt的第3行
  • < 3 / > 7: change 方式为 1.txt 删除字符3, 2.txt 增加字符7
  • 5d4: 1.txt的第5行 delete
  • ……

  • "***"表示变动前的文件
  • “—”表示变动后的文件

  • “—”表示变动前的文件
  • “+++”表示变动后的文件

Practice

diff 2.txt 1.txt -u

Practice

git diff 使用的是哪种 diff 形式?

git diff 与 git log

  • git diff 不关心待比较文件的历史,也不关心分支,只关注当前对象本身
  • git log 更关注文件的来龙去脉,即对象的parent、son……

Practice

比较当前HEAD版本和上一个HEAD版本

Practice

比较3者的异同:
1. $ git diff topic master
2. $ git diff topic..master
3. $ git diff topic…master

  1. Changes between the tips of the topic and the master branches.
  2. Same as above.
  3. Changes that occurred on the master branch since when the topic branch was started off it.

git difftool

设置方法请search,或查看《Git聊天入门》

git branch

Focal Point

git branch 查看所有分支
git branch -v 查看所有分支,和当前最新的commit
git branch -vv 查看所有分支,和当前最新的commit
和upstream
git branch xyz 创建 xyz 分支
git branch -d xyz 删除 xyz 分支,如果分支尚未合入主干
或upstream,则失败
git branch -D xyz 删除 xyz 分支,强制

branch is ref

  • tag 可以理解为仅是指针
  • branch 不仅仅是指针,还包括向前追溯的一串节点信息

Practice

查看某 branch 内commit的关系

Practice

查看所有 branch 的commit的关系

Practice

查看某个 commit 所属的 branch

git checkout

原理图

git fetch/pull/push

原理图

git merge

Focal Point

  • 不必从干净的工作目录开始合并
  • 但劝你最好从干净的工作目录开始合并,除非你想把自己搞晕
  • merge 前做好解决冲突的心理准备
  • merge 前看清楚当前所处的 branch

合并冲突

步骤:

  1. git merge rev //糟糕,冲突了
  2. git diff //看看啥冲突,此时的 git diff 和平常的稍有不同
  3. vi conflictFile 或 git mergetool //解决冲突,最后记得删掉各种标记符号
  4. git add //重新add
  5. git commit //里面会有 merge 的提示

Practice

演示合并冲突、及解决

合并策略

  • 退化合并
    • already up-to-date
    • fast-forward
  • 常规合并
    • resolve :两分支合并
    • recursive :两分支,但多个合并基础的合并
    • octopus :多分支合并
  • 特殊合并
    • ours
    • subtree


完整的策略列表: git help merge – 搜索 MERGE STRATEGIES

合并策略的选择

  • git会根据用户的merge命令参数自动决定使用哪种策略
  • 用户也可以 -s strategy 指定策略 —— 慎重
    • git merge -s resolve …
    • git merge -s ours …
    • git merge -s subtree …
    • git merge –no-ff

Git 进阶

wkevin’s cheatsheet

git remote

git reset

原理图

git rebase

Git Object

Git 生态

Git 托管平台

Github Vs Gitlab

托管平台扩展的SCM

fork、PR

基于托管平台的CI

Github Actions



Creating a new GitHub Action

Gitlab CI & Gitlab Runner

  • Multi-platform
  • Multi-language
  • Stable
  • Parallel builds
  • Realtime logging
  • Flexible pipelines
  • Versioned pipelines
  • Autoscaling
  • Build artifacts
  • Docker support
  • Container Registry
  • Protected variables
  • Environments

Git Workflow

工作流是一种约定

  • 工作流是软件团队成员之间的约定
  • 约定内容包括:
    • 对分支的定义
    • 对合并触发时机的定义
    • 对repo的分布、fork的定义
    • repo的人员分工的定义
    • 对权限的约定:
      • git的分布式特性让“一个领导或管理员统管权限”变得无法操作
      • 可以适当运用gitlab等软件来约束权限,但它并不能解决所有问题

工作流因团队而异

  • 不同的团队需要根据人员(能力、规模)、时间、发布策略等制定不同的工作流
    • 单机工作流
    • 小团队工作流
    • 分布式工作流
  • 请在立项阶段就考虑 git 的工作流
  • 可以在《版本构建说明》中详细描述本团队的工作流
  • 请在每个sprint都审视工作流是否合适、运转正常

长期分支~特性分支

  • 建议:
    • 不要为团队只定义一个master分支做长期分支
    • 请至少定义出这样几个长期分支:
      • 稳定、随时可发布的长期分支
      • 较稳定、供二次开发者或VIP用户使用的长期分支
      • 较稳定、供团队合并特性分支的长期分支
      • 不稳定的前沿长期分支
    • 特性分支的使用

Centralized Workflow
集中式工作流

Integration-Manager Workflow
集成管理者工作流

Dictator and Lieutenants Workflow
司令官与副官工作流

github/gitlab 的管理方式

Understanding the GitHub Flow

最后

几点建议

  • 用命令行,远离GUI
  • 用简文本,尽量抛弃word、excel、powerpoint等富文本
  • 扬Git之开源、共享精神
  • 开胸怀、学习新知识
  • git和svn是可以共存的,不要一刀切

End

Thank you!