版本穿梭、分支和远端推送

在上一节中上一篇博客,我们讲解了本地项目文件在git中的提交过程和状态查询的方法,这一小节,我们将讲解版本穿梭、分支和远端推送。

版本穿梭

我们知道,git是一个版本管理的工具,那如何进行版本的管理呢?
在上一节中,我们提到,可以使用

1
2
git reflog
git log

两个指令来查看版本的信息。我们可以从中获得版本的版本号。例如下图,版本号就是“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. 分支可以提高开发效率,促进并行开发
  2. 一个分支上项目出现问题,不会影响其他分支的内容,独立性。

查看/创建/切换 分支

查看分支的指令比较简单:

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 分支名 //把指定的分支合并到当前的分支上

这里有一点要注意,注释的意思有两点信息:

  1. “分支名”是指定的分支
  2. 当前分支会添加新的内容,但“指定的分支”自身的内容并不会改变

但是,合并分支存在两种情况,正常合并和冲突合并。

正常合并

正常合并其实没有什么好说的,命令就是上面提到的“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,且会做三件事:

  1. 拉取代码
  2. 初始化本地仓库
  3. 创建别名

总结

这一节我们讲了版本穿梭,分支,和远程仓库的连接,其实这已经包含了大部分的内容了,接下来,我们会接触到团队协作,还有就是使用IDEA集成git,挥这个之后,我们甚至不用打命令了。大家下次见!