git是分布式版本控制系统。

  • 版本控制系统:
    • 集群式版本控制(CSV / SVN):增量
    • 分布式版本控制(Git):全量(每一个版本都包含全部文件,数据在任何版本都完整)
  • git优势
    • 本地版本控制
    • 重写提交声明
  • git管理下的文件的状态
    • 未跟踪
    • 已跟踪:已经add过的
      • 已修改(modified)
      • 已暂存(staged)
      • 已提交(commited)

加密算法

  • shal:目的产生随机数。区分哪一次提交(并且不重复)
  • md5
  • 区域
    • 工作区
    • 暂存区
    • 版本库
  • 对象
    • Git 对象
    • 树对象
    • 提交对象

一、Git 底层概念(底层命令)

(一)基础的linux命令

  • clear:清屏
  • echo 'test content':往控制台输出信息
  • ll:将当前目录下的子目录&子文件平铺在控制台
  • find 目录名:将对应目录下的子孙文件&子孙目录平铺在控制台。
  • find 目录名 -type f:将对应目录下的子孙文件平铺在控制台。
  • rm 文件名:删除文件
  • mv 源文件 重命名文件:重命名
  • cat 文件的url:查看对应文件的内容
  • vim 文件的url(在英文模式下)
    • 按 i 进插入模式,进行文本编辑
    • 按 esc 键:退出文本编辑模式
    • 按冒号:键:进行命令的执行
      • :q!:强制退出不保存
      • :wq:保存并退出
      • set nu:设置行号

(二).git目录

  • .git文件里的东西
    • hooks:目录包含客户端或服务端的钩子脚本。
    • info:包含一个全局性排除文件
    • logs:保存日志信息
    • objects:目录存储所有数据内容
    • refs:目录存储指向数据的提交对象的指针(分支)
    • config:文件包含项目特有的配置选择
    • description:用来显示对仓库的描述信息
    • HEAD:文件指示目前被检出的分支
    • index:文件保存暂存区信息。

(三)git对象

  • Git的核心技术是一个简单的键值对数据库。你可以向该数据库插入任意类型的内容。它会返回一个键值,通过该键值可以在任意时刻再次检索改内容。
  • git 对象:key:value组成的键值对(key是value对应的hash)
    • 键值对在git内部是一个blob类型
    • 代表文件的一次次版本。
  • 存在问题:
    • 记住文件的每一个版本的 sha-1哈希值,不现实
    • 在Git中,文件名没有被保存而是保存了文件内容。(解决方法:树对象)
  • 注意:当前操作都不涉及暂存区。只涉及本地区和版本区

向数据库写入内容,并返回对应键值

  • 命令:echo 'test content' | git hash-object -w --stdin
    • -w选项,指示hash-object命令存储数据对象。若不指定此选项,则该命令仅返回对应的键值。
    • --stdin选项(standard input),指示该命令从标准输入读取内容。若不指定此选项,则须在命令尾部给出待存储文件路径。
      • git hash-object -w 文件路径:存文件
      • git hash-object 文件路径:返回对应文件的键值。如下
        ce013625030ba8dba906f756967f9e9ca394464a
  • 返回的键值:该命令输出一个长度为40个字符的校验和。这是一个sha-1哈希值

补充

  • 一竖杠|是两条命令的分隔。
  • sha-1哈希值是键,文件内容是值。

根据键值拉取数据

  • 命令:git cat-file -p ce013625030ba8dba906f756967f9e9ca394464a
    • -p选项,可指示该命令自动判断内容的类型,并为我们显示格式友好的内容。返回:对应文件内容。
    • -t选项,可指示该命令为我显示文件类型。返回:git类型(blob,tree,commit)。

(四)树对象

  • 树对象:解决文件名保存问题,允许我们将多个文件组织到一起。
    • 代表项目的一次次版本。
    • 可以认为树对象就是我们项目的快照。
  • 查看暂存区:git ls-files -s

构建树对象

  • 我们可以通过update-index; write-tree; read-tree等命令构建树对象,并塞到暂存区。

