工程专题-Git学习之旅
什么是版本控制系统(VCS)
版本控制:最基本功能
中央式版本控制系统
git status HEAD、master 与 branchHEAD:当前 commit 的引用
branch:对commit的引用
git commit
git log
master: 默认 branch
master` ,其实是一个特殊的 `branch`:它是 Git 的默认 `branch
所谓的「默认 branch」,主要有两个特点:
-
新创建的 repository(仓库)是没有任何
commit
的。但在它创建第一个commit
时,会把master
指向它,并把HEAD
指向master
。 -
当有人使用
git clone
时,除了从远程仓库把.git
这个仓库目录下载到工作目录中,还会checkout
(签出)master
(checkout
的意思就是把某个commit
作为当前commit
,把HEAD
移动过去,并把工作目录的文件内容替换成这个commit
所对应的内容)。
branch 的通俗化理解
branch
理解为从初始 commit
到 branch
所指向的 commit
之间的所有 commit
s 的一个「串」。例如下面这张图:
bramch的理解
1.所有的 branch
之间都是平等的。
- branch
包含了从初始
commit` 到它的所有路径,而不是一条路径。并且,这些路径之间也是彼此平等的。
git checkout -b feature1
…
git commit
git checkout master
…
git commit
删除 branch
git branch -d feature1
需要说明的有两点:
-
HEAD
指向的branch
不能删除。如果要删除HEAD
指向的branch
,需要先用checkout
把HEAD
指向其他地方。 -
由于 Git 中的
branch
只是一个引用,所以删除branch
的操作也只会删掉这个引用,并不会删除任何的commit
。(不过如果一个commit
不在任何一个branch
的「路径」上,或者换句话说,如果没有任何一个branch
可以回溯到这条commit
(也许可以称为野生commit
?),那么在一定时间后,它会被 Git 的回收机制删除掉。) -
出于安全考虑,没有被合并到
master
过的branch
在删除时会失败(因为怕你误删掉「未完成」的branch
啊):引用」的本质
所谓「引用」(reference),其实就是一个个的字符串。这个字符串可以是一个
commit
的 SHA-1 码(例:c08de9a
),也可以是一个branch
(例:`ref: refs/heads/xxx)。Git 中的
HEAD
和每一个branch
以及其他的引用,都是以文本文件的形式存储在本地仓库.git
目录中,而 Git 在工作的时候,就是通过这些文本文件的内容来判断这些所谓的「引用」是指向谁的。
实质上,push
做的事是:把当前 branch
的位置(即它指向哪个 commit
)上传到远端仓库,并把它的路径上的 commit
s 一并上传。
git checkout feature1
git push origin feature1
它做的事也是合并:指定一个 commit
,把它合并到当前的 commit
来
git merge branch1
merge
有什么用
-
合并分支
当一个
branch
的开发已经完成,需要把内容合并回去时,用merge
来进行合并。 -
pull
的内部操作之前说过,
pull
的实际操作其实是把远端仓库的内容用fetch
取下来之后,用merge
来合并。
冲突
- 解决掉冲突
- 手动
commit
一下
HEAD 落后于 目标 commit——fast-forward
git merge feature1
git log在 Git 中,有两个「偏移符号」: ^
和 ~
。
^
的用法:在 commit
的后面加一个或多个 ^
号,可以把 commit
往回偏移,偏移的数量是 ^
的数量。例如:master^
表示 master
指向的 commit
之前的那个 commit
; HEAD^^
表示 HEAD
所指向的 commit
往前数两个 commit
。
~` 的用法:在 `commit` 的后面加上 `~` 号和一个数,可以把 `commit` 往回偏移,偏移的数量是 `~` 号后面的数。例如:`HEAD~5` 表示 `HEAD` 指向的 `commit`往前数 5 个 `commit
- 查看历史中的多个commit:log
- 查看详细改动:
git log -p
- 查看大致改动:
git log --stat
- 查看详细改动:
- 查看具体某个commit: show
- 要看最新
commit
,直接输入git show
;要看指定commit
,输入git show commit的引用或SHA-1
- 如果还要指定文件,在
git show
的最后加上文件名
- 要看最新
- 查看未提交的内容:diff
- 查看暂存区和上一条
commit
的区别:git diff --staged
(或--cached
) - 查看工作目录和暂存区的区别:
git diff
不加选项参数 - 查看工作目录和上一条
commit
的区别:git diff HEAD
- 查看暂存区和上一条
git merge branch1
git checkout branch1
git rebase master
commit -—amend
reset --hard 丢弃最新的提交
git reset --hard HEAD^
git rebase --onto 目标 commit
起点 commit
终点 commit
git rebase --onto 第3个commit 第4个commit branch1
reset 的本质移动 HEAD 以及它所指向的 branch
git reset --hard branch2
reset --hard & reset --soft & reset 不加参数
--hard
:重置位置的同时,清空工作目录的所有改动;--soft
:重置位置的同时,保留工作目录和暂存区的内容,并把重置HEAD
的位置所导致的新的文件差异放进暂存区。--mixed
(默认):重置位置的同时,保留工作目录的内容,并清空暂存区。
git checkout branch2
git checkout branch名
的本质,其实是把 HEAD
指向指定的 branch
,然后签出这个 branch
所对应的 commit
的工作目录
checkout 和 reset 的不同
checkout
和 reset
都可以切换 HEAD
的位置,它们除了有许多细节的差异外,最大的区别在于:reset
在移动 HEAD
时会带着它所指向的 branch
一起移动,而 checkout
不会
stash:临时存放工作目录的改动
git stash
git stash pop
git stash -u
reflog
一张图总结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 文件的状态
- 新建一个文件,该文件处于 Untracked 状态
- 通过git add命令添加到缓存区,此时文件处于Tracked状态又或者说 此时这个文件已经被版本控制系统所跟踪,而且他处于Staged(暂存)状态
- 通过git commit命令把暂存区的文件提交提交到本地仓库,此时文件 处于Unmodified(未修改)状态
- 此时如果去编辑这个文件,文件又会变成Modified(修改)状态
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代码示例
- 创建dev分支
- 开始新Feature分支开发
- 完成Feature
- 开始Relase
- 完成Release
- 开始Hotfix
- 完成Hotfix
我们知道常用的命令:
git的本地库,暂存区,与工作区流程图:
再来一张图回忆一下常用命令:
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
团队开发的规范:
当然每个公司可能制度不一样,总得来说,有master主分支,这个分支我们一般不会在上面修改改代码。
比如我们要开发出一个电商系统,需要有支付模块和订单模块,那就从develop分支拉取代码,分别创建feature1和feature2来实现这两块功能,然后合并到test测试分支,没有问题将主分支与版本分支(打标签)合并,完整功能上线!