git从零开始2
版本穿梭、分支和远端推送
在上一节中上一篇博客,我们讲解了本地项目文件在git中的提交过程和状态查询的方法,这一小节,我们将讲解版本穿梭、分支和远端推送。
版本穿梭
我们知道,git是一个版本管理的工具,那如何进行版本的管理呢?
在上一节中,我们提到,可以使用
1 | git reflog |
两个指令来查看版本的信息。我们可以从中获得版本的版本号。例如下图,版本号就是“b9f048a”(和第一节不一样了,因为我为了写博客重新建了一个项目),我们先修改一下文件,搞一个第二个版本,以便进行实验。
我们在hello.txt里面第一行末尾加上五个1.

然后我们重新提交,此时再用git reflog发现,存在了两个版本,版本号分别为“b9f048a”和“f892d81”

如果这时候老板觉得,不要这五个1,还是第一个版本好,我们就需要使用以下这个指令,回到第一个版本:
1 | git reset --hard b9f048a |

我们发现,版本已经回到第一个版本了,此时如果你回去看hello文件里的内容,五个1已经没有了! 需要注意,不是说回到第一个版本,第二个版本就没了!他还在呢!
实质上我们可以看到,是名为HEAD的指针指向了第一个版本号,因此版本才会回去了
现在我们可以来看看.git文件夹中的文件了,里面就有一个叫“HEAD”的文件,我们使用记事本打开,发现内容是:
1 | ref: refs/heads/master |

意思是说,这个HEAD指针所在的位置就是master分支
那我们能知道这个master分支是什么吗? 可以! 在.git文件夹中的这个路径下就有master文件,同样记事本打开查看,wow,恍然大悟了对吧! master指向的就是这个版本号!


所以总结一下, git中版本管理的底层其实是由两个指针决定的 :
head指针->master(分支)指针->版本
是不是一下就清楚了!
另外,如果要再回到第二个版本,也是执行同一个指令,只要把版本号改成第二个版本的就行了。
分支(branch)
分支是一个相当重要的功能(机制),例如在企业里,我们可以使用分支来管理一个软件的各个版本,例如测试版、正式版、公司内部版、上市版……对于个人开发,我们可以使用分支对一个项目中的文件内容进行分类,或者并行开发,我的博客为了在两台电脑上同步更新,就使用了分支的功能。简单来说,分支可以是copy的关系,也可以是父子关系,更可以是分而治之的思维……
分支的好处
分支机制由两个好处:
- 分支可以提高开发效率,促进并行开发
- 一个分支上项目出现问题,不会影响其他分支的内容,独立性。
查看/创建/切换 分支
查看分支的指令比较简单:
1 | git branch -v |

创建分支的指令很简单:
1 | git branch 分支名 |
例如这里,我创建了一个名为test的分支。使用查看的指令,就可以看到所有的分支:

切换的指令也很简单:
1 | git checkout 分支名 |
例如这里,我们切换到test分支,此时后面括号后的分支名提示我们,已经切换到test分支了。

但是以下要注意的是,我们可以看一下test分支里面有什么。其实,创建分支默认就是 拷贝master分支 ,所以创建初始,test里面也有一个hello文件,且内容完全一样。但是,我们可以开始尝试修改test分支了。例如,我们这里在hello文件中的第一行末尾写上5个a.然后提交。


此时,test分支就已经和master分支不一样了, 即使在windows的文件夹中,文件内容也有5个a了,他们俩就像双胞胎。但如果我们再切换回到master分支,文件内容会是什么呢,其实也很好猜,5个a会消失!所以,我们只要切换版本,直观上,明明你没有对文件夹做什么操作,里面的文件却能够改变,很神奇吧!

