git的基础学习,本地版本管理。个人认为比较简单易懂~

       本人陆陆续续学了很多次git,但是多次又忘了。到最后还是只会在idea上,上传和推送自己的修改。最近又看了一个讲git讲的还不错的,至少自己隔了好多天还没忘,所以专门记录一下。

前传

       先说点废话(只是想学命令的,建议从中传开始看起)
       Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。
       Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?
       在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!
       你也许会想,为什么Linus不把Linux代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。
       不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。
       安定团结的大好局面在2005年就被打破了,原因是Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图破解BitKeeper的协议(这么干的其实也不只他一个),被BitMover公司发现了(监控工作做得不错!),于是BitMover公司怒了,要收回Linux社区的免费使用权。
       Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:
       Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。
       Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。
       历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的Git了。
       

原理1. git原理

       首先,git基于版本快照工作。
       Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个快照流。
在这里插入图片描述
       

原理2. git保证数据完整性

       Git 中所有数据在存储前都计算校验和,然后以校验和来引用。这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程中丢失信息或损坏文件,Git 就能发现。
       Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串,基于 Git 中文件的内容或目录结构计算出来。 SHA-1 哈希看起来是这样:

24b9da6552252987aa493b52f8696cd6d3b00373

       Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。

原理3. 版本丢失

       你执行的 Git 操作,几乎只往 Git 数据库中增加数据。 很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。 同别的 版本控制工具一样,未提交更新时有可能丢失或弄乱修改的内容;但是一旦你提交快照到 Git 中,就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。
       这使得我们使用 Git 成为一个安心愉悦的过程,因为我们深知可以尽情做各种尝试,而没有把事情弄糟的危险。

中传 – 很重要的概念: 版本库(仓库),工作区,暂存区,分支区

在这里插入图片描述

1.版本库(仓库)

       版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
       

2.工作区

       存放要管理的文件的位置

3.暂存区

       版本库中 包含暂存区 git add命令 或 git rm 命令加入的操作 被记录在暂存区内

4.分支区

       版本库中 包含分支区 是最终版本信息保存的位置 git commit命令将暂存区内记录的操作 提交到分支中
       可以配置多个分支,如果不指定则默认为master分支,并有一个head指针指向master分支的最新位置

1. 创建版本库

      首先,如果你想让你的文件被git管理,你要把你的文件夹声明成一个git文件夹。使用的命令是:

git init

       命令执行后,该目录下会多出一个.git的目录,这个目录是Git用来跟踪管理版本库的,请勿手动修改。
       git是一个很多人都可以用的版本管理工具,那么如何让其他人知道你是你呢?我们可以做一些配置

       首先设置user.name , 使用 git config --global suer.name “你想要设置的名字”即可

git config --global user.name "zhangsan"

       名字有时候会重复,所以还得设置邮箱。使用git config --global user.email 邮箱 即可。

git config --global user.email zhangsan@qq.com

       因为本次不是对git相关配置做讨论,所以仅仅简单介绍一下。

       查看自己的配置信息使用 git config --list

git config --list

       

2. 工作区和仓库

       可以将git管理的文件夹分为三个区域:工作区、暂存区、分支区。
       工作区可以理解为修改文件的区域。
       分支区可以理解为:提交了的文件(commit成功的文件)的区域。
       暂存区介于二者之间,可以理解成二者的过渡区。既能提交到分支区,也可以撤销到工作区。
       
在这里插入图片描述

3. 新增文件以及add和commit

       首先,我们随意写一个文件,就叫text01.txt。我们可以使用一个命令来查看一下git管理的文件夹下的变化。

git status

        这是对输出的内容进行的一个解释。
在这里插入图片描述
       因为我们新增了text01.txt文件,所以git提示我们有一个文件没有追踪(即这个文件无法被提交到分支区)。我们可以使用git add 文件名 命令追踪文件,追踪的同时也会将文件提交到暂存区。

git add text01.txt

同时,我们再次查看一下git的状态

git status

下面的图片上的第二行文字写错了,应该是 没有未提交的内容
在这里插入图片描述
       我们已经新增完了文件,同时也提交到了暂存区,接下来只要把他提交到分支区即可。
使用 git commit -m 相关信息 即可。 相关信息为这次提交的备注。

-m后面输入的是本次提交的说明,可以输入任意内容
  本例中只经历了一个修改就提交了,其实完全可以 多个修改后一次提交
git commit -m "add file test.txt"

再次查看版本库状态

git status

在这里插入图片描述
画图的话,现在版本库变成了如下状态:
在这里插入图片描述

4. 修改并比较文件

       首先对test01.txt进行修改。修改完毕后查看版本库状态

git status

在这里插入图片描述
画图的版本库状态如下:
在这里插入图片描述
       此时,我们可以查看文件的修改信息。使用git diff 文件名称 命令。

