一、文件,指令讲解

首先讲一下远程仓库和本地仓库在文件上面的区别,首先我们来看下对比图(当然这里说的区别是在于.git文件下面的文件内容,至于里面内容我们不会关注)這裡我们进行了相同的操作就是本地仓库里面新建了version.txt内容也是一样的v1.0:

图一

图二

图一为本地仓库,图二为克隆的远程仓库,首先我们应该看一下config里面的区别:

图三

图四

很容易看到了区别就是图四为远程仓库内容。

从这个文件中我们可以了解到:

1,本地库的当前分支为master,其关联的远程库名称为origin(不同的名称可以指向同一个远程库,参见git remote命令)

2,远程库origin所在的位置为(URL):https://github.com/dwlsxj/BattleHeart.git
然后进行了version.txt的编辑和提交。这是我们刚才新建version.txt(远程)以及再添加内容为“v1.0”,在添加到暂存区,提交到本地提交中,最后提交到远程服务器,下面是我们生成的commit对象和git对象还有就是tree对象内容:

$ find .git/objects/ -type f
.git/objects//6c4629f6de8c956548570a113fa181d9b22692 commit对象
.git/objects//e34626d7993cf8d6c5e3e458744df4a9a31594 tree对象
.git/objects/c6/94c68edd99aeefa053f25308cd71ecca922036 blob对象

接下来我们就来看一下这个commit对象和tree对象下面的树分支和commit的指向内容。

$ git cat-file -t 186c46
commit $ git cat-file -t 90e346
tree $ git cat-file -t c694c6
blob $ git cat-file -p 186c46
tree 90e34626d7993cf8d6c5e3e458744df4a9a31594
author BattleHeart <dwlsxj@.com> +
committer BattleHeart <dwlsxj@.com> +
inital commit $ git cat-file -p 90e346
blob c694c68edd99aeefa053f25308cd71ecca922036 version.txt $ git cat-file -p c694c6
V1.

当我们git  push origin master(命令格式:git push [remote-name] [branch-name])时候会生成一个我们会发现.git/refs/文件夹下多了一个remote文件夹

我们跟进去看一下会有一个默认origin服务器名称,下面会有一个master分支,也就是这个代表的是远程服务器的master分支并不代表我们本地的master分支。看一下这个master分支内容和本地分支的内容是否一致,因为我们刚才将提交的内容提交到origin服务器上,应该两个分支引用指向的commit记录是一样的。

根据上面图中,标号1代表的是本地master分支指向的内容,而标号2代表的是远程服务器上面master分支只想的内容。(186c46正是我们的提交记录commit对象)
接下来我们的操作就是在进行添加一个本地内容修改下version.txt,修改内容为添加版本为v1.1。然后我们不提交到远程服务器上面看一下这两个master指向。当然不用猜就已经知道结果了,肯定指向的内容是不一样的。
修改文件后生成的blob对象

$ find .git/objects/  -type f
.git/objects//6c4629f6de8c956548570a113fa181d9b22692
.git/objects//e34626d7993cf8d6c5e3e458744df4a9a31594
.git/objects/9f/aadaec6f7c8657372544e6f414f9b0b6910279
.git/objects/c6/94c68edd99aeefa053f25308cd71ecca922036

提交到本地版本控制中。

$ git commit -m 'second commit version.txt'
[master 5777c82] second commit version.txt
file changed, insertion(+)

提交之后产生的commit对象和新的tree对象内容

$ find .git/objects/ -type f
.git/objects//6c4629f6de8c956548570a113fa181d9b22692
.git/objects//77c8270e24ff7417fa6f8d27f73c068acd42b0
.git/objects//e34626d7993cf8d6c5e3e458744df4a9a31594
.git/objects/9f/aadaec6f7c8657372544e6f414f9b0b6910279
.git/objects/a4/3a49679a6ecd3cbcdd889aeb9906b8620e7976
.git/objects/c6/94c68edd99aeefa053f25308cd71ecca922036

看一下了两个master分支内容:

$ cat .git/refs/heads/master
5777c8270e24ff7417fa6f8d27f73c068acd42b0 $ cat .git/refs/remotes/origin/master
186c4629f6de8c956548570a113fa181d9b22692

啊哈,果然不出我们所料,这就是说明本地提交的记录还没有提交的远程服务器上面所以说这个远程服务器的master分支还是指向了原来的commit对象。
当我们使用的了git   fetch  [remote-name]从服务器里面拉去数据的时候会产生一个FETCH_HEAD指针。这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。这时候我们会发现有一个FETCH_HEAD指针是一个指向远程最后一次获取的指针位置。首先我们看一下这个FETCH_HEAD指针的主要作用:

也就是说我们每次获取的本地没有的文件后都会有一个fetch_HEAD,这个指针和本地的HEAD指针有着区别,这样我们现在还看不出来因为本地和服务器上的记录都是一样的。这时候我们来在服务器上面添加一个readme文件提交上去,再在本地获取。
添加readme文件这里是在服务器上直接提交的记录,所以跟本地数据没有任何关系。

当我们使用git  fetch  origin命令的之后,我们来看一下.git/objects在服务器上产生的新的commit记录和tree对象还有git对象内容。

$ find    .git/objects/ -type f
.git/objects//6c4629f6de8c956548570a113fa181d9b22692
.git/objects//204399d2b99a020ac03dbca151570a959b7523
.git/objects//f565ecbaa66b236c42914bfd7e93a5eb0844f7
.git/objects//77c8270e24ff7417fa6f8d27f73c068acd42b0
.git/objects//e34626d7993cf8d6c5e3e458744df4a9a31594
.git/objects/9f/aadaec6f7c8657372544e6f414f9b0b6910279
.git/objects/a4/3a49679a6ecd3cbcdd889aeb9906b8620e7976
.git/objects/c6/94c68edd99aeefa053f25308cd71ecca922036
.git/objects/e0/26393257f8b7519ac7c378c6ff470ca737fe10

这里面有三个对象是git  fetch后新增加的就是如下几个,然后我们通过查看其类型以及其中的内容就能看到确实是从服务器上拉取出来的数据。

$ git cat-file -t
commit $ git cat-file -p
tree e026393257f8b7519ac7c378c6ff470ca737fe10
parent 186c4629f6de8c956548570a113fa181d9b22692
author BattleHeart <dwlsxj2013@hotmail.com> +
committer BattleHeart <dwlsxj2013@hotmail.com> + Create commit Readme Create commit Readme $ git cat-file -t 56f565
blob $ git cat-file -p 56f565
# BattleHeart
README $ git cat-file -t e02639
tree $ git cat-file -p e02639
blob 56f565ecbaa66b236c42914bfd7e93a5eb0844f7 README.md
blob c694c68edd99aeefa053f25308cd71ecca922036 version.txt

其实这时候我们来看一下git的历史记录图。

这里的lol命令是我取的别名log  –oneline  –decorate  –graph  –all。可以看到这个命令分了两个,就是说origin/master是服务器的master分支。我们来看一下master分支。

$ cat .git/refs/heads/master                       本地分支引用
5777c8270e24ff7417fa6f8d27f73c068acd42b0 $ cat .git/refs/remotes/origin/master 服务器master分支引用
50204399d2b99a020ac03dbca151570a959b7523

也就是说本地分支引用是没有变化的,变化的是服务器master分支引用的地址从186c46变化到了最新的502043这个commit提交记录上面了。其实这之后FETCH_HEAD也会将最新的commit记录在里面(这里不是指向master分支上而是指向了commit记录上面),也就是说FETCH_HEAD指的是: 某个branch在服务器上的最新状态。其中每一行对应于远程服务器的一个分支.当前分支指向FETCH_HEAD, 就是这个文件第一行对应的那个分支。这里服务器里面只有一个master分支是默认的分支。

虽然说拉去出来的数据但是并不是我们想要的,拉去的数据并没有放在本地仓库指向的内容里面而是服务器分支指向的内容里面。这时候我们是用git merge来进行合并。也就是说这个FETCH_HEAD里面存在的是服务器上每一个分支上面最后一个提交记录内容,当然我们也可以使用git  merge  FETCH_HEAD这个命令来合并分支,但是多条分支记录的时候他只会取出第一条merge记录。这时候我们就需要使用服务器的分支来进行合并了,比如origin/test指针就可以git  merge  origin/test。这与后面要讲的git  pull的区别就是从服务器上面获取下来的内容分支之类的不会直接合并到本地,而是自己去合并但是git pull是git pull = git fetch + git merge的操作。

git  pull命令:
接下来我们就来演示下git pull内容,首先我们在服务上面新建了一个空的仓库,把这个空的仓库拉到本地来,新建一个文件a,在文件a里面添加一条记录this is file a on local master,把他提交到本地仓库里面,我们看一下如下操作:
新建一个文件a并赋值。

$ echo 'this is file a on local master' > a

看一下文件内容

$ cat a
this is file a on local master

添加到暂存区内将添加的文件

