工程专题-Git学习之旅

 

什么是版本控制系统(VCS)

版本控制:最基本功能

中央式版本控制系统

工程专题-Git学习之旅_版本控制系统

git status HEAD、master 与 branch

HEAD:当前 commit 的引用

branch:对commit的引用

git commit

工程专题-Git学习之旅_暂存区_02

git log

master: 默认 branch

master` ,其实是一个特殊的 `branch`:它是 Git 的默认 `branch

所谓的「默认 branch」,主要有两个特点:

  1. 新创建的 repository(仓库)是没有任何 commit 的。但在它创建第一个 commit 时,会把 master 指向它,并把 HEAD 指向 master

    工程专题-Git学习之旅_git_03

  2. 当有人使用 git clone 时,除了从远程仓库把 .git 这个仓库目录下载到工作目录中,还会 checkout (签出) mastercheckout 的意思就是把某个 commit 作为当前 commit,把 HEAD 移动过去,并把工作目录的文件内容替换成这个 commit 所对应的内容)。

工程专题-Git学习之旅_暂存区_04

branch 的通俗化理解

branch 理解为从初始 commitbranch 所指向的 commit 之间的所有 commits 的一个「串」。例如下面这张图:

工程专题-Git学习之旅_重置_05

bramch的理解

1.所有的 branch 之间都是平等的。

工程专题-Git学习之旅_版本控制系统_06

  1. branch包含了从初始commit` 到它的所有路径,而不是一条路径。并且,这些路径之间也是彼此平等的。

工程专题-Git学习之旅_重置_07

git checkout -b feature1

git commit

工程专题-Git学习之旅_版本控制系统_08

git checkout master

git commit

工程专题-Git学习之旅_版本控制系统_09

删除 branch

git branch -d feature1

工程专题-Git学习之旅_git_10

需要说明的有两点:

  1. HEAD 指向的 branch 不能删除。如果要删除 HEAD 指向的 branch,需要先用 checkoutHEAD 指向其他地方。

  2. 由于 Git 中的 branch 只是一个引用,所以删除 branch 的操作也只会删掉这个引用,并不会删除任何的 commit。(不过如果一个 commit 不在任何一个 branch 的「路径」上,或者换句话说,如果没有任何一个 branch 可以回溯到这条 commit(也许可以称为野生 commit?),那么在一定时间后,它会被 Git 的回收机制删除掉。)

  3. 出于安全考虑,没有被合并到 master 过的 branch 在删除时会失败(因为怕你误删掉「未完成」的 branch 啊):

    引用」的本质

    所谓「引用」(reference),其实就是一个个的字符串。这个字符串可以是一个 commit 的 SHA-1 码(例:c08de9a),也可以是一个 branch(例:`ref: refs/heads/xxx)。

    Git 中的 HEAD 和每一个 branch 以及其他的引用,都是以文本文件的形式存储在本地仓库 .git 目录中,而 Git 在工作的时候,就是通过这些文本文件的内容来判断这些所谓的「引用」是指向谁的。

push 的本质

实质上,push 做的事是:把当前 branch 的位置(即它指向哪个 commit)上传到远端仓库,并把它的路径上的 commits 一并上传。

工程专题-Git学习之旅_版本控制系统_11

feature1提交

git checkout feature1
git push origin feature1

工程专题-Git学习之旅_重置_12

merge:合并 commits

它做的事也是合并:指定一个 commit,把它合并到当前的 commit

git merge branch1

工程专题-Git学习之旅_版本控制系统_13

merge 有什么用

  1. 合并分支

    当一个 branch 的开发已经完成,需要把内容合并回去时,用 merge 来进行合并。

  2. pull 的内部操作

    之前说过,pull 的实际操作其实是把远端仓库的内容用 fetch 取下来之后,用 merge 来合并。

冲突

  1. 解决掉冲突
  2. 手动 commit 一下

HEAD 落后于 目标 commit——fast-forward

git merge feature1

工程专题-Git学习之旅_暂存区_14

工程专题-Git学习之旅_重置_15

git log

在 Git 中,有两个「偏移符号」: ^~

^ 的用法:在 commit 的后面加一个或多个 ^ 号,可以把 commit 往回偏移,偏移的数量是 ^ 的数量。例如:master^ 表示 master 指向的 commit 之前的那个 commitHEAD^^ 表示 HEAD 所指向的 commit 往前数两个 commit