git diff test.txt

       我的电脑上,显示如下
在这里插入图片描述
       将文件添加到暂存区。

git add test01.txt

       查看状态

git status

在这里插入图片描述
       图片的版本库状态如下:
在这里插入图片描述
       此时,提交修改到分支。

git commit -m "change Git to git"

       再次查看状态

git status

在这里插入图片描述
       图片的版本库状态如下
在这里插入图片描述

5. 查看历史版本

       再次修改test01.txt。修改完后增加文件到暂存区。

git add text01.txt

       然后再提交文件到分支。

git commit -m "...some msg..."

此时已提交了多次文件到分支区,可以使用 git log 命令查看历史版本

git log

在这里插入图片描述

6. 回滚版本

       有一天,正在修改的时候,突然发现自己修改错了,需要回到以前某次提交的时候,这个操作叫回滚。可以使用如下命令:

git reset --hard HEAD^

       在Git中,用HEAD表示当前版本,上一个版本就是HEAD^, 上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

       如果懒得数往上第几个版本,也可以回滚到指定的版本号。

git reset --hard 5527510751b4303390bb4f321bfa8b7f997cbfd0

       懒得敲也可以敲前几个就行。

git reset --hard 55275

       回滚到以前版本,再次使用git log查看历史版本。

git log

       使用该命令会发现,只会显示当前版本及当前版本以前的版本;当前版本之后的版本查看不到。
       那么是不是说我们只能往前回滚不能往后回滚呢?
       当然不是的。
       使用git reflog命令可以查看所有的版本。

git reflog

       配合git reset 命令可以方便的回滚到任意版本。

7. 撤销修改

       回到原来。我们再次修改文件,但是发现修改错了,想撤销掉这次修改。可以使用 git checkout – 文件名。该命令会将工作区中的文件恢复到最近一次add 或 commit之前的状态。

git checkout -- test.txt

       我们继续修改文件,并将文件add到暂存区(还没有提交到分支区)。突然,我们发现又写错了…单独使用git checkout命令就不好使了。这时候,我们可以配合其他命令使用。
       首先,我们可以回滚到当前版本(回滚到其他版本时,暂存区中的文件将会消失,这样就清除了暂存区中的文件)

git reset HEAD test.txt

       然后再使用git checkout命令进行撤销。

git checkout -- test.txt

       这次,我们继续修改文件,将文件add并commit。然后发现又写错了…可以通过回滚的方式撤销掉本次修改。但是,即使回滚,使用git reflog仍然可以看到这次提交。所以,只要提交到了git的分支区,就不可能删除。

8. 删除文件

       我们发现某个文件无用,就删了它。

rm test01.txt

       当然也可以手动删除。删除过后查看版本库状态

git status

在这里插入图片描述
       将删除的文件增加到暂存区。使用git rm 文件名 命令。

git rm test01.txt

       当然,也可以使用git add命令。查看版本库。

git status

在这里插入图片描述
       将其提交到分支。

9. git管理和跟踪的是什么

       git跟踪并管理的是修改,而并非是文件。
       举个例子,首先,我们在test01.txt中新增一行文字:111111。
       然后将文件添加到暂存区中。
       再在test01.txt中新增遗憾文件:222222。
       然后提交到分支。
       然后查看版本库状态,会发现, 222222并未提交。

10. 命令总结

在这里插入图片描述

11. 通过tag指定版本标签名

       git中的版本都有版本编号,对代码的提交和回滚都是基于版本编号进行的,但是git中的版本编号是一串随机串,不好记忆,此时可以使用标签机制为某个提交增加标签,方便以后查找。大了标签之后所有需要用到版本编号的位置都可以用对应的标签替代。标签也可以理解成别名。
       首先,在当前分支的当前提交上打标签。

git tag v1.0

       也可以查看所有标签

git tag

       也可以将标签打到以前提交的版本上

git tag v0.9 f52c663

       还可以创建带有说明的标签。用-a指定标签名,用-m指定说明文字。

git tag -a v0.1 -m "version 0.1 released " 1094adb

       可以通过如下命令查看一个tag信息:

git show v0.1

       如果标签打错了,也可以删除

git tag -d v0.1

       如果要推送标签到某个远程,使用git push origin tagName。

git push origin v1.0

       也可以一次性将所有尚未推送到远程的本地标签全部推送过去。

git push origin --tags

       但是,如果标签已经推送到了远程,删除的时候就会麻烦了。首先要删除本地标签

git tag -d v0.9

       然后再从远程删除

git push origin :refs/tags/v0.9

