git不同于类似SVN这样的版本号管理系统,尽管熟悉经常使用的操作就能够满足大部分需求,但为了在遇到麻烦时不至于靠蛮力去尝试,了解git的原理还是非常有必要。

文件

通过git管理的文件版本号信息所有存放在根文件夹.git下,略微看下:

$ ls .git
COMMIT_EDITMSG HEAD branches description index logs packed-refs
FETCH_HEAD ORIG_HEAD config hooks info objects refs

git除了提供给我们平时经常使用的一些命令之外,还有非常多底层命令,能够用于查看以上部分文件表示的东西。

三个区域/三类对象

理解git里的三个区域概念非常重要。git里非常多经常使用的命令都是环绕着这三个区域来做的。它们分别为:

  • working directory,也就是你所操作的那些文件
  • history,你所提交的全部记录,文件历史内容等等。git是个分布式版本号管理系统,在你本地有项目的全部历史提交记录;文件历史记录;提交日志等等。
  • stage(index),暂存区域,本质上是个文件,也就是.git/index

git中还有三类经常使用对象(实际不止三种),理解这三类对象也非常重要。分别为:

  • blob,用于表示一个文件
  • tree,用于表示一个文件夹,索引到若干文件或子文件夹
  • commit,用于表示一次提交(commit)

全部对象都会以文件的形式保存在.git/objects文件夹,一个对象一个文件。

接下来把上面全部的内容关联起来。做下面操作:

$ mkdir test && cd test
$ git init
$ ls -a .git/objects # 没有文件
. .. info pack
$ touch readme # working directory里添加了一个readme文件
$ git add readme # 加入一个文件到stage区域
$ git ls-files --stage # 这个命令能够查看stage区域里的内容,能够看到有readme
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 readme
$ ls -a .git/objects # 同一时候.git/objects添加了一个e6的文件夹
. .. e6 info pack
$ ls -a .git/objects/e6/ # e6文件夹下添加了一个文件
. .. 9de29bb2d1d6434b8b29ae775ad8c2e48c5391

上面的操作展示了git中三个区域三个对象的部分关联关系。git中每一个对象都以一个40个字符长度的SHA-1哈希值为标识,以这40个字符的前2个字符作为目录,以后38个字符为文件名称。

基于以上继续操作:

$ git commit -m 'first commit'   # commit会将stage里标识的文件提交到history区域
[master (root-commit) 8bf6969] first commit
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 readme $ ls -a .git/objects # 添加了2个文件,也就是2个对象
. .. 8b e6 e8 info pack
$ git ls-files --stage # stage仅表示当前被版本号管理的文件,所以内容不变
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 readme # git cat-file 命令能够用于查看.git/objects下的文件,意就可以用于查看对象
$ git cat-file -t e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 # 这个是之前git add readme产生的文件对象 blob
blob # 相同我们来查看git commit -m后新增的两个对象 $ ls .git/objects/8b/
f696927c17526eb8f0c6dae8badb968a001ed0
$ git cat-file -t 8bf696927c17526eb8f0c6dae8badb968a001ed0 # 记得带上8b这个目录名,才算一个完整的对象ID。这是一个commit对象
commit
$ ls .git/objects/e8
0ad49ace82167de62e498622d70377d913c79e
$ git cat-file -t e80ad49ace82167de62e498622d70377d913c79e # tree对象
tree

区域和对象怎样交互的能够用下图描写叙述:

通过git cat-file -p能够查看对象的很多其它描写叙述,git cat-file -t仅获取对象的类型。做下面操作获得更深的认识:

# 这个commit对象记录了提交者的信息,还包含指向的tree对象
$ git cat-file -p 8bf696927c17526eb8f0c6dae8badb968a001ed0
tree e80ad49ace82167de62e498622d70377d913c79e
author Kevin Lynx <kevinlynx@gmail.com> 1410090424 +0800
committer Kevin Lynx <kevinlynx@gmail.com> 1410090424 +0800 first commit # 查看tree对象能够看出tree指向的blob对象
$ git cat-file -p e80ad49ace82167de62e498622d70377d913c79e
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 readme