小测试

  • 1.利用update-index命令,为test.txt文件的首个版本,创建一个暂存区。并通过write-tree命令生成树对象。
    • 命令:
      a)git update-index --add --cacheinfo 100644\ce013625030ba8dba906f756967f9e9ca394464a test.txt
      b)git write-tree
      • 文件模式:
        • 100644表明这是一个普通文件。
        • 100755表示一个可执行文件。
        • 120000表示一个符号链接。
      • --add选项:把文件添加到暂存区。
      • --cacheinfo选项:因为将要添加的文件位于git数据库中,而不是位于当前目录下。
  • 2.新增new.txt。将new.txt和test.txt文件的第二个版本塞入暂存区。并通过write-tree命令生成树对象
    • 命令:
      a)echo 'a new file' > new.txt
      b)git update-index -cacheinfo 100644\38748dc9f68597a98e4c4d0162078bc783b16226 test.txt第二个版本。同名则覆盖。
      c)git update-index --add --cacheinfo e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt
      d)git write-tree

到目前有五个对象,五个哈希值。两个树对象,三个git对象。

  • 3.将第一个树对象加入第二个树对象,使其成为新的树对象。
    • 命令:
      a)git read-tree --prefix=bak 620ffd0fd9579a46e46ef4505b198ee0a01a57f2第一个树对象的哈希值
      b)git write-tree
      • git read-tree:把树对象读入暂存区。

查看树对象

  • 命令:git cat-file -p 620ffd0fd9579a46e46ef4505b198ee0a01a57f2用树对象的哈希值

解析树对象

(五)提交对象

  • 提交对象:通过调用commit-tree命令创建一个提交对象,为此需要指定一个树对象的sha-1值,以及该提交的父提交对象(第一次将暂存区做快照没有父对象)
  • 可以形成链式结构。

创建提交对象

  • 第一次创建提交对象命令:echo 'first commit' | git commit-tree 620ffd0fd9579a46e46ef4505b198ee0a01a57f2
    • 返回一个哈希值,代表commit对象
  • 继续创建提交对象命令:echo 'second commit' | git commit-tree 第一棵树对象哈希值 -p 第二棵树对象的哈希值

查看提交对象

  • 命令:git cat-file -p commit对象的哈希值
    • 返回:
      tree tree对象的哈希值
      author 名称 邮箱 时间戳
      committer 名称 邮箱 时间戳
      提交说明

二、git 的高层命令(CRUD)

  • git -version:安装
  • git init:创建git本地版本库
  • rm -rf .git:删版本库,并且删掉里面的子目录。
  • git status:查看文件状态。

(一)设置邮箱和用户名

  • git config
    • 1.git config --system:基本不用。给当前计算机一次性设置 ~ .gitconfig
    • 2.git config --global:推荐,给当前用户一次性设置
    • 3.git config --local:给当前项目一次性设置 .git/config
      • git config --local user.name 'konsoue':设置用户名
      • git config --local --unset user.name:删除用户名
    • 地址越精确,优先级越高。3>2>1

(二)配别名

  • 可以通过git config命令来未每一个命令配置一个别名。
    • git config --global alias.别名 "原名"
    • git config --global alias.lol "log --oneline --decorate --graph --all" 这样以后使用就这样用git lol

(三)文件操作

  • touch a.txt:在工作区新建a.txt文件
  • git add hello.txt:添加hello.txt到暂存区
    • git add .:把工作区所有文件添加到暂存区。
  • git rm test.txt:在工作区删除test.txt文件,并add到暂存区。
    • git rm --cached hello.txt:把暂存区的hello.txt退回工作区
  • git commit:把暂存区的文件提交到对象区。
    • git commit -m "第一次提交":提交说明少,可以这么写

  • git checkout -- hello.txt或者git restore hello.txt:撤回上一次修改,还原到已提交状态。
  • git reset HEAD hello.txt或者git restore --staged hello.txt:把刚提交到暂存区的hello.txt文件删回工作区。
  • git rm hello.txt:把版本库的hello.txt删回暂存区。(现在可以删回工作区或者再提交一次。)

  • rd 文件夹:进入某个文件夹查看
  • ls:查看当前文件夹的所有文件
  • cat:查看文本文件内容。
  • git log:查看本分支提交日志
    • git log -2:最近提交的两次记录
    • git log --pretty=oneline:提交对象哈希值和提交说明放在同一个区域。
    • git log --pretty=format:"%h - %an ,%ar : %s":显示shal函数前一部分,%an用户名,%ar提交世界,%s提交说明
    • git log --oneline --decorate --graph --all:查看所有分支的提交日志。
  • git reflog:记录着HEAD的所有移动。
  • git diff:查看当前更新未暂存
    • git diff --cached或者git diff --staged: 查看更新且已暂存,未提交的文件。
  • git cat-file -p 暂存区文件哈希值:查看暂存区文件内容
  • git config:config配置的意思
    • git config --list:查看仓库级、全局级、系统级配置文件
    • git config --edit:编辑.git文件里的config文件

  • vi hello.txt:把对象区的hello.txt提回工作区,让你修改。要重新提交。
  • echo 'world' > hello.txt:把hello.txt内容写改为world
  • git mv 原文件名 重命名文件名:给工作区的文件重命名,且add到暂存区里。

