这是我第二篇关于git使用的文章,承袭上一篇文章《git基本概念以及简单用法》地址是:https://www.cnblogs.com/lizhe-Ning/p/9162242.html
先说两句题外话,今天看到一位老师写的文章,内容相似。但是人家的文章一看就条理鲜明,思路清楚,格式工整规范。如果我是一个求助者,肯定喜欢读他的文章。这是我以后学习的对象与目标。我把他的链接贴出来希望能够帮助大家。http://bioinfostar.com/2018/06/15/%E5%AD%A6R%E5%AD%A6%E5%88%9D%E9%98%B6-03-R-Git%E5%92%8CGithub-1/,转载的时候才发现这位老师也是转载其他人的,为了避免间接引用我直接给出原作者的链接。
以下是我的笔记!!辣眼睛。我会改的,加油!!!!!!
PS:新学会了一个技能:在命令行中使用ls可以查看目录中包含可见子目录,与dir效果相似。使用ls -a命令能看到隐藏的目录。
Git文件
git资源库与普通文件夹不同之处就是,其中保存了自资源库创建以来资源库历史相关的元数据。以.git文件格式保存,通常情况下为隐藏目录。
初始化git仓库git init
在相应的目录输入命令git init,即可以初始化或者新建一个git仓库。git版本库必须初始化在一个已经存在文件夹中,可以使用
mkdir flode_name
cd flode_name
pwd
来新建一个名为flode_name的文件夹,pwd
命令用于显示当前目录。在Windows系统中,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。
新创建的git仓库中没有任何的commit。例子见图二。
图二初始化仓库示例
因为我创建的新目录是version-control路径下的recipes,所以我转到该目录下使用git init命令,初始化一个新的git库。(PS:该目录中已经包含三个文件了,分别是cake.txt,chili.txt和frosting.txt,三个文件。)
Git 的版本库和目录
每个 Git 版本库位于一个特定目录,即你运行了 git init 的目录中。以.git文件保存。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。在Git中还存在工作区,就是你在电脑里能看到的目录,比如我的recipes
文件夹就是一个工作区。
注意:你经常会看到,某个目录中的 Git 版本库仅包含或仅跟踪该目录中的某些,而不是所有文件。这是被允许的。因为可能发生改变的只有几个文件,其他文件没有发生变化。
状态命令 git status
git status:可以获得git仓库状态,仓库中有哪些文件,是否被追踪,有多少个commit,是否有初始commit。
图三状态命令的使用
从图中可以发现,新建的git目录中没有任何提交,并且没有被追踪的文件,有三个未被追踪的文件。
添加到储存区命令 git add
git add:将文件添加到储存区的命令。文件添加到git仓库机理:git会使用一个临时储存区的空间,文件先逐个进入该区域,添加到该区域后文件可以被打包commit。
图四添加到储存去命令
删除命令 git reset
git reset:删除暂存区中的文件。例如,如果你意外地添加了 lesson_2_reflections.txt,但不想提交它,请运行 git reset lesson_2_reflections.txt,此命令会从暂存区中删除该文件,但它仍在你的工作目录中。
- 第一种方法,如果只需要回到最近几次的版本,那么直接移动HEAD指针即可,回退一版:
HEAD^
,回退两版:HEAD^^
,依次类推;或者用数字表示:退N版:HEAD~N。 - -
hard
,顾名思义,硬删除,把之后所有的改动都删掉。 - 第二种方法,如果想要回到很久之前的一个版本,写
^
或者~N
都不合实际,那么可以用commit id,即hash码去回退,先用git log
去查看之前的commit,找到你想回退的那个版本id,然后reset。git reset --hard commitID。
对于丢弃工作区和暂存区的修改可以使用命令git checkout -- file。命令git checkout -- readme.txt
意思就是,把readme.txt
文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit
或git add
时的状态。git checkout -- file
命令中的- -
很重要,没有- -
,就变成了“切换到另一个分支”的命令
同样,git rest --head 命令放弃工作区和暂存区中所有更改!谨慎使用,因为没有办法撤回。
但是最近在读别人的博文时发现有这样一招,可以找回删除的commit。首先,得找到这个commit id,git reflog
可以记录你的每一次commit,不论是HEAD之前还是之 后,只要你commit过,它就记录下来了,然后再reset即可。经过简单测试发现果然好用,但是只能针对已经commit的版本。
图五删除命令示例
删除文件
上面介绍了怎样删除commit或者更改。同样,我们可以删除一个文件,一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm
命令删了,这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status
命令会立刻告诉你哪些文件被删除了,那就用命令git rm
删掉,并且git commit。
图五+ 删除文件
提交命令 git commit
使用git commit命令可以提交暂存区中的内容。使用git commit命令会打开默认的提交信息编辑器,在其中编辑commit信息。一般使用祈使句。git commit
命令执行成功后会告诉你,n file changed
:n个文件被改动;a insertions, b deletions
:插入了a行内容删除了b行。如下图所示。
图六提交命令示例
比较命令 git diff
git diff命令:"git diff ID1 ID2"命令可以比较两个commit之间的区别,这在上节课中讲过。其实,
Ø “git diff”(不加任何参数)命令可以比较工作区和文件暂存区(使用git add之后的文件)文件的不同,修改文件会在工作区进行修改,最新的更改没有提交到暂存区前,暂存区中存储版本库中最近的commit的副本。
Ø “git diff --staged”命令可以比较暂存区和版本库中文件的区别。
分支命令 git branch
补充一个概念,也是我在廖老师的博客中看到的:在Git里,这个分支叫主分支,即master
分支。HEAD
严格来说不是指向提交,而是指向master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。当我们创建新的分支,例如easy-mode
时,Git新建了一个指针叫easy-mode,指向master
相同的提交,再把HEAD
指向easy-mode,就表示当前分支在easy-mode上。不过,从现在开始,对工作区的修改和提交就是针对easy-mode分支了,比如新提交一次后,easy-mode指针往前移动一步,而master
指针不变看不懂就不要管这些东西。以后再看不捉急。
当只是修改bug时线性结构足已完成任务,如果想要实验一个新的功能,就可以创建分支。
分支分为两种:master分支,仓库中的主要分支,每次创建一个git仓库时就会创建一个maser分支;其他分支,因为其他目的创建的分支。
Git branch:创建和查看分支。
1. 当不带任何参数时,显示当前分支;
2. 以名字为参数时,可以创建一个新的分支;
3. git checkout -b new_branch_name:同时创建新的分支并且转到新的分支去。
图七 git branch命令示例
master分支旁边的星号代表是当前检出分支。同样可以使用checkout 加分支名命令可以转到相应的分支。
图八 git branch命令使用示例
在分支中进行的操作和在master分支中相同。如果提交成功的话,会有如下显示:
图九提交成狗界面
PS:我在easy-mode分支中,提交了一个commit。提交后第一行显示说明文件,第二行显示修改内容。最后使用git status命令查询状态时发现显示“没有要提交的文件,工作区没有文件”。因为修改的文件已经被提交了。
如果删除某个分支并导致无法从现有的分支访问一些提交,则在 Git 的垃圾收集过程运行之前,仍可继续通过提交 ID 访问这些提交。除非你主动关闭此过程,否则它将不时自动运行。也可以通过命令 git gc 手动运行此过程。
Git分支结构日志
git log --graph:使用该命令直观的查看分支结构;--oneline:使输出更短。使用这些命令时后面加上分支名,以明确可视化内容。
git只是记住每一个commit的ID和他们父节点,在检出(checkout)提交处不断向上寻找父节点,直到根节点。所以如果有版本分支的话,检出节点是分支中的节点,那么一定会有一些节点无法达到。这些节点是在该检出节点不可访问的。比如其他分支中的节点。
合并
将两个版本合并时遵循以下规则:
Ø 不同版本中都存在的部分一定保存;
Ø 一个版本中存在,另一个版本中不存在,且原始版本中不存在(即新加入的特性)应该得到保留;如果一个版本中存在,另一个版本中不存在,且原始版本中存在(即某一个版本因为某些原因删去该部分),这部分应该删去;
Ø 如果在两个版本中都存在但是内容存在差异,这时候会提示内容冲突(CONFLICT(content)),这时候需要手动来选择到底保存哪个。
打开有冲突的文件git会使用类似的标记标出不同代码段。并告知他们属于哪个分支,在这里进行修改,之后删除特殊的git行即可。
图十显示内容冲突后代开冲突文件显示画面
在没有修改冲突之前,使用git status会得到以下结果
图十一存在冲突时git状态
both modifie表明文件被修改了两次,两个分支都修改了文件由此产生了冲突
档把修改后的文件提交到暂存区后在使用git status命令得到
图十二保存到暂存区后git状态
图十二表明冲突已经被修复,现在仍然在合并中,使用命令git commit可以继续合并。
两个分支合并就是用两个分支中信息重新创建一个commit,新的commit的父提交是被合并的两个commit。所以对合并后的commit使用git log会显示两条分支上所有的commit,他们按照时间顺序排列。
合并命令 git merge
git merge branch1 branch2:合并两个分支。
要注意,在合并的版本中会包含当前检出的分支。因此,如果检出了 branch1,并且运行 git merge branch2 branch3,则合并的版本会将 branch1 以及 branch2 和 branch3 组合起来。由于在你进行合并提交后 branch1 标签将会更新,因此,你不想将 branch1 中的更改包含在合并中是不可能的。有鉴于此,在合并之前应始终检出你打算合并的两个分支之一。应检出哪个分支取决于你想让哪个分支标签指向新的提交。由于检出的分支始终包含在合并中,因此,你可能已猜到,在合并两个分支时,无需在命令行上将两者都指定为 git merge 的参数。如果想将 branch2 合并到 branch1 中,只需键入 git checkout branch1,然后键入 git merge branch2 即可。键入 git merge branch1 branch2 的唯一原因是,它能帮助你对要合并的分支更加心中有数。
另外,由于是合并两个分支,因此在命令行中按何顺序键入分支并不重要。关键是要记住,git merge 始终将所有指定的分支合并到当前检出的分支中,并为该分支新建一个提交。
当我使用git merge进行合并时,出现了错误,
图十三内容冲突
解决方法:
i. 运行 git merge --abort,将文件恢复到你开始合并之前的状态
ii. 仔细检查文件的状态。如果在检出 master 分支时运行 git log。
iii. 在文件处于正确的状态后,利用你所做的更改新建一个提交。
iv. 重新尝试合并。
真的是经历了几十次尝试才成功。有以下几个要点:
1. 文件一定不能使用tab,一定要用空格来调整格式。
2. 使用windows系统时需要设置git config --global core.autocrlf true。详情参考:https://help.github.com/articles/dealing-with-line-endings/#platform-all
3. 合并前一定要注意现在在那个分支中,有可能修改文件后,进入系统默认的创建的临时分支中,我就是这样老是失败。如果发现要合并分支最近的commit不是想要的,或者是错的。使用”git reset --hard HEAD~1“删除最近的commit,然后直接在分支下修改,提交,然后进行合并。(修改时切记不要检出某个commit然后修改,提交。这样新的commit不会保存在原分支中,而是储存在新建的一个临时分支中。)
终于成功了!!!开心。还有一点就是merge同样会让你写说明文档,但是其实里面已经有内容了,即“合并了。。。分支”。
与父级进行对比 git show
刚刚已经说了,合并之后所有的commit按照时间顺序排列,这真的不好,没法直接找到某一个commit的父版本,不利于比较和修改。基于此我们可以使用两种办法:
1. 删掉某一个分支中的所有标签。git branch dash d coins(分支名)。他不会删除分支中的提交,只会删除标签,这样的话很难找到他们
2. git show :git show command_id命令直接返回command_id提交与其父版本的区别。
在命令行中使用ls可以查看目录中包含可见子目录,与dir效果相似。使用ls -a命令能看到隐藏的目录。