即使是已经被版本号管理的文件,发生修改后(正常修改或合并)都使用git add来又一次mark它。创建第二次提交进一步认识:

$ echo 'hello git' > readme
$ touch install
$ git ls-files --stage # 不使用git add,暂存区域内容没变
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 readme # 此时stage里内容未变,提示no changes added to commit
$ git commit
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# install
no changes added to commit (use "git add" and/or "git commit -a") $ git add readme
$ ls .git/objects/ # git add之后.git/objects下新增文件
8b 8d e6 e8 info pack
$ ls .git/objects/8d/
0e41234f24b6da002d962a26c2495ea16a425f
$ git cat-file -p 8d0e41234f24b6da002d962a26c2495ea16a425f # 查看该新增对象
hello git # 这个时候还能够在提交前撤销git add readme
$ git reset readme # 从history到stage
Unstaged changes after reset:
M readme
$ cat readme
hello git
$ git checkout readme # 从stage到working directory
$ cat readme # 没有内容,回到第一个版本号 $ git add install # 加入新创建的文件
$ git ls-files --stage # stage中的内容是最新的readme和新加入的install
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 install
100644 8d0e41234f24b6da002d962a26c2495ea16a425f 0 readme
$ ls .git/objects/
8b 8d e6 e8 info pack

以上,发现一个有趣的现象:新加的install文件的SHA-1哈希值和之前的readme同样,这是由于这2个文件都是空的,内容同样。继续:

$ git commit -m 'second commit'
$ ls .git/objects/ # 提交后新增2个对象
45 72 8b 8d e6 e8 info pack $ ls .git/objects/72/
b94e949c5fca6092cc74c751a7bb35ee71c283
$ git cat-file -p 72b94e949c5fca6092cc74c751a7bb35ee71c283
tree 45cf0bd049d7eea4558b14f33a894db27c7c1130 # 新创建的tree对象
parent 8bf696927c17526eb8f0c6dae8badb968a001ed0 # commit对象有parent,正是上一次提交
author Kevin Lynx <kevinlynx@gmail.com> 1410094456 +0800
committer Kevin Lynx <kevinlynx@gmail.com> 1410094456 +0800 second commit
# 新创建的tree对象指向了2个文件
$ git cat-file -p 45cf0bd049d7eea4558b14f33a894db27c7c1130
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 install
100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f readme

须要注意,有时候我们使用git commit -a,它会直接将已经增加版本号管理的文件一起提交,从而跳过了git add这个过程。同git非常多操作一样,它仅仅是一个快捷操作。

总结

从上面的内容事实上已经能够看出git的优势所在,它能够全然不须要server就完毕一个版本号控制系统的全部事情。在.git文件里它记录了全部的文件的全部历史提交,记录了每一次提交的信息。

git的经常使用操作中还会涉及到分支、远端仓库等,空了再写。

參考文档

原文地址: http://codemacro.com/2014/09/09/understand-git/

written by Kevin Lynx  posted at
http://codemacro.com