(四)git 本地分支操作

  • 分支的本质:其实就是一个指向提交对象的可变指针.
  • HEAD 是一个指针,它默认指向 master 分支,切换分支就是让 HEAD 指向不同的分支。
    • 像是一只领头羊(往前走的是它),带着master或者其他分支往前走。
  • 命令:git branch显示分支列表

创建&删除分支

  • 创建分支命令:
    • git branch 分支名作用:这会在当前所在的提交对象上创建一个可移动的新指针。
    • git branch 分支名 commitHash作用:新建一个分支并使这个分支指向对应的提交对象。
  • 删除分支命令:git branch -d 分支名。合并后用小d
    • 未合并强制删除用大Dgit branch -D 分支名

版本穿梭:建个分支给之前的提交对象。回去查看一波

切换分支

  • 命令:git checkout 分支名
    • 切换三个地方:把HEAD、工作区、暂存区切换到分支所在版本。
  • 最佳实践:每次切换分支前,保证当前分支一定是干净的(已提交状态)
  • 注意:
    • 在切换分支时,如果当前分支上有未暂存的修改(第一次)或者 有
      未提交的暂存。分支可以切换成功,但是可能污染其他分支。

合并分支

  • 快进合并(fast forward):a分支落后于b分支时,在a分支用命令git merge b分支名就会把a分支快进到和b分支同步。这样a分支就合并了b分支的版本。
  • 典型合并:
    • (1)两个分支并排时
    • (2)是快进合并,但是强制不快进
      git merge --no--ff 分支名
  • 冲突:如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们,这时就产生冲突。
    • 查看冲突:git status
    • 解决冲突:vim 有冲突的文件修改冲突,然后git add .表明冲突已修改,git commit -m ''提交

分支模式

  • 长期分支
  • 特性分支