$ git add .

将文件添加版本记录中去。

$ git commit -m 'local first commit'
[master (root-commit) 7358cc0] local first commit
warning: LF will be replaced by CRLF in a.
The file will have its original line endings in your working directory.
file changed, insertion(+) create mode a

这时候看一下产生的对象

$ find .git/objects/ -type f
.git/objects//da50374fa7eaa9d2ea609198237ed8af97c7e9
.git/objects//58cc0797e6bf72393ab54c543c6261784c27dc
.git/objects/7e/8f2d0c90cdd5dffd9bfb5f32604f74199725e4

分别查看一下这些对象的类型以及对象的内容:

$ git cat-file -t 34da50
tree $ git cat-file -p 34da50
blob 7e8f2d0c90cdd5dffd9bfb5f32604f74199725e4 a $ git cat-file -p 7e8f2d
this is file a on local master $ git cat-file -p 7358cc
tree 34da50374fa7eaa9d2ea609198237ed8af97c7e9
author BattleHeart <dwlsxj@.com> +
committer BattleHeart <dwlsxj@.com> + local first commit

这时候我们将新的文件提交到服务器上面。

$ git push origin master
Counting objects: , done.
Writing objects: % (/), bytes | bytes/s, done.
Total (delta ), reused (delta )
To https://github.com/dwlsxj/test.git
* [new branch] master -> master

OK提交成功了,这时候.git/refs就会生成一个remote文件文件里面有默认服务器名称origin文件夹,该文件夹下面保存了服务器上最新的master分支指向的内容。让我们来看一下:

$ cat .git/refs/remotes/origin/master               服务器master分支
7358cc0797e6bf72393ab54c543c6261784c27dc $ cat .git/refs/heads/master 本地master分支
7358cc0797e6bf72393ab54c543c6261784c27dc

这时候是一样的,因为服务器分支和本地分支是一样的。接下来我们在服务器分支上面修改下a文件如下图所示:

这时候我们会想到服务器上面会产生commit记录这时候服务器的master分支的指向就不再是本地这个指向了。
这时候我们也来修改下本地的a文件。添加文本内容为this is file a on local master second edit。提交到版本控制中。看一下所有的操作内容:
编辑文件a

$ vim a

将a文件添加到暂存区内容

$ git add .
warning: LF will be replaced by CRLF in a.
The file will have its original line endings in your working directory.

看一下新生成的git对象内容

$ find .git/objects/ -type f
.git/objects//da50374fa7eaa9d2ea609198237ed8af97c7e9
.git/objects//58cc0797e6bf72393ab54c543c6261784c27dc
.git/objects/7e/8f2d0c90cdd5dffd9bfb5f32604f74199725e4
.git/objects/af/cc87af98402de78840dc0737700a62345abff4

将修改的a文件提交到记录里面。

$ git commit -m 'local second commit on master'
[master warning: LF will be replaced by CRLF in a.
The file will have its original line endings in your working directory.
de7c4cd] local second commit on master
warning: LF will be replaced by CRLF in a.
The file will have its original line endings in your working directory.
file changed, insertion(+)

这时候我们来看一下提交记录的图,这时候HEAD指针是指向最新的master分支的,但是服务器的master分支则是指向原有的commit记录。

$ git lol
* de7c4cd (HEAD -> master) local second commit on master
* 7358cc0 (origin/master) local first commit

看一下产生的tree对象以及tree对象内容,还有commit对象。

$ find .git/objects/ -type f
.git/objects//da50374fa7eaa9d2ea609198237ed8af97c7e9
.git/objects//e33f7b7a44ad93bcb3a049075e666b9041f63c
.git/objects//58cc0797e6bf72393ab54c543c6261784c27dc
.git/objects/7e/8f2d0c90cdd5dffd9bfb5f32604f74199725e4
.git/objects/af/cc87af98402de78840dc0737700a62345abff4
.git/objects/de/7c4cd49e32f197afc6161d0d6f5e6d413212c8 $ git cat-file -t 66e33f
tree $ git cat-file -p 66e33f
blob afcc87af98402de78840dc0737700a62345abff4 a $ git cat-file -p afcc87
this is file a on local master
this is file a on local master second edit $ git cat-file -p de7c4c
tree 66e33f7b7a44ad93bcb3a049075e666b9041f63c
parent 7358cc0797e6bf72393ab54c543c6261784c27dc
author BattleHeart <dwlsxj@.com> +
committer BattleHeart <dwlsxj@.com> + local second commit on master