12. 指定git忽略部分内容

       可以在仓库中配置.gitIgnore文件,在其中配置哪些文件是不需要git管理,则git在处理此仓库时,会自动自动忽略声明的内容。
       .gitIgnore文件格式:
       1)空格不匹配任意文件,可作为分隔符,可用反斜杠转义
       2)以“#”开头的行都会被 Git 忽略。即#开头的文件标识注释,可以使用反斜杠进行转义。
       3)可以使用标准的glob模式匹配。所谓的glob模式是指shell所使用的简化了的正则表达式。
       4)以斜杠"/“开头表示目录;”/“结束的模式只匹配文件夹以及在该文件夹路径下的内容,但是不匹配该文件;”/“开始的模式匹配项目跟目录;如果一个模式不包含斜杠,则它匹配相对于当前 .gitignore 文件路径的内容,如果该模式不在 .gitignore 文件中,则相对于项目根目录。
       5)以星号”“通配多个字符,即匹配多个任意字符;使用两个星号”**" 表示匹配任意中间目录,比如a/**/z可以匹配 a/z, a/b/z 或 a/b/c/z等。
       6)以问号"?“通配单个字符,即匹配一个任意字符;
       7)以方括号”[]“包含单个字符的匹配列表,即匹配任何一个列在方括号中的字符。比如[abc]表示要么匹配一个a,要么匹配一个b,要么匹配一个c;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配。比如[0-9]表示匹配所有0到9的数字,[a-z]表示匹配任意的小写字母)。
       8)以叹号”!“表示不忽略(跟踪)匹配到的文件或目录,即要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。需要特别注意的是:如果文件的父目录已经被前面的规则排除掉了,那么对这个文件用”!“规则是不起作用的。也就是说”!“开头的模式表示否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用”!"也不会再次被包含。可以使用反斜杠进行转义。
需要谨记:git对于.ignore配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效;
       因为markdown语法问题,有些符号可能会显示错误,故在下面附上图片版:
在这里插入图片描述

       示例:
# 表示此为注释,将被Git忽略
.a 表示忽略所有 .a 结尾的文件
!lib.a 表示但lib.a除外
/TODO 表示仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ 表示忽略 build/目录下的所有文件,过滤整个build文件夹;
doc/
.txt 表示会忽略doc/notes.txt但不包括 doc/server/arch.txt

bin/: 表示忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件
/bin: 表示忽略根目录下的bin文件
/.c: 表示忽略cat.c,不忽略 build/cat.c
debug/
.obj: 表示忽略debug/io.obj,不忽略 debug/common/io.obj和tools/debug/io.obj
/foo: 表示忽略/foo,a/foo,a/b/foo等
a/
/b: 表示忽略a/b, a/x/b,a/x/y/b等
!/bin/run.sh 表示不忽略bin目录下的run.sh文件
*.log: 表示忽略所有 .log 文件
config.php: 表示忽略当前路径的 config.php 文件

/mtk/ 表示过滤整个文件夹
*.zip 表示过滤所有.zip文件
/mtk/do.c 表示过滤某个具体文件

被过滤掉的文件就不会出现在git仓库中(gitlab或github)了,当然本地库中还有,只是push的时候不会上传。

需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中,如下:
!.zip
!/mtk/one.txt
唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。为什么要有两种规则呢?
想象一个场景:假如我们只需要管理/mtk/目录中的one.txt文件,这个目录中的其他文件都不需要管理,那么.gitignore规则应写为::
/mtk/

!/mtk/one.txt

假设我们只有过滤规则,而没有添加规则,那么我们就需要把/mtk/目录下除了one.txt以外的所有文件都写出来!
注意上面的/mtk/*不能写为/mtk/,否则父目录被前面的规则排除掉了,one.txt文件虽然加了!过滤规则,也不会生效!

还有一些规则如下:
fd1/*
说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;

/fd1/*
说明:忽略根目录下的/fd1/目录的全部内容

/*
!.gitignore
!/fw/
/fw/*
!/fw/bin/
!/fw/sf/
说明:忽略全部内容,但是不忽略 .gitignore文件、根目录下的/fw/bin/和/fw/sf/目录;主要要对bin/的父目录使用!规则,使其不被排除。
       因为markdown语法问题,有些符号可能会显示错误,故在下面附上图片版:

在这里插入图片描述
       

13. 总结

       git本地管理到此结束,本地管理的话,这些命令也基本够用
       1. 分清工作区、暂存区和分支区
       2. add是提交到工作区,commit是提交到分支区。一旦提交到分支区,永远不可能删除。即使回滚到以前的版本,仍然可以找到提交的信息。
       3. git log 查看当前版本的以前所有版本的信息,git reflog查看所有的版本的信息。
       4. git commit时,一定要好好写 -m 后面的信息
       5. 其实前面忘说了,如果觉得麻烦,可以使用 git add * 提交所有文件,也可以 git add /src 提交根目录src下所有文件。add的命令还是很灵活的。
       6. git指定忽略内容没必要背,知道有这么个东西,用的时候现查就行了。
       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章