(五)git 栈存储

  • 想从b分支切到a分支,但是b分支的工作已经提交过version1,但是修改成version 2,但还不想提交,可以先放到栈里。(栈里面一般放一两个)
  • 命令:git stash:把修改后的文件,放到栈里。
    • git stash list:查看栈有啥东西。
    • git stash apply stash@{n}:应用栈的储存,但没有删除。没写指定的储存,默认栈顶。
    • git stash drop 栈顶(stash@{n}:删除栈的储存。没写指定储存,默认栈顶
    • git stash pop:应用栈顶的储存,而且删除。

(六)git撤回&重置

git撤回(后悔药)

  • 所谓撤回,只是视觉效果的撤回。
  • 工作区:撤回在工作区已跟踪的文件的修改。
    • 命令:git checkout -- test.txt或者git restore test.txt
  • 暂存区:撤回暂存区的文件修改。
    • 命令:git reset HEAD test.txtgit restore --staged test.txt
  • 版本库:撤回版本库的文件修改。
    • 命令:git commit --amend
    • 原理:把暂存区的数据重新提交并且重新注释。
      是不是调用了git reset --soft HEAD~git commit

git重置(reset):版本穿梭

  • reset三部曲
    • 移动HEAD
      • 命令:git reset --soft HEAD~
      • 作用:移动HEAD和HEAD所对应的分支。git checkout是移动HEAD而已。~是回到HEAD的父节点,可以换成提交对象的哈希值。
    • 更新暂存区(索引)
      • 命令:git reset HEAD~git reset --mixed HEAD~
      • 作用:移动HEAD和HEAD所对应的分支,且把暂存区更新到HEAD父节点的版本。
      • 特有命令:git reset [--mixed] HEAD~ filename
      • 最后加上一个文件名,只回退这个文件。HEAD和其对应分支不移动
    • 更新工作区
      • 命令:git reset --hard HEAD
      • 作用:移动HEAD和HEAD所对应的分支,且把暂存区、工作区更新到HEAD父节点的版本。
      • 存在风险:把工作区未跟踪的文件抹掉。
  • 利用git reflog命令找到原来的节点的哈希值,在那里创建个分支,然后切回去。

(七)打tag(标签)

  • Git可以给历史中的某一提交打上tag,以示重要。比如这个软件第几个版本了。
  • tag标签,就像个不会动的分支。
  • 命令:git tag:列出标签名

创建标签

  • git使用两种类型标签:轻量标签 与 附注标签
  • 命令:git tag v1.0 (提交对象的哈希值)
    • 这样就打了个tag交v1.0
  • 切回某个tag的版本,命令:git checkout tagName
    • 头部分离:切回去的版本没有分支,不能修改。得加一个分支。

查看特定标签

  • 命令:git show tagName
    • 显示该标签所在版本的内容。

删除tag

  • 命令:git tag -d tagname

三、远程仓库

  • 远程仓库是指托管在因特网或其他网络中的你的项目的版本库。

(一)三种分支

  • 分支
    • 远程分支:在github仓库的分支
      • 它们以 远程库别名/远程分支名 形式命名。
      • 远程引用:对远程仓库的引用(指针),包括分支、标签等。
      • 查看远程引用完整列表:git ls-remote 远程库别名
      • 更多远程分支的信息:git remote show 远程库别名
    • 远程跟踪分支(跟踪分支):就是本地分支 跟踪 远程分支
      • 创建命令:git checkout -b 新建本地分支名 远程分支
      • 远程跟踪分支是远程分支状态的引用。 它们是你不能移动的本地引用,当你做任何网络通信操作(fetch、push、pull)时,它们会自动移动。
      • 远程跟踪分支像是你上次连接到远程仓库时,那些分支所处状态的书签。
      • 例如,如果你想要看你最后一次与远程仓库 origin 通信时 master 分支的状态,你可以查看 origin/master 分支。
    • 本地分支

(二)远程协作基本流程

  1. 项目经理创建远程仓库(github)
    (1)在github初始化一个的仓库
  2. 项目经理创建本地仓库
  3. 项目经理为远程库配置别名&用户信息
    (1)命令:git remote add 远程库别名 url添加一个新的远程Git仓库,同时指定一个你喜欢的远程库别名(remoteName)
    (2)命令:git remote -v显示远程仓库使用的Git别名与其对应的url
    (3)命令:git config --local user.name 'yourName'配置用户信息。(用户名,用户邮箱)
    (4)
  4. 项目经理推送本地项目到远程仓库
    (1)清理windows凭据
    (2)命令:git push 远程库别名 本地分支输入用户名 密码后会附带生成远程跟踪分支
  5. 成员克隆远程仓库到本地
    (1)命令:git clone url(克隆不需要git init)
    在本地生成.git文件,默认给远程仓库配个别名origin。
  6. 项目经理邀请成员进入团队
    在github上操作
  7. 成员推送提交到远程仓库
    (1)修改源码文件,提交到本地库
    (2)git push 远程仓库别名 本地分支输入用户名 密码,自动生成远程跟踪分支
  8. 项目经理更新成员提交内容
    (1)命令:git fetch remoteName

四、github

一、基本概念

  • 仓库 (Repository)
    • 用来存放项目代码,每个项目对应一个仓库,多个开源项目则有多个仓库。
  • 收藏 (Star)
    • 收藏项目,方便查看。
  • 复制克隆项目 (Fork)
    • 复制别人仓库里的开源项目,自己新建个仓库放它。(本质上是在原有项目上新建分支),随便改,因为是备份,不会影响原有的代码与结构。
  • 发起请求 (Pull Request)
    • 基于 fork。改了别人的代码,觉得有用,想把改进合并到原有项目里。这时发送 pull request (PR) 请求,原有项目创建人 review 完,觉得 Ok,就接受你的 RP。
  • 关注(watch)
    • 关注某个项目后, 当项目有更新,通知你。
  • 事务卡片(lssue)
    • 发现代码 bug,但目前没有成型代码,需要讨论时用。
  • Github主页
  • 仓库主页
  • 个人主页