OK,到了这里我们就要开始见证奇迹的时候到了,因为我们同时修改了a文件都是从第一次提交的commit记录里面衍生出来的(服务器上和本地提交),接下来就是见证奇迹了。

$ git pull origin
remote: Counting objects: , done.
remote: Compressing objects: % (/), done.
remote: Total (delta ), reused (delta ), pack-reused
Unpacking objects: % (/), done.
From https://github.com/dwlsxj/test
7358cc0..67f70c5 master -> origin/master
Auto-merging a
CONFLICT (content): Merge conflict in a
Automatic merge failed; fix conflicts and then commit the result.

Pull之后我们先不着急看a文件的内容,我们先来看一下生成的对象内容。

$ find .git/objects/ -type f
.git/objects//da50374fa7eaa9d2ea609198237ed8af97c7e9
.git/objects//7f7359a768d3e98b65cd8b1558e09489d920b3
.git/objects//e33f7b7a44ad93bcb3a049075e666b9041f63c
.git/objects//f70c522e9e5b748445abbb41ea0cfa0fd171f9
.git/objects//58cc0797e6bf72393ab54c543c6261784c27dc
.git/objects/7e/8f2d0c90cdd5dffd9bfb5f32604f74199725e4
.git/objects/af/cc87af98402de78840dc0737700a62345abff4
.git/objects/de/7c4cd49e32f197afc6161d0d6f5e6d413212c8
.git/objects/de/fb97746b25d3963454d4ff69fc903956b12075
.git/objects/f5/537ea43f681442d2656105a2f348284181ef95

接下来就要看一下新增加的对象内容,其实我们猜想就能才想到肯定有三个对象是git对象和commit对象、tree对象因为这是在服务器上提交记录产生的。那么还多一个对象是什么呢?我们来看一下吧。

Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git cat-file -t 597f73 该对象是服务器上提交内容对象
blob

对象的内容如下

Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git cat-file -p 597f73
this is file a on local master
this is file a on server master

接下来67f70c是提交记录,是和上面blob一起的

Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git cat-file -t 67f70c
commit Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git cat-file -p 67f70c
tree f5537ea43f681442d2656105a2f348284181ef95
parent 7358cc0797e6bf72393ab54c543c6261784c27dc
author BattleHeart <dwlsxj2013@hotmail.com> +
committer BattleHeart <dwlsxj2013@hotmail.com> + this is file a on server master this is file a on server master

接下来是tree对象内容,都是服务器上第二次提交产生的。

Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git cat-file -t f5537ea
tree $ git cat-file -p f5537ea
blob 597f7359a768d3e98b65cd8b1558e09489d920b3 a
$ git cat-file -t defb97
blob

哎呦,这个对象叼了,这个对象是在本地产生的,产生的冲突文件,我们会发现我没有将Administrator这一行去掉是因为我们现在文件是由冲突的,我们可以看到master|MERGING

Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git cat-file -p defb97
this is file a on local master
<<<<<<< HEAD
this is file a on local master second edit
=======
this is file a on server master
>>>>>>> 67f70c522e9e5b748445abbb41ea0cfa0fd171f9

那么下来我们看一下commit的图是如何的:

我们发现origin/master分支指向也更新为了最新的记录。并且现在还是两个分支,因为还有冲突没有解决。这时候我们需要解决冲突在提交就好了。

并将其提交到记录里面这时候我们就会发现最后的commit图就合并到了一起。

Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master|MERGING)
$ git add . $ git commit -m 'merge'
[master 0dd66df] merge Administrator@USER-20150201IC MINGW64 ~/Desktop/rrr/test (master)
$ git lol
* 0dd66df (HEAD -> master) merge |\ | * 67f70c5 (origin/master) this is file a on server master * | de7c4cd local second commit on master |/ * 7358cc0 local first commit

最后来一张图清晰地告诉大家git fetch和git push的区别。

二、结束语

本篇文章分析完毕,希望各位能够喜欢并且指正里面的错误,分析的有不正确的就指出来。谢谢啦。