理解git经常使用命令原理的更多相关文章

  1. 图解git,用手绘图带你理解git中分支的原理和应用

    大家好,今天我们来聊git当中一个非常非常重要的特性,就是branch. git branch可以说是git当中最重要的概念了,甚至没有之一.因为git最重要的使用场景就是协同开发,大家一起在一个项目 ...

  2. 『现学现忘』Git后悔药 — 34、git commit --amend 命令

    目录 1.git commit --amend 命令说明 2.使用场景 (1)场景一 (2)场景二 3.git commit --amend 命令原理 这是我们Git中的第三种后悔药. 1.git c ...

  3. 使用plumbing命令来深入理解git add和git commit的工作原理

    前言: plumbing命令 和 porcelain命令 git中的命令分为plumbing命令和porcelain命令: porcelain命令就是我们常用的git add,git commit等命 ...

  4. git plumbing 更加底层命令解析-深入理解GIT

    原文: http://rypress.com/tutorials/git/plumbing 本文详细介绍GIT Plumbing--更加底层的git命令,你将会对git在内部是如何管理和呈现一个项目r ...

  5. 深入理解Git的实现原理

      0.导读   本文适合对git有过接触,但知其然不知其所以然的小伙伴,也适合想要学习git的初学者,通过这篇文章,能让大家对git有豁然开朗的感觉.在写作过程中,我力求通俗易懂,深入浅出,不堆砌概 ...

  6. 理解git的分支原理,更好地使用git

    文章内容转载于git-scm. 部分内容涉嫌枯燥 一.git分支概念 几乎每一种版本控制系统都以某种形式支持分支.使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作.在很多版本控 ...

  7. 【Git 学习三】深入理解git reset 命令

    重置命令(git reset)是Git 最常用的命令之一,也是最危险最容易误用的命令.来看看git reset命令用法. --------------------------------------- ...

  8. 全面理解Git

    前言 人生贵知心,定交无暮早. 原文博客地址:Git命令总结 知乎专栏&&简书专题:前端进击者(知乎)  前端进击者(简书) 正文 1.Git简介 Git的诞生确实是一个有趣的故事,我 ...

  9. 理解git分支-远程分支

    远程分支 远程引用是对远程仓库的引用(指针),包括分支.标签等等. 你可以通过 git ls-remote (remote)来显式地获得远程引用的完整列表,或者通过 git remote show ( ...

随机推荐

  1. windows phone 7 通过Post提交URL到服务器,从服务器获取数据(比如登陆时候使用)

    原文:windows phone 7 通过Post提交URL到服务器,从服务器获取数据(比如登陆时候使用) HttpWebRequest myRequest = (HttpWebRequest)Web ...

  2. NET Core控制反转(IoC)

    ASP.NET Core中的依赖注入(1):控制反转(IoC)   ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制, ...

  3. 《Javascript高级程序设计》读书笔记之闭包

    闭包 function createComparisonFunction(propertyName) { return function (object1, object2) { var value1 ...

  4. Windows Phone开发(43):推送通知第一集——Toast推送

    原文:Windows Phone开发(43):推送通知第一集--Toast推送 好像有好几天没更新了,抱歉抱歉,最近"光荣"地失业,先是忙于寻找新去处,唉,暂时没有下文.而后又有一 ...

  5. Graphics.DrawString 方法

    MSDN上的解释: 在指定位置而且用指定的 Brush 和Font 对象绘制指定的文本字符串. public void DrawString( string s, Font font, Brush b ...

  6. 主流芯片解决方案Ambarella的高清网络摄像机、德州仪器和控制海思

    (本文由四川艾普作为数码科技有限公司 苏斌.范清华 收集) 高清网络视频监控发展到今天.正的高清时代.诸多有实力的高清摄像机厂家的产品线也逐渐完好起来,高清网络视频监控的配套产品有更加丰富和成熟.与此 ...

  7. 利用Sambaserver在Ubuntu系统和Win7系统间共享目录

    1 介绍 如今是网络化的时代,我们每一个人要更好的发展.离不开网络化.信息化的支持.利用网络的支持.在不同的操作系统间共享文件等信息,是计算机专业学生必备的一项技能. 本文所讲的就是怎样建立.设置.链 ...

  8. REDGATE又一好用的脚本工具ScriptsManager1.3

    原文:REDGATE又一好用的脚本工具ScriptsManager1.3 REDGATE又一好用的脚本工具ScriptsManager1.3 先说明一下:这个工具是免费的 下载地址:http://ww ...

  9. PM俱乐部之旅7-弱活着

     有些人认为,最终我们放松一点时间,有意想不到的事情发生--公司组织结构调整. 公司由于业务范围调整,所以要进行对应的组织结构调整.PMO部门也随之重组,项目经理俱乐部的活动改成项目交流会,请项目 ...

  10. Xamarin.Android 入门实例(4)之实现对 SQLLite 进行添加/修改/删除/查询操作

    1.Main.axml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns: ...