GIT三剑客
01-课程综述
一、Git综述
1、VCS出现前的状况
- 用目录拷贝区别不同版本
- 公共文件容易被覆盖
- 成员沟通成本很高,代码集成效率低下
2、集中式VCS(SVN)
- 有集中的版本管理服务器
- 具备文件版本管理和分支管理能力
- 集成效率有明显地提高
- 客户端必须时刻和服务器相连

3、分布式VCS(Git、Github、Gitlab)
- 服务端和客户端都有完整的版本库
- 脱离服务端、客户端照样可以管理版本
- 查看历史和版本比较等多数操作,都不需要访问服务器,比集中式VCS更能提高版本管理效率
4、Git的特点
- 最优的存储能力
- 非凡的性能
- 开源的
- 很容易做备份
- 支持离线操作
- 很容易定制工作流程
02-安装git
1、Git官方文档地址:
https://git-scm.com/book/zh/v2
2、macOS 平台 Git 下载地址:
https://git-scm.com/download/mac
3、Windows 平台 Git 下载地址:
https://git-scm.com/download/win
4、Linux 平台 Git 下载地址:
https://git-scm.com/download/linux
5、检查安装结果
git --version ## 通过执行该命令,看git是否返回版本信息
03-使用git之前需要做的最小化配置
1.配置user.name和user.email
$ git config --global user.name 'your_name' $ git config --global user.email 'your_email@domain.com'
2.git config命令的三个作用域(缺省等同于local)
$ git config --local ## local只对某个仓库有效 $ git config --global ## global对当前用户所有仓库有效 $ git config --system ## system对系统所有登录的用户有效
3.查看config配置,加--list
$ git config --list $ git config --list --global $ git config --list --system $ git config --list --local
4.清除config配置,加--unset
$ git config --unset --global user.name $ git config --unset --system user.name $ git config --unset --local user.name
local、global、system的优先级:local > global > system
04-创建第一个仓库并配置local用户信息
两种方式
1.用Git之前,已经存在项目代码
$ cd 项目代码所在的文件夹 $ git init
2.用Git之前,还不存在项目代码
cd 某个文件夹 git init your_project #会在当前路径下创建和项目名称同名的文件夹,里面有个裸仓库.git cd your_project 创建local user #此时global的配置信息无效,因为local用户的优先级较高 vim readme #新建readme文件 git add readme #文件从“工作目录”存到“暂存区”;此步骤后文件将被Git系统持续追踪 git status #查看工作区的当前状态 git commit -m 'Add readme' #提交变更,-m参数为变更说明 git log #显示提交记录(包括变更说明信息),此时会显示提交修改的用户名和邮箱地址均为local user
向Git仓库中添加文件
$ git add file_name ## file_name表示你的文件的名字 $ git add file_name1 file_name2 file_name3 ## 添加多个文件 $ git add -u ## -u 代表update,此命令针对已经被Git跟踪的文件,可以一起提交到暂存区,无需给出具体文件名 $ git add . ## 添加该目录下的全部文件
05-通过几个commit来认识工作区和暂存区
Git仓库中工作区、暂存区、版本历史的关系
06-给文件重命名的简便方法
1. 传统方法(需要三步命令)
(1)mv readme readme.md //git status 输出:删除了“readme”文件,并且存在未追踪(untracked)文件readme.md
(2)git add readme.md
(3)git rm readme //git status 输出:暂存区需要提交的改变为“将readme重命名为readme.md” (智能识别出重命名的目的)
注:
git reset --hard //不想保留刚刚的操作,清楚暂存区和工作区中的所有变更(危险操作,需谨慎)
git status 输出:nothing to commit, working tree clean;此时git log的历史记录与操作前一致
2. 便捷方式(一步到位)
(1)git mv readme readme.md //git status 输出:暂存区需要提交的改变为“将readme重命名为readme.md”
(2)git commit -m 'Move readme to reame.md' //git log查看新增加的操作记录
07-通过git log查看版本演变历史
版本历史命令 git log //git help log 打开log帮助文档,添加--web参数则在浏览器中显示
(1)git log --oneline //查看单行的简洁历史
git log --oneline branch_name ## 查看branch_name分支的日志
git log --graph ## 图形化显示
git log branch_name ## 查看branch_name分支的日志
(2)git log -n4 //查看最近的4条历史(可与--oneline组合使用:git log -n4 --oneline),4可变
(3)git branch -v //查看本地有多少分支
(4)git checkout -b temp //创建新分支temp,并切换到分支temp
(5)git commit -am '...' //直接将工作区内容提交,跳过"git add"
(6)git log //默认只显示当前分支的历史(如:head->temp)
(7)git log --all //显示所有分支的历史
(8)git log --all --graph //图示化显示分支历史
注:上述参数可自由组合
补充:Tag标签
显示已有标签
git tag
新建标签
创建一个含附注类型的标签非常简单,用 -a (译注:取 annotated 的首字母)指定标签名字即可
git tag -a tag_name -m 'Some Messages'
删除标签
删除本地标签:
git tag -d tag_name
删除remote
标签 :
git push --delete origin tag_name
推送标签到github 将本地所有标签推送到remote
:
git push origin --tags
08-gitk:通过图形界面工具查看版本历史
https://www.jianshu.com/p/01e4b27bd293
(1)命令行输入gitk
(2)gitk 文件的路径 //查看单个文件的修改历史的具体内容
(3)某次变更有:作者(author)、提交者(commiter)两类属性,可不同
(4)通过“view”菜单定制显示内容
09-探秘.git目录
查看.git
文件夹下的内容:
ls .git/ -al
如下:
drwxr-xr-x 1 Andy 197609 0 12月 17 22:38 ./ drwxr-xr-x 1 Andy 197609 0 12月 17 21:50 ../ -rw-r--r-- 1 Andy 197609 7 12月 17 22:38 COMMIT_EDITMSG -rw-r--r-- 1 Andy 197609 301 12月 12 22:55 config -rw-r--r-- 1 Andy 197609 73 12月 12 22:55 description -rw-r--r-- 1 Andy 197609 96 12月 19 00:00 FETCH_HEAD -rw-r--r-- 1 Andy 197609 23 12月 12 22:55 HEAD drwxr-xr-x 1 Andy 197609 0 12月 12 22:55 hooks/ -rw-r--r-- 1 Andy 197609 249 12月 17 22:38 index drwxr-xr-x 1 Andy 197609 0 12月 12 22:55 info/ drwxr-xr-x 1 Andy 197609 0 12月 12 22:55 logs/ drwxr-xr-x 1 Andy 197609 0 12月 17 22:38 objects/ -rw-r--r-- 1 Andy 197609 114 12月 12 22:55 packed-refs drwxr-xr-x 1 Andy 197609 0 12月 12 22:55 refs/
命令
cat命令主要用来查看文件内容,创建文件,文件合并,追加文件内容等功能。 cat HEAD 查看HEAD文件的内容 git cat-file 命令 显示版本库对象的内容、类型及大小信息。 git cat-file -t b44dd71d62a5a8ed3 显示版本库对象的类型 git cat-file -s b44dd71d62a5a8ed3 显示版本库对象的大小 git cat-file -p b44dd71d62a5a8ed3 显示版本库对象的内容
.git
里几个常用的如下:
HEAD:指向当前的工作路径 config:存放本地仓库(local)相关的配置信息。 refs/heads: 存放分支 refs/heads/master/: 指向master分支最后一次commit refs/tags: 存放tag,又叫里程牌 (当这次commit是具有里程碑意义的 比如项目1.0的时候 就可以打tag) objects:核心文件,存储文件
.git/objects/ 存放所有的 git 对象,对象哈希值前 2 位作为文件夹名称,后 38 位作为对象文件名, 可通过 git cat-file -p 命令,拼接文件夹名称+文件名查看。
10-commit、tree和blob三个对象之间的关系
commit 此次提交信息的一个快照(也可以称作镜像)
tree 文件夹,就相当于目录。
blob 具体的某一个文件。 文件内容一样(不关心文件名),就是同一个blob。
类似于二叉树,一次commit,创建一棵大树,commit是root节点。该tree里面有具体的信息,可能有blob(文件)、tree(文件夹)。
【同学问题】 每次commit,git 都会将当前项目的所有文件夹及文件快照保存到objects目录,如果项目文件比较大,不断迭代,commit无数次后,objects目录中文件大小是不是会变得无限大?
【老师解答】 Git对于内容相同的文件只会存一个blob,不同的commit的区别是commit、tree和有差异的blob,多数未变更的文件对应的blob都是相同的,这么设计对于版本管理系统来说可以省很多存储空间。其次,Git还有增量存储的机制,我估计是对于差异很小的blob设计的吧。
11-小练习:数一数tree的个数
12-分离头指针的注意事项
分离头指针的应用场景:如果临时想基于某个commit做变更,试试新方案是否可行,就可以采用分离头指针的方式。测试后发现新方案不成熟,直接reset回其他分支即可。省却了建、删分支的麻烦了。
当创建一个分离头指针的时候,在切换分支时,记得将分离头挂到一个分支上,不然基于分离头提交的commit容易丢失
$ git branch branch_name commit_id
git checkout hash值
写代码时,要注意要在分支下开发,要不然有可能git会当做垃圾清除了。
detached HEAD
13-进一步理解HEAD和branch
HEAD可以指向当前分支,也可以指向commit
- git diff HEAD HEAD^^ (~和……代表的是父节点)
- git diff HEAD HEAD~2
- git diff hash hash
git checkout -b new_branch [具体分支 或 commit] 创建新分支并切换到新分支
git diff HEAD HEAD~1 比较最近两次提交
git diff HEAD HEAD~2 比较最近和倒数第三次提交
git diff HEAD HEAD^ 比较最近两次提交
git diff HEAD HEAD^^ 比较最近和倒数第三次提交
HEAD可以指向Branch的最新一次的提交,也可以指向Branch的某次提交(分离头状态)
- 一个节点,可以包含多个子节点(checkout 出多个分支)
- 一个节点可以有多个父节点(多个分支合并)
- ~和都是父节点,区别是跟随数字时候,2 是第二个父节点,而~2是父节点的父节点
- ~和^可以组合使用,例如 HEAD~2^2
$ git checkout -b branch_name commit_id ## 基于commit_id所在的提交,新建一个分支
14-怎么删除不需要的分支
查看分支
$ git branch $ git branch -a $ git branch -v $ git branch -av $ git branch -vv
删除分支命令
$ git branch -d branch_name $ git branch -D branch_name
使用-d 在删除前Git会判断在该分支上开发的功能是否被merge到其它分支。如果没有,不能删除。如果merge到其它分支,但之后又在其上做了开发,使用-d还是不能删除。-D会强制删除。
15-怎么修改最新commit的message
git commit --amend 对最近一次的commit信息进行修改
$ git commit -m '' ## 将缓存区的内容提交
16-怎么修改老旧commit的message
$ git rebase -i commit_id ## 该commit_id是我们要修改的那个commit的父commit,或者说是我们要修改的那个commit的上一个commit的id
接下来就是一个交互过程...
这期间会产生一个detached HEAD,然后将改好的commit指向该detached HEAD,如下图所示:
git rebase工作的过程中,就是用了分离头指针。rebase意味着基于新base的commit来变更部分commits。它处理的时候,把HEAD指向base的commit,此时如果该commit没有对应branch,就处于分离头指针的状态,然后重新一个一个生成新的commit,当rebase创建完最后一个commit后,结束分离头状态,Git让变完基的分支名指向HEAD。
17-怎样把连续的多个commit整理成1个
$ git rebase -i 开始commit [结束commit]
如果没有指定 结束commit,那么结束commit 默认为当前分支最新的 commit,那么rebase 结束后会自动更新当前分支指向的 commit,
如果指定了结束 commit,而且结束 commit不是当前分支最新的 commit,那么rebase 后会有生成一个 游离的 head,,而且当前分支指向的commit 不会更新
18-怎么把间隔的几个commit整理成1个
$ git diff --cached
19-怎么比较暂存区和HEAD所含文件的差异
$ git diff
20-怎么比较工作区和暂存区所含文件的差异
21-如何让暂存区恢复成和HEAD一样
$ git reset HEAD ## 恢复所有文件 $ git reset HEAD -- file_name1 file_name2 ## 恢复指定文件
22-如何让工作区的文件恢复为和暂存区一样
$ git checkout $ git checkout -- file_name
23-怎样取消暂存区部分文件的更改
24-消除最近的几次提交
$ git reset --hard commit_id
25-看看不同提交的指定文件的差异
26-正确删除文件的方法
删除文件
$ git rm filename ## 删除工作区中的文件 $ git rm --cached filename ## 删除暂存区中的文件
27-开发中临时加塞了紧急任务怎么处理
将现在工作区的内容存进stash
$ git stash stash_name
将stash中的内容放回工作区
$ git stash apply ## apply这种方式,即使将内容放回工作区后,也不会删除stash中的内容 $ git stash pop ## pop这种方式,是将内容放回工作区后,同时也将stash中的内容删除
28-如何指定不需要Git管理的文件
29-如何将Git仓库备份到本地
克隆一个裸仓库(裸仓库对代码平台的意义很大)
裸仓库就是只有.git 没有work、tree的仓库
$ git clone --bare path name ## path表示要克隆的仓库的路径,name表示克隆下来的新仓库的名字
克隆一个带工作空间的仓库
$ git clone url
仓库分为本地仓库、本地远程仓库和远程仓库
30-注册一个GitHub账号
31-配置公私钥
32-在GitHub上创建个人仓库
33-把本地仓库同步到GitHub
第四章 Git多人单分支集成协作时的常见常见
参考:
https://github.com/aimuch/iGit
https://juejin.im/post/5c7b4e3b518825620677ed22
https://www.atlassian.com/git/tutorials