小丁带你走进git世界五-远程仓库的更多相关文章

  1. 小丁带你走进git世界一-git简单配置

    小丁带你走进git世界一-git简单配置 1.github的简单配置 配置提交代码的信息,例如是谁提交的代码之类的. git config  –global user.name BattleHeaer ...

  2. 小丁带你走进git的世界三-撤销修改

    一.撤销指令 git checkout还原工作区的功能 git reset  还原暂存区的功能 git clean  还没有被添加进暂存区的文件也就是git还没有跟踪的文件可以使用这个命令清除他们 g ...

  3. 小丁带你走进git的世界三-撤销修改(转)

    一.撤销指令 git checkout还原工作区的功能 git reset  还原暂存区的功能 git clean  还没有被添加进暂存区的文件也就是git还没有跟踪的文件可以使用这个命令清除他们 g ...

  4. 小丁带你走进git的世界二-工作区暂存区分支

    小丁带你走进git的世界二-工作区暂存区分支 一.Git基本工作流程 1.初始化一个仓库 git  init git  clone git仓库分为两种情况: 第一种是在现有项目或目录下导入所有文件到 ...

  5. 小丁带你走进git的世界四-重写历史记录

    一.git对象文件创建 开篇先补充一个知识点,就是比如我建立一个文件之后,使用git add就会生成一个git对象,但是git对象生成后可以在.git/objects里面对应,首先我们来初始化一个仓库 ...

  6. 小丁是怎样入门git的

    0x01前言 既然没有华丽的出场,那就平凡的分享,首先我要说明一点本篇文章针对Git初学者,对我自己学Git的资源的整合,其实本篇索引应该在我写Git系列文章的时候就紧跟着放上索引的,由于时间问题没有 ...

  7. Myeclipse如何使用自带git工具向远程仓库提交代码(转)

    Myeclipse如何使用自带git工具向远程仓库提交代码 第一步:将改动的代码标记 项目右键:team->synchronize workspace 点击确定 项目右键>add to g ...

  8. git如何删除远程仓库的某次错误提交

    git如何删除远程仓库的某次错误提交 如果远程仓库,能ssh访问,那就跟本地没什么区别   reset命令有3种方式   git reset --mixed 此为默认方式,不带任何参数的git res ...

  9. git关联github远程仓库的问题

    git关联github远程仓库的时候,报fatal: remote origin already exists. 导致这个问题原因可能是之前关联的时候关联错了,再次关联就不行了. 解决办法是: 1.将 ...

随机推荐

  1. 在 ML2 中配置 OVS flat network - 每天5分钟玩转 OpenStack(133)

    前面讨论了 OVS local network,今天开始学习 flat network. flat network 是不带 tag 的网络,宿主机的物理网卡通过网桥与 flat network 连接, ...

  2. ASP.NET Core 中间件之压缩、缓存

    前言 今天给大家介绍一下在 ASP.NET Core 日常开发中用的比较多的两个中间件,它们都是出自于微软的 ASP.NET 团队,他们分别是 Microsoft.AspNetCore.Respons ...

  3. “.Net 社区虚拟大会”(dotnetConf) 2016 Day 2 Keynote: Miguel de Icaza

    美国时间 6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开,美国时间6.8 是第二天, Miguel de Icaza 做Keynote,Miguel 在波士顿Xa ...

  4. 卡片抽奖插件 CardShow

    这个小项目(卡片秀)是一个卡片抽奖特效插件,用开源项目这样的词语让我多少有些羞愧,毕竟作为一个涉世未深的小伙子,用项目的标准衡量还有很大差距.不过该案例采用 jQuery 插件方式编写,提供配置参数并 ...

  5. MAVEN学习-第一个Maven项目的构建

    MAVEN安装成功之后就可以进行项目的构建和管理了: 为什么要用maven进行项目的构建和管理? 对于初学者来说一个最直接的也是最容易里的优点在于JAR包的管理,相对于以前开发一个项目的时候我们需要用 ...

  6. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  7. 新手学习web遇到的一些乱码问题

    在新手学习web网站学习的时候经常会遇到?????这种乱码,对于刚起步的菜鸟来说真的很头痛,很容易打击继续学的信心当然了对于菜鸟的我最近也遇到过乱码问题,沉浸其中不能自拔,爱的深啊!!!!!我所遇到的 ...

  8. Spark-shell和Spark-Submit的使用

    Spark-shell有两种使用方式: 1:直接Spark-shell 会启动一个SparkSubmit进程来模拟Spark运行环境,是一个单机版的. 2:Spark-shell --master S ...

  9. can't run roscore 并且 sudo 指令返回 unable to resolve host

    I'm using ubuntu14 LTS. Problems: 1. When run roscore, got a mistake and an advice to ping the local ...

  10. 冗余代码都走开——前端模块打包利器 Rollup.js 入门

    之前翻译过一篇文章,介绍了通过 ES2015 的解构赋值语法引入模块,可以让打包工具(browserify)最终编译出来的代码量最小化. 殊不知在 webpack 1.X 版本是无法利用该特性来避免引 ...