Git创建一个自己的本地仓库
如果我们要把一个项目加入到Git的版本管理中,可以在项目所在的目录用git init命令建立一个空的本地仓库,然后再用git add命令把它们都加入到Git本地仓库的暂存区(stage or index)中,最后再用git commit命令提交到本地仓库里。
创建一个新的项目目录,并生成一些简单的文件内容:
$ mkdir test_proj
$ cd test_proj
$ echo “hello,world” > readme.txt
在项目目录创建新的本地仓库,并把项目里的所有文件全部添加、提交到本地仓库中去:
$ git init #在当前的目录下创建一个新的空的本地仓库Initialized empty Git repository in /home/user/test_proj/.git/
$ git add . #把前目录下的所有文件全部添加到暂存区
$ git commit -m 'project init' #创建提交[master (root-commit) b36a785] project init 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 readme.txt
Git目录的结构
git init命令在项目的顶层目录中建了一个名为:“.git”的目录,它的别名是 “Git目录”(Git directory)。这时”Git目录”中虽然有一些文件,但是没有任何提交(commit)在里面,所以我们叫它是空仓库(empty Git repository)。
和 SVN不同,一个Git项目一般只在项目的根目录下建一个“.git”目录,而SVN则会在项目的每一个目录下建一个”.svn”目录;这也我喜欢Git的原因之一:
Git把所有的历史提交信息全部存储在“Git目录”里,它就是一个Git项目的仓库;你对本地的源代码进行编辑修改后创建的提交也都会先保存在这 里面,然后再推送到远端的服务器。当我们我把项目目录和“Git目录”一起拷到其它电脑里,它能马上正常的工作(所有的提交信息全都保存在Git目录 里);甚至可以只把“Git目录”拷走也行,但是要再签出(checkout)一次。
Git为了 调试的方便,它可以指定项目的Git目录的位置。有两种办法:一是设置“GIT_DIR”环境变量,二是在命令行里设定“--git-dir--git-dir”参数指定它的位置,大家可以看一下这里(git(1) Manual Page)。
庖丁解牛
前面的这些东东我在第一篇里也大概的讲过一些,但是今天我们想不但要开动这辆叫“Git”的跑车,还想看看它里面有些什么样的零件,是怎么构成的。
OK,我们来看看“test_proj”项目里的“Git目录”的结构:
$cd test_proj/.git
$ ls | more
branches/ # 新版的Git已经不再使用这个目录,所以大家看到它 #一般会是空的
COMMIT_EDITMSG # 保存着上一次提交时的注释信息
config # 项目的配置信息
description # 项目的描述信息
HEAD # 项目当前在哪个分支的信息
hooks/ # 默认的“hooks” 脚本文件
index # 索引文件,git add 后把要添加的项暂存到这里
info/ # 里面有一个exclude文件,指定本项目要忽略的文件 #,看一下这里
logs/ # 各个refs的历史信息
objects/ # 这个目录非常重要,里面存储都是Git的数据对象
# 包括:提交(commits), 树对象(trees),二进制对象 #(blobs),标签对象(tags)。
#不明白没有关系,后面会讲的。
refs/ # 标识着你的每个分支指向哪个提交(commit)。
我先用git log命令来看一下这个Git项目里有哪些提交:
$ git logcommit 58b53cfe12a9625865159b6fcf2738b2f6774844
Author: liuhui998 <liuhui998@nospam.com>
Date: Sat Feb 19 18:10:08 2011 +0800
project init
大家可以看到目前只有一个提交(commit)对象,而它的名字就 是:”58b53cfe12a9625865159b6fcf2738b2f6774844”。这个名字就是对象内容的一个SHA签名串值,只要对象里面的内容不同,那么我们就可以认为对象的名字不会相同,反之也成立。我在使用时一般不用把这个40个字符输全,只要把前面的5~8个字符输完就可以(前提是 和其它的对象名不冲突)。为了方便表示,在不影响表达的情况下,我会只写SHA串值的前6个字符。
我们可以用git cat-file来看一下这个提交里的内容是什么:
$ git cat -file -p 58b53c tree 2bb9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13author liuhui998 <liuhui998@nospam.com> 1298110208 +0800
committer liuhui998 <liuhui998@nospam.com> 1298110208 +0800
project init
大家可以看到:提交“58b53c” 是引用一个名为“2bb9f0”的树对象(tree)。一个树对象(tree)可以引用一个或多个二进制对象(blob), 每个二进制对象都对应一个文件。 更进一步, 树对象也可以引用其他的树对象,从而构成一个目录层次结构。我们再看一下这个树对象(tree)里面有什么东东:
$ git cat-file -p 2bb9f0100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt
不难看出,2bb9f0”这个树对象(tree)包括了了一个二进制对象(blob),对应于我们在前面创建的那个叫 ”readme.txt”的文件。现在我们来看看这个”blob”里的数据是不是和前面的提交的内容一致:
$ git cat-file -p 2d832dhello,world
哈哈,熟悉的“hello,world”又回来了。
想不想看看提交对象、树对象和二进制对象是怎么在”Git目录“中存储的;没有问题,执行下面的命令,看看”.git/objects”目录里的内容:
$ find .git/objects.git/objects
.git/objects/2b
.git/objects/2b/b9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13.git/objects/2d
.git/objects/2d/832d9044c698081e59c322d5a2a459da546469.git/objects/58
.git/objects/58/b53cfe12a9625865159b6fcf2738b2f6774844.git/objects/info
.git/objects/pack
如果大家仔细看上面命令执行结果中的粗体字,所有的对象都使用SHA签名串值作为索引存储在”.git/objects”目录之下;SHA串的前两个字符作为目录名,后面的38个字符作为文件名。
这些文件的内容其实是压缩的数据外加一个标注类型和长度的头。类型可以是提交对象(commit)、二进制对象(blob)、 树对象(tree)或者标签对象(tag)。
如何clone一个远程项目
我身边的很多朋友是因为要得到某个开源项目的代码,所以才开始学习使用Git。而获取一个项目的代码的一般的做法就是用git clone命令进行直接复制。
例如,有些朋友可能想看一下最新的linux内核源代码,当我们打开它的网站时,发现有如下面的一段提示:
URL
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
URL下面的三行字符串表示三个地址,我们可以通过这三个地址得到同样的一份Linux内核源代码。
也就是说下面这三条命令最终得到的是同一份源代码:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
git clone http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
git cone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
我们先来看一下URL,git://、http://、https://这些代表是传输git仓库的协议形式,而“git.kernel.org“则代表了Git仓库存储的服务器名字(域名),“/pub/scm/linux/kernel/git/torvalds/linux-2.6.git” 则代表了Git仓库在服务器上位置。
Git 仓库除了可以通过上面的git、http、https协议传输外还可以通过ssh、ftp(s)、rsync等协议来传输。git clone的本质就是把“Git目录”里面的内容拷贝过来,大家想想看,一般的“Git目录”里有成千上万的各种对象(提交对象,树对象,二进制对象......),如果逐一复制的话,其效率就可想而知。
如果通过git、ssh协议传输,服务器端会在传输前把需要传输的各种对象先打好包再进行传输;而http(s)协议则会反复请求要传输的不同对 象。如果仓库里面的提交不多的话,前者和后者的效率相差不多;但是若仓库里有很多提交的话,git、ssh协议进行传输则会更有效率。
不过现在Git对http(s)协议传输Git仓库做了一定的优化,http(s)传输现在也能达到ssh协议的效率,有兴趣的朋友可以看一下这里(Smart HTTP Transport)。
好的,现在我们执行了下面这条命令,把linux-2.6的最新版源代码clone下来:
$cd ~/$mkdir temp$git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.gitInitialized empty Git repository in /home/liuhui/temp/linux-2.6/.git/
remote: Counting objects: 1889189, done.
remote: Compressing objects: 100% (303141/303141), done.
Receiving objects: 100% (1889189/1889189), 385.03 MiB | 1.64 MiB/s, done.
remote: Total 1889189 (delta 1570491), reused 1887756 (delta 1569178)
Resolving deltas: 100% (1570491/1570491), done.
Checking out files: 100% (35867/35867), done.
当我们执行了“git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git”这条命令后大家可以看到这条输出:
Initialized empty Git repository in /home/user/temp/linux-2.6/.git/
这就是意味着我们在本地先建了一个“linux-2.6”目录,然后在这个目录建了一个空的Git本地仓库(Git目录);里面将会存储从网上拉下来的历史提交。
下面两条输入代表服务器现在调用git-pack-objects 对它的仓库进行打包和压缩:
remote: Counting objects: 1888686, done.
remote: Compressing objects: 100% (302932/302932), done.
然后客户端接收服务器端发过送过来的数据:
Receiving objects: 100% (1889189/1889189), 385.03 MiB | 1.64 MiB/s, done.
在我们执行完上面的clone linux-2.6代码的的操作后,Git会从“Git目录”里把最新的代码到签出(checkout)到“linux-2.6”这个目录里面。我们一般 把本地的“linux-2.6”这个目录叫做”工作目录“(work directory),它里面保存着你从其它地方clone(or checkout)过来的代码。当你在项目的不同分支间切换时,“工作目录”中的文件可能会被替换或者删除;“工作目录”只是保存着当前的工作,你可以修 改里面文件的内容直到下次提交为止。
大家还记得前面的“庖丁解牛”吗,是不是觉得只杀一头叫“hello,world”的小牛太不过瘾了。没有问题,拿起前面的那把小刀,来剖析一下现在躺在你硬盘里这头叫“linux-2.6”大牛看看,我想一定很好玩。
向本地仓库中增加文件
下面我们向版本库中增加文件,需要注意的是,在版本库中只能跟踪和管理文本文件,比txt文件、js文件、php文件、java文件等,所有的程序 代码都可以的。但是像视频、图片等这些二进制文件,虽然能由git管理,但是只能记录大小,无法跟踪具体修改了什么,嘿嘿。大家懂了吧。好了,下面我们来 增加一个readme.txt文件,其内容如下:
1 2 3 |
|
注意,新建的readme.txt文件,一定要在pro目录,不然git无法管理这里文件哦,嘿嘿!下面我们把个文件放到版本库中。
1).git status 命令
我们先用git status命令查看一下,如上图。大家可以看到git记录我们新增加一个文件readme.txt,并且提示这个文件还没有被提交。下面我们用git add命令提交一下。
2).git add 命令
git add 命令是告诉git,我们要把什么文件提交到仓库中去,大家可以看我们执行git add readme.txt命令后,没有任何提示。那就说明我们提交完成了。下面我们通过git commit命令,将readme.txt文件提交到版本库中。
3).git commit 命令
1 2 3 4 |
|
大家可以看到我们用git commit命令提交readme.txt文件,给出的提示是 1 file changed, 3 insertions(+),一个文件改变,插入了三行内容。与我们上面增加三行内容一致。嘿嘿!下面我们简单的说明一下git commit命令,其中的参数-m后面输入的是本次提交的版本说明,可以输入任意内容,但需要说明的是,最好写有意义的说明,便于以后查看。
4).git status 命令
最后我们再用git status命令查看一下版本库的状态,提示没有任何内容需要提交说明我们向版本库增加文件成功了,嘿嘿。
4.总结
1).初始化一个Git仓库,使用git init命令
2).添加文件到本地Git仓中,分为两步:
使用git add命令,注意,可以多次使用,添加多个文件
使用git commit命令,完成添加。
为什么Git添加文件需要两步呢?一步add,一步commit。嘿嘿,因为commit命令可以一次提交多个文件,所以你可以多次使用add命令呢。下面是个案例:(我们也经常这么用)
1 2 3 4 |
|
Git创建一个自己的本地仓库的更多相关文章
- Git 历险记(三)——创建一个自己的本地仓库
如果我们要把一个项目加入到Git的版本管理中,可以在项目所在的目录用git init命令建立一个空的本地仓库,然后再用git add命令把它们都加入到Git本地仓库的暂存区(stage or inde ...
- [原]git的使用(一)---建立本地仓库、add和commit、status和git diff、版本回退使用git reset
在window下已经安装了git的环境 1.建立本地仓库 mkdir test #建立test目录 cd test #进入目录 git init # ...
- Git 学习(三)本地仓库操作——git add & commit
Git 学习(三)本地仓库操作——git add & commit Git 和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念.这在上文已有提及,本文具体说明什么是工作区及暂存区,以及 ...
- 使用Git GUI工具 上传本地仓库到 gitee码云仓库
前言: 网上关于git的命令操作与使用很多教程和博客,在使用git工具时我发现有一个 git Gui 可视化工具,我觉得十分的亲切,由于我之前一直是使用svn作为版本控制管理工具,都是可视化操作,使用 ...
- 1、git基础介绍及远程/本地仓库、分支
1. Git基础介绍 基于Git进行开发时,首先需要将远程仓库代码clone到本地,即为本地仓库.后续大部分时间都是基于本地仓库上的分支进行编码,最后将本地仓库的代码合入远程仓库. 1.1. 远程仓库 ...
- [Git] 007 三棵树以及向本地仓库加入第一个文件
1. "三棵树" 1.1 前言 理论上要稍稍复杂一点 我在这里说得简化一点 顺道挖个坑 下回具体介绍 坑号编码:Git07-1 1.2 看图 1.3 简介 树左:工作区(平时写代码 ...
- git 创建一个空分支
创建一个分支 使用参数 --orphan,这个参数的主要作用有两个,一个是拷贝当前所在分支的所有文件,另一个是没有父结点,可以理解为没有历史记录,是一个完全独立背景干净的分支. 参考git的帮助文档, ...
- git使用问题一新建本地仓库添加远程合并推送
1,git远程新建仓库demo 2,git本地初始化仓库demo 3,git本地添加远程仓库 git remote add <name> <url> 4,git把远程仓库pul ...
- Git轻松入门1:本地仓库篇
什么是Git 版本控制系统 首先我们要明白,什么是版本控制系统(version control systems)? 版本控制系统,顾名思义,就是能控制文件处于哪个版本的系统. e.g. 你在博客园里编 ...
随机推荐
- GUI编程笔记(java)03:GUI的组件继承图
1.组件继承图: 2.分析上面的组件继承图 (1)Component:public abstract class Component extends Object implements ImageOb ...
- 输入一个字符串,去掉重复的字符,并按ASCII值排序-华为机试
import java.util.Scanner; //输入字符串,去掉重复的字符,并按ASSIC码值排序 public class quChong { public static void main ...
- SCIP读书笔记(1)
这书也算是必修吧,尤其是我这种非科班人员,还是应该抽时间尽量学习一下.大致翻过一遍,习题非常多,尽力吧. ##构造过程抽象 * 为了表述认知,每种语言都提供了三种机制:基本元素:组合方式:抽象方法. ...
- JS1 js获取dom元素方法
js获取dom元素方法 1.通过ID选取元素(getElementById) 1)使用方法:document.getElementById("domId") 其 ...
- gulp 前端自动化工具
一开篇 在前端开发的过程中,我们经常会碰到压缩.合并.图片script 等,于是就有了gulp 前端自动化构建工具,它能帮你在前端开发中,节省时间. 1,安装 node.js 因为gulp 构建工具是 ...
- jsp中的注释
jsp中有各种针对不同类型语言的注释,值得注意的是对于标签 <jsp:include/>是需要使用jsp注释"<%----%>", (不能是<!-- ...
- 安装mysql数据库
http://jingyan.baidu.com/article/f3ad7d0ffc061a09c3345bf0.html
- hibernate 其中七种关联关系
写的很好 http://blog.csdn.net/qq_27550755/article/details/50070017
- OC基础-day04
#pragma mark - Day04_01_匿名对象 1. 如果函数有返回值 我们可以不使用变量接收返回值. 而是直接将函数写在要使用其返回值的地方. 2. 正常情况下.我创建对象. 是使用了1 ...
- React初探
经过几天根据官方文档和博园中一些大牛的文章,在了解过基础的语法和组件后,总结一下: 1.第一件事就是分析界面,理想状态下是让每个组件只做一件事情,也就是单一职责,相互嵌套.我认为: 构建组件树,整体的 ...