~` 的用法:在 `commit` 的后面加上 `~` 号和一个数,可以把 `commit` 往回偏移,偏移的数量是 `~` 号后面的数。例如:`HEAD~5` 表示 `HEAD` 指向的 `commit`往前数 5 个 `commit
  1. 查看历史中的多个commit:log
    1. 查看详细改动: git log -p
    2. 查看大致改动:git log --stat
  2. 查看具体某个commit: show
    1. 要看最新 commit ,直接输入 git show ;要看指定 commit ,输入 git show commit的引用或SHA-1
    2. 如果还要指定文件,在 git show 的最后加上文件名
  3. 查看未提交的内容:diff
    1. 查看暂存区和上一条 commit 的区别:git diff --staged(或 --cached
    2. 查看工作目录和暂存区的区别:git diff 不加选项参数
    3. 查看工作目录和上一条 commit 的区别:git diff HEAD
rebase

git merge branch1

工程专题-Git学习之旅_暂存区_16

git checkout branch1
git rebase master

工程专题-Git学习之旅_暂存区_17

commit -—amend

工程专题-Git学习之旅_版本控制系统_18

reset --hard 丢弃最新的提交

工程专题-Git学习之旅_暂存区_19

git reset --hard HEAD^

工程专题-Git学习之旅_重置_20

git rebase --onto 目标 commit 起点 commit 终点 commit

git rebase --onto 第3个commit 第4个commit branch1

工程专题-Git学习之旅_工程专题_21

reset 的本质

移动 HEAD 以及它所指向的 branch

git reset --hard branch2

工程专题-Git学习之旅_版本控制系统_22

reset --hard & reset --soft & reset 不加参数

  1. --hard:重置位置的同时,清空工作目录的所有改动;
  2. --soft:重置位置的同时,保留工作目录和暂存区的内容,并把重置 HEAD 的位置所导致的新的文件差异放进暂存区。
  3. --mixed(默认):重置位置的同时,保留工作目录的内容,并清空暂存区。
checkout 的本质

git checkout branch2

工程专题-Git学习之旅_暂存区_23

git checkout branch名 的本质,其实是把 HEAD 指向指定的 branch,然后签出这个 branch 所对应的 commit 的工作目录

checkout 和 reset 的不同

checkoutreset 都可以切换 HEAD 的位置,它们除了有许多细节的差异外,最大的区别在于:reset 在移动 HEAD 时会带着它所指向的 branch 一起移动,而 checkout 不会

stash:临时存放工作目录的改动

git stash

git stash pop

git stash -u

reflog

工程专题-Git学习之旅_暂存区_24

一张图总结git常用的命令!
工程专题-Git学习之旅_暂存区_25

.git目录

config
HEAD
index
objects

用户信息

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

git config --list

~/.gitconig
工程专题-Git学习之旅_重置_26
工程专题-Git学习之旅_版本控制系统_27
git 文件的状态

  1. 新建一个文件,该文件处于 Untracked 状态
  2. 通过git add命令添加到缓存区,此时文件处于Tracked状态又或者说 此时这个文件已经被版本控制系统所跟踪,而且他处于Staged(暂存)状态
  3. 通过git commit命令把暂存区的文件提交提交到本地仓库,此时文件 处于Unmodified(未修改)状态
  4. 此时如果去编辑这个文件,文件又会变成Modified(修改)状态
Git中对象类型

blob对象

blob对象就是单纯存储数据

tree对象

像一个目录,管理一些“tree”对象或是“blob”对象

commit对象

“commit”对象指向一个“tree对象”

tag对象

一个“tag”对象包括一个对象名(SHA1签名)、对象类型、标签名、标签创建人的名字(“tagger”), 还有一条可能包含有签名(signature)的消息

跟踪新文件

git add README 
git status

暂存已修改文件
查看已暂存和未暂存的修改

git diff
git diff --staged

移除文件

git rm
git rm --cached

查看提交历史

git log

一个常用的选项是,用来显示每次提交的内容差异。 你也可以加上来仅显示最近两次提交:

git log -p -2 git log --stat
git log --pretty=oneline
git log --pretty=format:"%h - %an, %ar : %s"

撤消操作

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 选项的提交命令尝试重新提交:

git commit --amend

取消暂存的文件

git reset

撤消对文件的修改

git checkout -- filename

查看远程仓库

git clone https://github.com/schacon/ticgit
 git remote -v

列出标签

git tag
git tag -l 'v1.8.5*'

创建标签

git tag -a v1.4 -m 'my version 1.4'

本地分支

1.分支概念
提交记录串成的时间线,默认初始创建的分支(时间线) —— master分支, 如果不切换到其他分支上,每次commit生成的快照都会串在这条分支上! 另外还有个 —— HEAD指针,该指针指向正在工作的本地分支,前面的版 本回退其实修改的就是这个HEAD指针的指向!
分支简介

git add README test.rb LICENSE
git commit -m 'The initial commit of my project'

新建分支

git add README test.rb LICENSE
git commit -m 'The initial commit of my project'

git merge git rebase

git reset 与 git checkout 差异

git分支命名规范

开发阶段

开发新需求都从master拉取feature分支,不同迭代发布代码使用不同的分支,避免相互影响。 需要进行开发环境联调的代码合并到develop分支,由jenkins自动发布到开发环境。
命名方式:dev-mmdd(时间)-需求名称,例如:dev-1205-xxxx

测试阶段

每月为一个迭代周期由系统owner拉取提测分支test,并定期维护(merge master)。开发feature分支合并到提测test分支,合并前需要由模块负责人进行review或交叉review。
多个feature分支在测试过程中,需要借助release分支来进行合并,然后进行提测。
多个feature分支在测试过程中,某一个需求不能如期发布,需要将release分支删除,讲课继续的分支重复执行第2部进行测试验证。
命名方式:test-mmdd(每月10日),例如:test-1215/ release-mmdd(每月10日),例如:release-1210

发布阶段

测试通过后release进行merge master,并解决冲突,在release分支回归测试
回归测试后,现在master分支拉取tag分支备份,然后把release合并到master
发布到master
命名方式:tag-mmdd(时间),例如:tag-1212

git flow代码示例

  1. 创建dev分支
    工程专题-Git学习之旅_暂存区_28
  2. 开始新Feature分支开发
    工程专题-Git学习之旅_暂存区_29
  3. 完成Feature
    工程专题-Git学习之旅_版本控制系统_30
  4. 开始Relase
    工程专题-Git学习之旅_工程专题_31
  5. 完成Release
    工程专题-Git学习之旅_工程专题_32
  6. 开始Hotfix
    工程专题-Git学习之旅_重置_33
  7. 完成Hotfix
    工程专题-Git学习之旅_版本控制系统_34
git使用场景

工程专题-Git学习之旅_重置_35
我们知道常用的命令:
工程专题-Git学习之旅_git_36
git的本地库,暂存区,与工作区流程图:
工程专题-Git学习之旅_版本控制系统_37
再来一张图回忆一下常用命令:
工程专题-Git学习之旅_暂存区_38

git flow

GitFlow流程常用分支

  • Production 分支

也就是我们经常使用的Master分支,这个分支最近发布到生产环境的代码,最近发布的Release, 这个分支只能从
其他分支合并,不能在这个分支直接修改

  • Develop 分支

这个分支是我们是我们的主开发分支,包含所有要发布到下一个Release的代码,这个主要合并与其他分支,比如
Feature分支

  • Feature 分支

这个分支主要是用来开发一个新的功能,一旦开发完成,我们合并回Develop分支进入下一个Release

  • Release分支

当你需要一个发布一个新Release的时候,我们基于Develop分支创建一个Release分支,完成Release后,我们合
并到Master和Develop分支

  • Hotfix分支

当我们在Production发现新的Bug时候,我们需要创建一个Hotfix, 完成Hotfix后,我们合并回Master和Develop分
支,所以Hotfix的改动会进入下一个Release
工程专题-Git学习之旅_git_39

团队开发的规范:
当然每个公司可能制度不一样,总得来说,有master主分支,这个分支我们一般不会在上面修改改代码。
比如我们要开发出一个电商系统,需要有支付模块和订单模块,那就从develop分支拉取代码,分别创建feature1和feature2来实现这两块功能,然后合并到test测试分支,没有问题将主分支与版本分支(打标签)合并,完整功能上线!
工程专题-Git学习之旅_暂存区_40