20171130 Git

一、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
    
    • 此时远程项目已经获得了更新
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容