一、Git的基本概念:
(一)版本控制工具的分类
- 本地版本控制系统:rcs
- 集中化的版本控制系统:cvs, svn
- 分布式的版本控制系统:bitkeeper, Git
(二)Git的工作目录分类
- 工作区:Working Directory,工作目录中除.git目录外的部分
- 暂存区:Staging Area,索引对象
- 版本库:Repository,对象库
(三)Git配置文件:git config
- 仓库特有:REPO/.git/config
- 用户全局:~/.gitconfig, --global
- 系统:/etc/git/gitconfig, -system
(四)Git的对象类型: .git/objects
- 块(blob)对象:文件的每个版本表现为一个块(blob)
- 树(tree)对象:一个目录代表一层目录信息
- 提交(commit)对象:用于保存版本库一次变化的元数据,包括作者、邮箱、提交日期、日志;每个提交对象都指定一个目录树对象
- 标签(tag)对象:用于给一个特定对象一个易读的名称
(五)Git中的文件分类:分为三类
- 已追踪的(tracked):已经在版本库中,或者已经使用git add命令添加至索引中的文件
- 被忽略的(Igored):在版本库中通过“忽略文件列表”明确声明为被忽略的文件
- 未追踪的(untracked):上述两类之外的其它文件
二、Git基础操作:暂存、提交
(一)add/rm/mv命令:
git add:暂存文件,添加至索引
git ls-files:
默认显示索引中的文件列表的原始文件名
-s:显示暂存的文件信息:权限、对象名、暂存号及原始文件名
-o:显示未被追踪的文件git rm:
git rm:删除工作目录中的文件,及索引中的映射
git rm --cached:只删除索引中的映射git mv:
git mv:改变工作目录中的文件名,及索引中的映射
(二)提交相关的命令:
git commit:提交至版本库
git log:查看提交日志
提交的标识:
引用:reference, SHA1, 绝对提交名
符号引用:symbolic reference
refs/heads/REF:本地特性分支名称
refs/remotes/REF:远程跟踪分支名称
refs/tags/REF:标签名Git会自动维护几个特定目的的特殊符号引用:
HEAD:始终指向当前分支的最近提交;或检出到其它分支时,目标分支的最近提交
ORIG_HEAD:合并操作时,新生成的提交前面的那一个提交保存于此引用中
FETCHED_HEAD:指向着目前已经从远程仓库取下来的分支的最近提交
MERGE_HEAD:合并操作时,其它分支的上一次提交git diff:比较提交、索引及工作目录
git reset:撤消此前的操作
--soft:将HEAD引用指向给定的提交,但不影响索引和工作目录
--mixed:将HEAD引用指向给定的提交,并将索引内容改变为指定提交的快照;但不改变工作目录
--hard:将HEAD引用指向给定的提交、将索引内容改变为指定提交的快照,并改变工作目录中的内容反映指定提交的内容-
实验1:Git的基础操作举例
- 建立目录,Git初始化本目录,在本目录下建立.git的隐藏目录
mkdir -pv testapp/examples cd testapp/ git init tree .git/
上图展现了git目录结构,主要包含:
branches:分支信息
HEAD:指向当前分支的指针
objects:Git对象
refs:引用每一次git add操作都会在.git/objects目录中产生blob对象文件
echo test line 1 > README git add README echo test line 2 >> README git add README tree .git/
- git add将变动文件存入暂存区后,git status可以提示当前的commit状态,并且查看上一次commit后变动的文件
echo test example line 1 > examples/example01 git add examples/example01 git status
- git commit后在.git/objects目录中新产生了很多commit对象文件
git commit -m "v 0.1" tree .git/
- git commit提交后,git status查看状态提示工作目录"clean";
git log查看commit历史,可以明确看到本次提交的对象文件名以及提交者、提交时间、提交摘要信息
git status git log
- git ls-files查看当前索引文件的原文件名信息
git ls-files git ls-files -s
至此,可以总结一下git commit后.git/objects目录下的对象文件内容:
0e---c52bcb201df969d28819ee5e67c0e817e35951
:
git add examples/example01产生的blob对象
1e---06d5b2a1a27e4f769348117e613ca0ddfa102f
:
第二次git add README产生的blob对象
3e---458f63a7d3d4a23a8cc4d5ddcff976eaaf02e6
:
git commit产生的tree对象
61---e358aa4aea526ce0b55bd6d1aaf266c2bf7cb3
:
第一次git add README产生的blob对象
ce---fefb13e8ae824aa4d59e464f4dae0a550b0dfd
:
git commit产生的tree对象
fe---3fc696f08c9488ac94070d284cbaf9e786205e
:
git commit产生的commit对象总结:
每一次git add操作都会产生blob对象
每一次git commit操作都会产生变动目录(从发生变动的文件所在目录至工作目录的所有层级目录)的tree对象,以及本次commit的commit对象
-
实验2:Git的撤销操作举例
- 修改README文件,git add添加至缓存区,git commit提交版本库
echo test line 3 >> README git add README git commit -m "v 0.2" git log
- soft模式撤销,可以看到git commit操作被撤销
git reset --soft fe3fc6 // 取目标对象文件名的前6位左右即可 git log
- 但是soft模式撤销下,blob对象没有撤销,文件的修改没有被撤销
git ls-files -s cat README
- 此时,只需执行git commit操作即可
git commit -m "v 0.2.1" git log
- mixed模式下的撤销不仅撤销了git commit操作,而且撤销了git add操作(注意两次git ls-files操作结果中README对应blob文件的变化),但文件的修改没有被撤销
git ls-files -s git reset --mixed fe3fc6 git log git ls-files -s cat README
- 此时,执行git add和git commit操作
git add README git commit -m "v 0.2.2" git log
- hard模式下的撤销将git commit, git add操作全部撤销,并且文件内容的修改也被撤销,故此模式危险性较大
git reset --hard fe3fc69 git log git ls-files -s cat README
注意,撤销操作并未真正删除blob, commit对象文件,只是将原来指向他们的指针指向命令指定的之前操作的位置
使用tree .git/命令查看此时的.git目录,发现之前git commit -m "v 0.2.2"时产生的commit对象82---ee06b08e0fb3dd3e3fcd8ecc30c289e38590bf和之前git add README产生的blob对象85---d402490f750fd3e2439e81aeb9f37b217b2705仍旧存在
- git的撤销操作只是指针的移动,不涉及对象文件的删除,故出现git层面无法恢复的误操作时,理论上还可以在文件层面尝试修复
三、Git分支:
分支命名法则:
可以使用/,但不能以/结尾
不能以-开头
以位于/后面的组件,不能以.开头
不能使用连续的...
不能使用空白字符
不能使用^, ~, ?, *,[等git分支操作基础命令
git branch BRANCH_NAME [START_COMMIT]:创建分支
git branch -d BRANCH_NAME:删除分支
git show-branch:查看分支及其相关的提交
git checkout <branch>:检出分支分支合并:
合并基础:要合并的分支的最近一次的共同提交
我们的版本:当前分支的最近一次提交
他们的版本:要合并进来的分支的最近一次提交无冲突合并:
$ git checkout master
$ git status
$ git merge BRANCH_NAME
$ git log --graph --pretty=oneline --abbrev-commit有冲突合并:
手动解决冲突后,重新git add, git commit变基操作:git rebase
$ git checkout dev
$ git rebase master
$ git checkout master
$ git merge -m "MSG"git merge(合并)与 git rebase(变基)的区别:
-
实验3:Git的分支管理举例
- 从commit: "v 0.2.3" 开始建立分支bugfix01,并进行了一次commit: "v 0.2.3.1"
echo test 4 >> README // 主分支上的操作 git branch bugfix01 // 建立分支bugfix01 git checkout bugfix01 // 检出分支bugfix01,转入分支bugfix01 echo test 5 >> README git add README git commit -m "v 0.2.3.1" git log
- 合并分支
git checkout master // 转入主分支 echo test example line 2 >> examples/example01 git add examples/example01 git commit -m "v 0.3" git merge bugfix01 // 合并分支 git log --graph --pretty=oneline --abbrev-commit cat README cat examples/example01
- 主分支最近一次commit: "v 0.3"
- 分支合并后的commit演进
- 可以看到主分支对examples/example01的改变和bugfix01分支对README的改变都在分支合并后得到了体现
四、Git分布式版本管理
Git服务器支持的协议类型:
本地协议(local)、HTTP/HTTPS协议、SSH协议、Git协议从Git服务器克隆操作:
git clone URL
-
URL格式:
- 本地协议:
/path/to/repo.git file:///path/to/repo.git
- Git协议:由git-daemon程序提供,监听在tcp的9418端口;仅支持“读”操作,无任何认证功能
git://host/path/to/repo.git git://host/~user/path/to/repo.git
- SSH协议
ssh://[USER@]host[:port]/path/to/repo.git ssh://[USER@]host[:port]/~USERNAME/path/to/repo.git
- HTTP/HTTPS协议:从1.6.6版开始支持智能http协议,支持读/写/认证
http://host/path/to/repo.git
五、引用远程版本库:
git remote命令:管理远程仓库
git fetch:取回远程服务器的更新
git pull:取回远程服务器更新,而后与本地的指定分支合并
git pull <远程主机名> <远程分支名>:<本地分支名>git push:将本地的更新推送到远程主机
git push <远程主机名> <本地分支名>:<远程分支名>-
实验4:实现克隆远程版本库至本地,在本地修改后推送更新至远程版本库
- 在github网站上注册账号,建立一个项目仓库"testapp1",可以自动为其生成一个README文件,并添加开源证书"Apache License 2.0"
- 在项目页的右上方"Clone or download"下,点击红框按钮将https网址复制下来作为git clone操作的URL
- 执行git clone操作将远程项目克隆至本地,对项目进行修改(文件的修改,git add,git commit等操作),并推送更新至远程项目
git clone https://github.com/hellopeiyang/testapp1.git // 从远程克隆项目至本地 cd testapp1/ echo "test line 1" > testfile // 创建一个新文件 git add testfile git commit -m "v 0.1" // 创建一个新commit git log // 为最近的commit: "v 0.1"建立一个标签"testapp-v0.1" git tag -a testapp-v0.1 -m "testapp-v0.1" 948a23 git tag --list ls .git/refs/tags/ // tag标签在.git目录中的位置 git push --tags origin master // 将本地项目推送至远程
- 在本地创建的commit: "v 0.1",可以为本次commit创建一个tag: "testapp-v0.1"
- 本地项目更新推送至远程,输入注册的账号和密码
- 远程项目成功获得更新,可以看到新增的文件testfile和最近的commit: "v 0.1"
-
实验5:利用GitLab搭建一个类似GitHub的平台,同样实现实验4的操作
- 在服务器主机上安装gitlab服务
rpm -ivh gitlab-ce-8.8.3-ce.0.el7.x86_64.rpm // 安装gitlab全自动安装包 gitlab-ctl reconfigure // 执行gitlab环境配置 gitlab-ctl start // 启动gitlab
- 浏览器登录服务器主机,自动进入管理员密码修改页面
- 要求注册账户,注册成功后进入管理页面,建立自己的项目testapp2
- 建立项目完成后,点击红框中按钮复制项目仓库http地址
- 克隆远程项目至本地,在本地就行修改,同步本地项目至远程,与实验4类似
git clone http://node0.hellopeiyang.com/morningpeiyang/testapp2.git cd testapp2 echo "test file 1" > testfile git add testfile git commit -m "v 0.1" git push origin master
- 此时远程项目已经获得了更新