0x00 前言
做CTF时遇见过.git源码泄露,但是由于不熟悉git命令,故开始学习
0x01 Git简介
Git作为一个出自Linus之手的分布式文件管理系统,可以有效、高速地处理从很小到非常大的项目版本管理 。
0x02 理论基础
你的本地仓库由 git 维护的三棵“树”组成。第一个是你的 工作目录,它持有实际文件;第二个是 缓存区(Index),它像个缓存区域,临时保存你的改动;最后是 HEAD,指向你最近一次提交后的结果。 
SVN记录的是每一次版本的变动 

而git是将每个版本独立保存 

三棵树:
(工作区域、暂存区域和本地仓库)

工作流程:
- 在工作目录中添加、修改文件 
- 将需要进行版本管理的文件放入暂存区域 
- 将暂存区域的文件提交到Git仓库 
所以文件拥有三种状态:
- 已修改(modified)
- 已暂存(staged)
- 已提交(commited)
0x03 相关命令
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | git init    创建项目
 git add README.md    添加文件至暂存区域
 
 git commit -m "add a readme file"   注释
 
 git status   查看状态
 
 git reset HEAD 将最近一次提交仓库的文件恢复到暂存区域
 
 git checkout -- FILE  将暂存区域的文件还原至工作区域
 
 git log     查看历史提交
 
 git show    显示各种类型的相关信息
 
 git clean    删除工作区未跟踪的文件
 
 git tag -a v1.1 -m "new tag"    创建一个标签,并且存放在/.git/refs/tags/1.1 中
 
 | 

回到过去
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | git rest --mixed HEAD~    (默认)---- 移动HEAD的指向,将其指向上一个快照
 ---- 将HEAD移动后指向的快照回滚到暂存区域
 git rest --soft HEAD~
 ---- 移动HEAD的指向,将其指向上一个快照
 ---- 撤销上一次的提交,并不会改暂存区的数据
 git rest --hard HEAD~
 ---- 移动HEAD的指向,将其指向上一个快照
 ---- 将HEAD移动后指向的快照回滚到暂存区域
 ---- 将暂存区域的文件还原到工作目录  (可能会将工作区域的文件删除)
 git reset 快照 文件名/路径  回滚指定文件
 git reset id  回滚指定快照(可以是以前的 可以是以后的)
 
 | 
实例:
| 12
 3
 4
 5
 6
 7
 
 | $git init$vim README.md
 $vim LICENSE
 $git add README.md && git commit -m "README.md"
 $git add LICENSE  && git commit -m "LICENSE v1"
 $vim LICENSE
 $git add LICENSE  && git commit -m "LICENSE v2"
 
 | 
结构图示:


比较三种reset 参数提交后的差距:
指针指向均为同一种:

git reset --soft HEAD~    撤销上一次的提交,并不会改暂存区的数据

git reset --mixed HEAD~   将HEAD移动后指向的快照回滚到暂存区域,会修改暂存区的数据 

git reset --hard HEAD~    将暂存区域的文件还原到工作目录 (会将工作区域的文件删除)

使用git reset 需谨慎,详细见 git reset soft,hard,mixed之区别深解
版本对比

会出现以上类型的交互界面,可以根据快捷键进行查看。
三棵树之间的diff命令详情:

文件增删改
| 12
 3
 4
 5
 6
 7
 
 | git commit --amend  修改最后一次commit提交    
 git rm 文件名    删除的只是工作目录和暂存区域的文件,也就是取消跟踪,在下次提交时不纳入版本管理
 
 git rm --cahced 文件名    只删除暂存区域的文件
 
 git mv old new   重命名
 
 | 
Git分支管理
几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。有人把 Git 的分支模型称为”必杀技特性”,而正是因为它,将 Git 从版本控制系统家族里区分出来。
| 12
 3
 4
 5
 6
 
 | git branch name  创建分支git checkout -b name 创建并切换至分支
 git checkout name  切换分支
 git branch -d name    删除分支
 git merge name  合并分支
 git log --decorate --all --oneline --graph  以图示化显示详情
 
 | 
实例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | $ git checkout -b yogaSwitched to a new branch 'yoga'
 $ vim yoga.html
 $ git add yoga.html && git commit -m "yoga"
 [yoga 77aad8e] yoga
 1 file changed, 2 insertions(+)
 create mode 100644 yoga.html
 
 $ git checkout -b Xm
 Switched to a new branch 'Xm'
 $ vim Xm.html
 $ git add Xm.html && git commit -m "Xm"
 [Xm d931fbb] Xm
 1 file changed, 2 insertions(+)
 create mode 100644 Xm.html
 
 $ git checkout master
 Switched to branch 'master'
 
 $ git merge Xm
 Updating 0bef8eb..d931fbb
 Fast-forward
 Xm.html   | 1 +
 yoga.html | 2 ++
 2 files changed, 3 insertions(+)
 create mode 100644 Xm.html
 create mode 100644 yoga.html
 $ git branch -d Xm
 Deleted branch Xm (was d931fbb).
 
 $ git merge yoga
 Already up to date.
 $ git branch -d yoga
 Deleted branch yoga (was 77aad8e).
 
 $ git log --decorate --all --oneline --graph
 * d931fbb (HEAD -> master) Xm
 * 77aad8e yoga
 * 0bef8eb index
 
 | 
指针图示:




由于此时产生了一个分支,于是git 会自动创建一个 P5的快照,而P5是P3、P4的祖先,于是master指向P5 即完成了合并 

推送改动
现在已经在本地仓库的 HEAD 中了。如下命令以将这些改动提交到远端仓库:
| 1
 | git push origin master  可以把 master 换成你想要推送的任何分支。
 | 
将你的仓库连接到某个远程服务器 ,使用如下命令添加:
| 1
 | git remote add origin    如此你就能够将你的改动推送到所添加的服务器上去了。
 | 
0x04 总结
差不多常用的Git命令就是这些了,而且git的用法远不止如此,作为目前最为优秀的文件管理系统。
0x05 Reference
Git-scm
廖雪峰的git教程