赞
踩
目录
不知道你有没有遇到这样的情况:我们写的文档,经常会需要进行修改,但是为了防止之前的文档丢失,我们不得不创建多个副本,并且命名为 :文档1.0 文档1.1 文档1.2等等,每个版本都会有所不同,且最终只会有一个版本被我们所使用。
但是因为之前的工作需要这些不同版本的文档,于是我们就会不断的复制粘贴,但是这样就会有个一问题,产生的文件会越来越多,不过更为重要的是,你还能记住这些文件做了哪些改动吗?
文档如此,我们的项目代码也会有这样的问题。
为了方便我们管理不同版本的文件,有人便创造了版本控制器。所谓的版本控制器,就是能让你了解到一个文件的历史及其发展历史。通俗的讲就是一个可以记录工程的每一次改动和版本迭代的管理系统,同时能方便多人协作。
说到版本控制器,就不得不提起git,git是目前最为主流的分布式版本控制器。git可以控制电脑上所有形式的文件,例如doc,Excel,dwg,dgn等等,对于我们开发人员而言,git最重要的就是帮助我们管理软件开发项目中的源代码文件!
注意事项:git只能跟踪文本文件的改动,比如txt文件,网页和所有的源文件等,版本控制器可以告诉你每次的改动,比如在xx行增加了一段文字,在xx行删除了一段代码。
而图片,视频等二进制文件,虽然也能够由版本控制器来管理,但是没有办法跟踪文件的改动,只能把二进制文件的每次的改动串起来,也就是仅仅能够知道图片从100kb变成了120kb,但至于到底改动了什么,版本控制器是不会知道的。
git是开源的代码托管工具,最早是在Linux下开发的,早期的时候也只能用于Linux平台,后面才慢慢被移植到windows系统下,如今git已经能够在各大平台下使用了。
Linux-Centos
在Linux-Centos的平台下,安装git是非常简单的,你可以先看看自己的平台有没有安装git
像这样的就是已经安装好了git,如果你的电脑没有出现git的版本,也不用担心,可以输入这样的指令:
注意一定要用sudo,紧接着就会给你安装git了,只需要稍微等待一下即可。在安装好git后,同样可以进行我们上一步的操作来看看git的版本,以确保git是安装好的。
我们首先要清楚一点,仓库是进行版本控制的一个文件目录,我们要想对文件进行版本控制,必须要有这样的一个仓库,而且以后我们的操作必须把要管理的文件放入该仓库中,git才能帮我们进行文件版本的管理。
创建一个仓库的命令是:git init
像这样,我们在预先创建好的文件夹git_12_4中输入git init就能帮我们创建一个空的仓库,
在这个空仓库中,我们能够看到一个.git的隐藏目录文件,.git目录是GIT用来跟踪管理仓库的,我们一定不要手动更改这个目录中的任何文件,不然一旦乱改,就会把GIT仓库给破坏掉,这样这个仓库就不能够使用了。
安装完git后,我们首先要做的就是设置你的用户名称和email地址,这个是非常重要的,下面是配置的命令:
其中--global是一个可选项,如果使用了该可选项,表示这台机器上的所有git仓库都会使用这个配置,如果你希望在不同的仓库使用不同的name和email,那么就不要加上这个选项。值得注意的一点是,在配置的时候一定要在仓库里。
当我们配置完仓库后同样可以查看仓库的相关配置,只需要用git config -l就能够看到相关的配置信息了。
既然可以配置,那么当然也可以删除配置
通常情况下,这样就能够删除配置了,但是为什么我这里没有删除成功呢?因为我们前面在配置的时候,使用了--global选项,所以在删除的时候也需要加上--global才能删除,那么在这里我就不给大家做演示了。
工作区:是能够被git仓库所管理的目录,通常我们会在这里开发程序代码,他和.git在同一级目录下存放。
暂存区:英文叫做index或者stage,一般会存放在.git目录下的index文件,所以我们有时候也会把暂存区叫做索引。
版本库:这个是真正的git仓库,工作区有⼀个隐藏目录?.git ,它不算工作区,而
是Git的版本库。这个版本库里面的所有⽂件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。下面的图片很好的展示了三者之间的关系:
其中左侧就是工作区,右侧为版本库,git的版本库中存放了许多东西,其中最重要的就是暂存区。
在创建git版本库的时候,git会为我们自动创建一个唯一的master分支,以及一个指向master的指针HEAD(这个我们在后面再详谈)
当我们对工作区进行修改的时候,如果使用了git add . 命令,暂存区目录树中的文件索引会被更新
当使用git commit时,master分支会做出相应的更新,可以理解为暂存区的目录树才会被真正的写到版本库中
所以从上述描述中,我们可以知道:通过新建或者粘贴进目录的文件,并不能被称为向仓库中新增了文件,而只能说是在工作区中添加了新文件,必须要使用git add和git commit真正的将工作区中的内容添加到仓库进行管理。
我们首先在包含.git文件的目录下(也就是和.git同级的路径)创建一个新文件Readme,然后就可以使用git add命令将工作区中的修改添加到暂存区中了
使用git add添加到暂存区中
•添加⼀个或多个⽂件到暂存区: git add [file1] [file2] ...
• 添加指定⽬录到暂存区,包括⼦⽬录: git add [dir]
• 添加当前⽬录下的所有⽂件改动到暂存区: git add .在使用git commit将暂存区的内容添加到本地仓库中
• 提交暂存区全部内容到本地仓库中:? git commit -m "message"
• 提交暂存区的指定⽂件到仓库区: git commit [file1] [file2] ... -m "message"注意:commit后面的-m选项以及他后面的message,这一部分一定不能省略,并且要好好描述,这部分是用来记录你的提交细节的,能方便我们后续的版本查看
git commit 命令执⾏成功后会告诉我们,1个⽂件被改动(就是我们新添加的ReadMe⽂件),然后可以使用git status来查看git仓库当前的状态,可以看到,目前没有东西需要提交,而且工作区是干净的。
我们在git add的时候可以写文件的名字,表示只要添加哪几个文件,但是在git commit的时候,是一次性提交所有在暂存区中的文件
截至目前为止,我们已经能够将代码提交到本地仓库中了,那么我们可以用git log来查看历史提交记录:
该命令是从最近的的提交记录开始显示,如果你觉得太过眼花缭乱,可以试试加上--pretty=oneline这个选项,这样就能够看得清晰一些了!
但是我们会发现git log中会有一长串的数字,这是其实是每次conmmit提交的时候版本号,我们也管他叫做commit id,这个数字不是从小到大递增的,而是git自动给我们通过某种算法计算出来的一个非常大的数字,然后用十六进制来表示
先来看看我们的.git目录结构:
可以看到我们刚刚说的几个都在这里面,比如index,HEAD,master等
(1)index就是我们的暂存区,add后的内容都是添加到这里的
(2)HEAD就是我们默认指向master分支的指针
(3)默认的master分支就是我们最近一次提交时候的commit id
(4)objects其实就是git的对象库,里面包含了创建的各种版本库对象及内容。当执行git add命令的时候,暂存区的目录树被更新,同时工作区修改的文件内容被写入到对象库的一个新对象中,就位于.git/objects目录下,让我们来看看这些对象有什么用处:
查找objects的时候需要将commit id分为两个部分,前2位是文件夹名称,后38位是文件名称,找到这个文件后一般不能直接查看文件的内容,因为该类文件是通过安全哈希算法加密过的文件,好在我们可以用git cat-file 命令来查看版本库中对象的内容
那么我们在这可以看见这就是我们最近的一次提交!
我们通过一步一步的从master往下查看,首先是看到了最近一次的commit id,然后再通过这个commit id看到了最近一次的提交信息,而在这个提交信息下有一个tree后面的长数字,我们用同样的方法,通过这串数字看到了每次提交对哪些文件进行了修改,以及他修改的id,最后通过这个id我们看到了上次对Readme文件的修改内容!!!
我们这里说的十分复杂,但能帮助我们更好的理解到git是如何存储的,如果你感到对这段很抽象,也可以不用考虑这些,只需要记住git中所有的文件,提交记录和分支都是以对象的形式存储的,而且每一次的commit提交都是这一次新建对象的id,通过这个id我们就能够看到提交的内容。
总结一下:
index:暂存区,git add后会更新这个区域的内容
HEAD:默认指向当前分支的一个指针
refs/heads/master:文件里保存着master分支当前最新的commit id
objects:包含了创建的各种版本库对象及内容,可以简单的理解为存放了git所维护的所有修改
学习到这里,我们已经对基本的操作有了了解,知道了如何向仓库中中添加文件,而且对于工作区,暂存区和版本库都有了一定了认识。那么我们再来展示一种添加文件的场景,能加深对工作区,暂存区和版本库的理解:
我们在这里创建了两个文件file1和file2,但是为什么只显示一个文件被修改呢?
我们来回忆一下,git add是将文件添加到暂存区,git commit是将暂存区中的内容提交到本地仓库中。由于我们并没有使用git add将file2添加到暂存区中,file2就不会在暂存区中维护,所以我们commit的时候仅仅只是把在暂存区中的file1提交了,而遗漏了工作区中的file2,那么如何提交file2呢?很简单,只需要在按照流程对file2进行git add和git commit就可以了。
GIt比很多的版本控制器都优秀许多,因为git跟踪并且管理的是修改而非文件
什么是修改?比如你新增了一行代码,删除了一行代码,或者是创建删除一个文件,这些都被称为修改。
下面我们来对Readme进行一点修改:
那么现在,仓库中的Readme和我们工作区中的Readme是不一样的,我们可以使用git status来查看当前的状态,从而知道在上一次提交后有没有对工作区进行修改
这里,他提示我们Readme文件被修改了,但是还没有完成添加和提交。
而且我们现在只知道文件被修改了,但至于是哪里被修改了,怎么样修改的你知道吗?时间一长我们很难再记住每次的改动了,于是乎git diff就诞生了,它能够显示暂存区和工作区之间的差异,显示的格式是,UNIX通用的diff格式。
当然也可以用git diff HEAD --文件名来查看版本库和工作区文件的区别
当然因为我们这里的暂存区和版本库中的内容是一样的,所以显示的并无差别。
我们通过git diff这个命令查看文件有什么修改再来提交到版本库就会放心多了
最后,我们在把他提交到版本库中就完成了一次的修改啦。
之前我们也提到过,GIT能够管理文件的历史版本,这也是版本控制器的最为关键的能力,如果有一天你发现近日做的工作出现了很大的问题,需要在某个特定的版本重新开始,这个时候就需要版本回退的功能了。
git reset是版本回退的命令,可以指定回退到某一次版本。要解释一下,版本回退的本质是将版本库中的内容进行回退,对工作区和暂存区是否回退取决于他后面的选项
git reset 命令语法格式为: git reset [--soft | --mixed | --hard] [HEAD]
• --mixed 为默认选项,使用时可以不用带该参数。该参数将暂存区的内容退回为指定提交版本内容,工作区文件件保持不变。
• --soft 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
• --hard 参数将暂存区与⼯作区都退回到指定版本。切记工作区有未提交的代码时不要⽤这个命令,因为工作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
对于HEAD的说明:
1.可以直接写成commit id,表示退回到某一次提交时候的版本
2.HEAD表示当前版本
3.HEAD^表示上一个版本(有几个^表示上几个版本)
4.同样也可以用~数字来替代^,如:HEAD~3就表示三个版本前
为了方便测试版本回退的功能,我们先对Readme进行三次的修改提交
现在我们有了三个版本的修改,如果突然发现第三个版本写乱了,需要回到第二个版本重新开发,由于我们希望的是工作区也回退到第二个版本,所以我们这次可以使用--hard选项
我们现在就能够看到Readme文件已经回退到了第二个版本了!然后我们再来查看HEAD指针的内容,竟然神奇的发现他刚好是第二个版本的commit id!!
到这里一般的版本回退功能就演示完成了,但是如果我又突然后悔了,想回到第三个版本怎么办?我们同样可以使用git reset来回到第三个版本,但是我们必须要拿到第三个版本的commit id,可以看到,我们目前是站在第二个版本上,所以git log并不能看到第三个版本的commit id,如果运气好的话,我们还能够从机器上看到之前的记录,但是运气不好的话,这个commit id就被我弄丢了,幸好git还提供了一个git reflog命令,它记录了本地的所有命令
像这样:
这样,我们就能够很方便的在各个版本之间进行切换了,但是为什么这里的commit id只显示了这么一点点呢?其实这就足够了,我们在版本回退的时候只需要输入者一部分的commit id就能够回到某个版本了。
可往往是理想很丰满,现实很⻣感。在实际开发中,由于长时间的开发了,导致? commit id ?早就找不到了,可突然某⼀天,我⼜想回退到?version3,那该如何操作呢?貌似现在不可能了。。。
值得说的是,Git的版本回退速度非常快,因为Git在内部有个指向当前分⽀(此处是master)的HEAD指针, refs/heads/master 文件里保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解成如下示意图:
情况一:
如果仅仅在工作区中进行了修改,但是还没有add和commmit,如何将工作区的代码恢复呢?
我们可以使用git checkout -- 文件名,让某个文件恢复。要注意:--非常重要,一定不要写掉了,因为一旦写掉git checkout就变成了另外一个命令了(我们后面在分支的时候讲到)
情况二:
如果已经add但是还没有commit,即文件的修改已经保存到了暂存区,该如何撤销修改呢?
我们先来回顾一下git resset,他是帮助我们进行版本回退的命令,默然情况下是--mix选项,就能够帮我们把暂存区和版本库中的内容回退,但工作区中的修改保持不变。那么我们就能够回退掉暂存区中的内容了!
在完成这个操作后,我们可以看到,现在暂存区已经干净了,但是工作区仍然有修改,你还记得我们之前是如何丢弃掉工作区的修改的吗?
现在我们就把情况二的问题解决了
但是其实还有更好的方法:就是直接用git reset --hard commit id让工作区和暂存区以及版本库都回退到某一个版本
已经 add ,并且也 commit 了
不要担⼼,我们可以 git reset --hard HEAD^ 回退到上⼀个版本!不过,这是有条件的,就是你还没有把⾃⼰的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后⾯会讲到远程版本库,⼀旦你推送到远程版本库,你就真的惨了……
在git中,删除也是一个修改操作,我们现在来实战一下看看:
如果仅仅是这样,那么只是修改了我们的工作区和暂存区,但是对于版本库是没有修改的,所以我们只需要再git commit到版本库就完成了删除工作了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。