要说的是,底层上,其实只是指针发生了改变
当我们创建并切换到test分支时,head指针就从master改变指向指到了test。
head->test->版本
合并分支
企业中,我们可能创建一个分支的目的,是为了给一个软件开发新的模块或者插件等等,当我们开发完之后,可能就要把分支和主分支合并了,从而给软件添加新的内容,这就是合并分支的作用。
命令非常的简单:
1 | git merge 分支名 //把指定的分支合并到当前的分支上 |
这里有一点要注意,注释的意思有两点信息:
- “分支名”是指定的分支
- 当前分支会添加新的内容,但“指定的分支”自身的内容并不会改变
但是,合并分支存在两种情况,正常合并和冲突合并。
正常合并
正常合并其实没有什么好说的,命令就是上面提到的“merge”。我们来尝试一下:

再次查看一下hello中的文件内容,会发现master中的hello也有了5个a
冲突合并
冲突合并实际才是最为常见的情况,怎么样会发生冲突呢?就是我对两个分支中的“ 同一个地方 ”做出不同的修改,此时要合并,git就会搞不懂了,因为它不知道要保留哪一个作为最终版本。在企业中,A和B对代码有不同的修改,此时就会产生这样的冲突,接下来我们试验一下。
要注意的是,不同版本的git对“同一个地方”的概念不同,低版本的git认为同一个文件时同一个地方,但是高版本的git会认为文件中同一个代码行才是同一个地方。
我们先在master分支中,文件第一行最后末尾加上“master”,再在test分支文件第一行末尾加上“test”,(注意改完都要重新提交),然后合并。
此时发现,git提示冲突!而且子啊括号中,变成了 (master|merging),这种情况要怎么解决呢?

我们可以此时打开hello文件看看。

其实git就提示你,冲突的地方在哪里了,我们只需要手动删除和保留内容就可以了。
例如我只想保留“master”,我就只要删掉提示符号和“test”即可。然后重新提交。大功告成。

接下来我们测试一下,如果不是修改同一行会怎么样。
我们先在master分支中,文件第一行最后末尾加上“master”,再在test分支文件最后行末尾加上“test”,(注意改完都要重新提交),然后合并。
我发现,在我这里,仍然会出现冲突,且提示的文件变成了这样:

但我的git应该是最新的版本,所以上面的说法可能存在不对的地方,git对于同一个位置的定义,就是一个文件。
链接远端
创建远端库
鉴于本博客的主要内容是git,在这里不讲述如何使用github。
但在本地库链接远端库之前,是需要在github(或者别的远端代码托管平台)创建一个远程库,而且建议,库的名字最好和本地库一样,便于记忆。
在创建了远程库之后,github会提供给我们两个库的链接,一个是http,一个是ssh,我们先用http。
接下来,我们来把本地库和远程库链接起来,指令很简单:
1 | git remote add <别名> <链接> // |
- 这个别名是因为链接比较复杂,所以给链接起个别名,这里建议也是取库的名字,便于记忆

使用
1 | git remote -v |
可以查看现在有的链接。
欸,你会发现,明明我只链接一个链接,为什么会有两个(一个fetch,一个push)。害,一个拉取一个推送嘛,双向通道咯,不过fetch是包含了clone和pull两个方式的。
推送
推送的指令很简单:
1 | git push <别名> <分支> |
- 这里要注意,别名就是那个链接,然后git推送的最小单位是分支,所以要加上分支名

- 这里可能有人会弹出登录界面,这才是正常的。因为我在github上设置了ssh免密,相当于github已经认识我这台电脑了,所以可以直接传上去。
现在,远程库就有我们的文件啦。

拉取
如果远程库中的内容有改动,我们就要拉取新的内容到本地库,操作时类似的:
1 | git pull <别名> <分支> |
克隆
我相信克隆应该时大家最常见的操作了吧,毕竟,白嫖最香了。
1 | git clone <远程库地址> |
git clone 并不需要登录github,且会做三件事:
- 拉取代码
- 初始化本地仓库
- 创建别名
总结
这一节我们讲了版本穿梭,分支,和远程仓库的连接,其实这已经包含了大部分的内容了,接下来,我们会接触到团队协作,还有就是使用IDEA集成git,挥这个之后,我们甚至不用打命令了。大家下次见!