git 学习(1) ----- git 本地仓库操作

  最近在项目中使用git了,在实战中才知道,以前学习的git 知识只是皮毛,需要重新系统的学一下,读了一本叫  Learn Git in a Month of Lunches 的书籍,这本书通俗易懂,使我对git 有了全面的认识。

  在平时,我们常常听到git 和github,它俩总是一起出现,总有一种必须一起使用的感觉。实际上,git和 github 是两个不同的概念, git是一个版本管理工具,而github则是一个网站,主要用于保存代码,分享代码。它们 之间没有必然的联系,可以使用其中的任意一个。如果我们只在自己电脑上开发项目,不用共享,只使用git进行版本管理就可以了,没有必要使用github. 如果我们想要分享项目,也可以只使用github, 在github上网站,我们可以直接把源代码拖动到网站,就像qq 邮箱拖动文件一样。当然说它们一点联系都没有,也不可能。git 和github 组合使用,通常用于大型的多人协作的项目。比如react, vue 等项目,多人协作,就要把代码放到一个大家都能找到的地方(gitHub)上,每个人在进行开发的时候,就要进行版本管理,和github 进行通信,那就要用到git命令。我们先学习git。

  git是一个版本管理工具,那什么是版本?版本为什么要进行管理?版本,我想大家都听说过,webpack有1,2,3,4 四个大版本。为什么会有这么多的版本?因为每一个版本就是一个变化,bug 修复,增加功能啊。如webpack2, 直接支持import,进行treeshaking, webpack4 提供了零配置的功能。这么多版本肯定要进行管理。这可能有点抽象,想一想我们平常的业务开发也是一样。我们写了一段代码,实现了一个功能, 但有时觉得代码实现方式不太好,就进行重写,但是引入了bug, 就想重新回到原来的代码?但由于变动太大,代码回不去了, 这时就想,要是把以前的代码保存一份该多好。修改代码之前保存一下,如果修改失败,可以进行回退。每一次的代码修改都是一次变化,git 就是用来帮我们管理这些变化的

  在windows上使用git, 相对比较麻烦,要先安装git, 百度一下git for window,或直接输入网址 https://gitforwindows.org/

  点击Download, 下载下来是一个.exe文件。双击进行安装。安装则比较简单,就是一路next. 安装完成后,桌面上通常会有一个git快捷方式, 同时点击鼠标右键,也会有git bash 和git GUI 命令。

  右键点击git bash 或双击快捷方式,就可以打开git bash的窗口,使用git 命令。

   Git 是管理变化的,最基本的就是要告诉git 是谁做出了这个改变, 所以在使用git 之前要先配置user.name, user.email,就是用户名和邮箱

    git config --globle user.name “sam”  

    git config --globle user.email “105778@qq.com”

  配置之后,可以看看有没有配置成功. 使用git config user.name, git config user.email  可以看到你刚才配置的信息。其实还有一个git config --list 命令,可以看到所有的git 配置,配置成功后,就可以学习git 了。 我们新建一个项目,就是文件夹,比如, git-learning来学习git.

  进入到git-learning 文件夹中,单击右键,出现的菜单中有一个git Bash Here,单击它,就会出现git bash 窗口。

  现在要输入的第一个命令就是git init, 它会在我们的文件夹中创建一个git 仓库, 此后git就可以追踪整个文件夹的变化,帮助我们管理整个项目了。输入git init ,按回车键,

  提示初始化了一个空的git 仓库,也就是创建git 仓库成功。但你会发现文件夹中什么也没有发生,还是空空如也,哪有创建git 仓库? 这主要是因为,它创建的git 仓库是一个.git 文件夹,window 默认不显示点开头的文件夹。Win10下,在文件夹上面有一个“查看”标签,点击,从右侧数,倒数第二个面板(显示/隐藏)中有一个 “隐藏的项目”复选框,勾选即可,这时看到.git 文件夹。.git文件夹就是git版本库,整个文件夹中所有的变化都放到它这里。所以这个文件夹至关重要,千万不要动它,此时,我们的git-learning 文件夹也称之为工作区,就是我们工作的地方,可以增加,删除文件。

  

  现在git 仓库创建成功,我们终于可以看看git 是怎么追踪变化的。在git learning 文件夹中创建一个index.html 文件,可以用touch index.html命令。查看变化的一个命令是git status, 使用git status 可以看到工作区发生了哪些变化

 

  可以看到Untracked files: index.html, index.html 没有被追踪, 也就是说git 已经检测到工作区新增了一个文件index.html. 怎么才能被git 追踪? 它提到了一个命令git add, 我们来使用一下这个命令, 它后面参数就是我们要add的文件名,在这里是index.html   git add index.html, 可以发现什么都没有发生,这时我们再查看一下状态:

  Changes to be commited, 这个变化可以被提交,指的就是index.html这个文件可以被提交(说明 git add 命令执行成功)。这里要使用的命令是git commit, 注意这个命令有一个参数-m 表示要添加的注释,提交一个变化,要说明其原因,为什么要提交,要不然提交它做什么。git commit -m '', 引号里面就是注释

  可以看到提交成功,再来查看一个状态 git status

  没有什么要提交的了,工作树是干净了。

  现在来简单回顾一下我们的操作,先创建一个index.html文件,然后git add 命令,让git 去追踪,最后git commit 提交变化,用git status 可以随时查看状态。你可能会有疑问,git add 把文件添加到什么地方了,git commit 提交,又把文件提交到什么地方了。这其实涉及到了git 的三个区:工作区, 暂存区, 版本区(git 仓库)。我们在工作区创建了一个index.html文件,然后调用 git add 命令, git add 命令就是把文件增加到暂存区,然后git commit , git commit 就是把文件提交到git 仓库。

  在工作区和版本区中加了一层暂存区,作为过渡, 显得更为灵活. 比如我们开发一个功能,不可能一次完成, 需要多次修改才能完成. 这时我们不可能把未完成的代码,直接提交到版本库,但有了暂存区之后,我们可以提交到暂存区,暂存区同样可以保存我们的代码,暂存区又没有提交到工作区,它不会影响到成熟的版本区. 这样就同时保护了工作区和版本区。

  我们把变化(改变的文件)提交到git仓库,git 就会把当前的变化保存起来,形成一个快照。git commit 就是告诉git 仓库 把当前状态保存一下。每提交一次,它就会保存一次,形成一条一条的历史快照,这样我们就可以版本来回切换。查看提交记录是用git log 命令。

  这里还有一个git ls-files 命令,可以查看版本库的内容。

  这时也可以看到git 仓库中有了index.html ,也表示我们提交成功了。

  现在我们再对index.html 进行修改,看看git 又是怎么追踪变化的文件的? 用编辑打开index.html, 输入html 模版。然后再用git status 查看状态

  Changes not staged for commit, stage就是缓存,变化没有提交到缓存区。他提供了后续的两个动作,一个是git add 提交到缓存区,一个是git checkout -- 放弃更改。当然,我们这里还是使用git.add 提交到缓存区。不过,在提交到缓存区之前,我们最好要看一下文件做了哪些改变,是不是我们想要做出的改变,这里的命令是git diff 

  可以看到git diff 把所有的更改都显示出来了。difff --git a/index.html  b/index.html  以 git 的方式显示两个文件a/index.html 和b/index.html 的不同。--- a/index.html --- 表示变动之前的文件。+++ b/index.html , +++表示变动之后文件。 @@ -0,0  +1, 14 @@,对变化的位置做了标识,以@@ 开头和@@ 结束的内容表示的就是变化的位置, 它会为两个部分-0,0 和+1,14.  -表示的是变动之前的文件,0表示变动前的第0 行,后面的0 表示连续0行,连接起来读就是变动之前的文件,从第0行,连续0行有变化,那就是什么都没有。

+表示变动后的文件,1表示变动后文件的第一行,14 表示连续14行, 变动后的文件从1行开始,连续14 行有变化。具体的主化内容,则是在它下面是显示。你可以看到第一行的开始都有一个加号+, 它表示变化后文件新增的行,有时还会有一个减号,表示变化前的文件中删除的行。有时什么都没有,表示的是没有变化。

  这时会有一个疑问,变动前的文件指的是哪一个文件?它指的是暂存区的文件,也就是git diff 比较的是工作区和暂存区的文件的不同。现在把变动提效到暂存区,git add index.html, 再调用git diff 命令,可以发现什么都没有输出。因为提交之后,工作区和暂存区一致了,没有什么不同,这也证明了,它只是对比的工作区和暂存区文件的不同。

  如果我们想对比 暂存区内的文件和版本区内的文件的不同,那要用 git diff  --staged。git diff --staged 看一下

  git diff master  对比工作区内的文件和版本区内的文件的不同, git commit -m "修改index.html" 提交版本区,自己试一下就可以了,这里就不写了。

  这里,只是对单个文件进行了修改,如果我们对多个文件进行了修改,git diff 会把所有修改的文件都显示出来,我们只想看到一个文件的变化,可以指它指定一个文件名,git diff 文件名,比如git diff text.txt ,只看到text.txt文件的变化内容。

  我们看到了变化后的内容,如是我们想要做的改变,那就要先git add 提交到暂存区,再git commit 提交到版本区。这里有一个快捷的命令,可以直接提交到版本区。 git commit -a -m "注释", -a 就是add 的简写。这个简写命令只对文件更改有效,因为更改的文件已经在 git 版本中被追踪了。如果是新建 一个文件,它没有被追踪,这个简写命令无效。

git commit -a -m "修改index.html"  可以看到直接提交到仓库了。

  现在我们可以添加并修改一个文件了,那多个文件呢?其实是一样的,不过有几个简捷的命令。现在我们添加新的文件,用touch index.js .style.css reset.css, 这时可以调用git status 来查看状态,不过,我想你已经知道结果了,那就是这三个文件,git没有追踪,并且你也知道下一步做什么,就是调用git add 命令添加到暂存区。但是按照以前,三个文件就要写三次git add  命令,git add index.js git add style.css , git add reset.css ,有点麻烦了。不过git 也想到了这个问题,所以git add 命令接受的参数还可以是文件夹名,我们调用git add . 试一试,. 表示的就中当前文件夹,连文件夹名都省略掉了,真是很人性化,它把当前文件夹中的文件全都上传到暂存区

 最后git commit 一下,提交到git 仓库。

 

 git 删除文件的操作

  1,如果我们想删除掉git 仓库中的文件,该怎么做呢?先删除掉本地(工作区)的文件, 然后再把变动提交到git 仓库。删除命令可以用rm, rm style.css 就可以删除掉style.css 文件。删除文件,它也是一个变动,所以还要git add 提交到暂存区,git commit 提交到git 仓库。git add 操作其实是把暂存区的文件删除了,git commit 把git 仓库中的文件删除了。操作一下,操作有没有问题。

  没有问题,git ls-files 命令,就是把仓库中的文件显示出来,可以看到确实是删除了style.css文件。我们在工作区删除文件,然后再在暂存区删除文件,感觉操作有点不人性化。我们在工作区删除,你直接把暂存区的文件删除就可以了。git 也考虑到这个问题,提供了一个git rm 命令,它把工作区和暂存区的文件一起删除,调用git rm 进入到暂存区阶段,只要commit 一下就可以把文件从仓库中删除了。

  git 重命名文件的操作。

  对于文件的重命名操作,可能有点不太好理解。在图形界面操作时,选中一个文件,然后右键重命名,输入新的文件名,操作的都是同一个文件。但对于命令行操作来说,它确不是这样的。对于命令行来说,重命名意味着,新建一个文件,然后把旧文件中内容都拷贝到新文件中,然后再把旧文件删除,所以它用的是mv 命令,就是 move,移动,把一个文件移动到另一个文件。mv index.js main.js 就是把index.js 改为main.js, 这时调用git status  看一下结果

  git status 告诉我们,删除了index.js文件,然后新建了一个main.js文件,这时 调用git add 和 git commit 提交到仓库。和删除 一样,git 也提供了git mv 命令,一步到暂存区。

我们把main.js 改回index.js  mv main.js index.js, 然后调git mv index.js main.js

  确实是到了暂存区,我们可以提交了,

 

  现在我们对main.js 进行修改,比如声明变量,输出值。

// 声明变量
let a = 5;
let b = 10;

// 输出值
console.log(a + b);

  然后再git add. 提交到暂存区. 但是发现,这些修改没有必要,需要从暂存区内撤销回来。git reset HEAD 文件名 命令就可以了。git reset HEAD main.js 撤回到工作区,暂存区中的保存的变化取消。

  unstaged changes 也说明撤销成功了。现在我们可以把main.js 中的内容全部删除,重新写,其实这里也可以使用另外一个命令,因为所有变动都在暂存区和工作区进行,版本区(仓库)中没有做任何改变,我们直接回到版本区中状态,就相当于把所有变动删除。git checkout -- 文件名,撤回到版本区的状态。git checkout -- main.js 

  可以看到main.js 变成了空文件,回退成功。

  再论git log, 实现版本回退

  当我们git commit 的时候,git 会形成一个历史快照,使用git log 可以查看。git log 还提供了一系列的参数来实现不同维度的输出。

  git log --oneline 以一行方式输出,更为简捷,可以看到我们提交了多少次的记录。

  git log --patch, 以git diff 对比变化的方式,输出提交记录。

  你发现只输出了两个完整的commit, 并且最下面还有一个:位置的光标在闪烁,这表示等待你继续输入命令,因为在git 输出时,它默认输出窗口的大小的内容,所以对于这种log的输出,它肯定很多,一个窗口的大小肯定输出不完。这时按空格键,可以发现,它 又输出了内容, 一直按空格,直到全部输出完为止,你可以看到一个end: 光标在闪烁。

  表明输出结束。此时按q(或Q)进行结束。

  git log --stat, 以文件变动的展示方式输出提交记录。

  还是和上面一样,你要按 空格或Q 进行继续输出或终止输出。

  git log --patch-with-stat 对以上两种方式进行了整合,可以自己输出看一看结果

  git log 参数 文件名,只输出包含指定文件的提交记录. git log --oneline index.html.  以oneline的方式输出只包含 index.html 的提交记录。

  除了使用命令行来查看提交记录时,我们也可以使用图形界面工具来查看,它显得更为直观。直接在命令行中输入gitk, 就可以打开图形界面工具

  在图形界面的上半部分,就是提交记录,下部分对应的每一个提交记录的变动。在上半部分的每一条提交记录上进行点击,下半部分就会相应变化,右铡还有patch, tree 等选择,自己可能多点点看一看,是非常直观。当我们手动关闭图形界面工具后,命令行窗口又变成了可输入状态。

  版本回退:在学习版本回退之前,要了解是什么能让git进行版本回退,那就是指针。在程序开发的过程中,我们会进行一次次的提交,从而形成一个提交历史。就像上面一样,我们有一个6条的提交历史。每一次的提交都会有一个指针,指向上一次的提交,就像链表一样,如下图所示。

  这一系列的提交也形成了一个分支,你可能没有注意,git init 在初始化git 仓库的时候,已经创建了一个默认分支叫master,我们这一次一次的提交都提交到了master 分支上。

   上图中最后的master 就是指的master 分支,它表示,我们一直在master分支上进行工作。同时master也是一个指针或引用,指向我们分支的最后一次的提交,

  也就是说,分支名,它即指的是我们开发过程中的整条分支,同时也是一个指针,指向整条分支的最后一次提交。

  好了,剩下最后一个HEAD指针要学习了,HEAD指针也是指的当前分支,默认指向当前分支的最后一次提交。

  我们可以使用命令看一下,master 和HEAD 是不是指向最后一个提交,命令是git rev-parse master 和 git rev-parse HEAD

  可以看到它们都指向了最后一次提交。不过,HEAD指针可以移动,从而实现版本的前进或回退。你可以把HEAD指针想像成听歌或看视频上的时候,进度条上的滑块,通过拖动滑块,我们可以快进或后退,从而实现想看哪里就看哪里。HEAD 指针也是如此,我们可以通过改变HEAD的位置,从而实现版本的回退或前进。常用的命令有3个 git reset, get checkout, git revert,  这三个命令接受的最基本的参数,就是commit ID.  我们提交的时候,它都会生成唯一的一个id,如上图中的 b695ce51ac10a45d995014c3546b4fe49c7a2f58

但是这三个命令的使用场景却大不相同,需要根据不同的场景使用不同的命令。

  git reset: reset 是重置的意思,重置意味着重新来过,当我们重置一个表单的时候,就是我们刚刚添写的内容全部舍弃掉,重新添写。我们用git log 查看一下commit id 

  现在想回退到删除style 样式文件, 那就用 git reset d3be0631e6c50dce17d00226dd270c7070b7ee86, 这个id 有点长,其实只要输入前面的6-7位就可以了,因为我们使用git log  --oneline 的时候,commit id 就是6位。再说,如果git 找不到这个id, 它会告诉我们找不到,所以也不用担心。

  输出的结果有点奇怪,index.js reset.css 没有添加到缓存区,但是我们的文件夹或工作区并没有发生变化,还是只有两个文件index.html 和main.js,这是怎么回事?其实当使用git reset 进行回退的时候,它默认改变的是暂存区,把暂存区的状态回退到指定id 的版本区(或暂存区)的状态,工作区不会发生变化。我们gitk 看看指定的id的版本区都有哪些文件?

在命令行中输入gitk,

  SHA1 ID 就是我们要回退到的id, 右下边可以看到这个提交所对应的版本区(仓库)的文件,有index.html, index.js reset.css三个文件,也就是说,当我们执行git reset d3be06时,暂存区回退到这种状态,有index.html, index.js reset.css文件。然后再和工作区进行比较,此时工作区只有index.html, main.js,所以对于git来说,相当于我们在工作区删除了index.js 和 reset.css 两个文件,所以它才会显示 unstaged change: index.js reset.css, 两个文件前面还有一个D,它就是Delete的意思,表示删除,也是说删除了两个文件,没有提交到暂存区。这时你可能想到了使用git diff 来查看一下暂存区和工作区的不同

  和我们刚才说的一样,我们删除了index.js 和reset.css 没有提交到暂存区,由于工作区还有main.js, 所以显示main.js 没有被追踪。这时如果想,回退版本的时候,直接把工作区也替换了,和暂存区状态一样。 这样再给git reset 命令增加一个参数: --hard.  为了完成这个操作,我们要回到以前的版本,这时 git log 一下,我们的提交记录只剩下4条了,根本就没有回去的commit ID, 

  相当于,d3be063 后面的两个提交

  b695ce5, 53767b8 都没有发生一样,这就是git reset 重置的作用,也就是说, 如果我们做的提交,我们不想要了,要把它扔掉,那就是git reset. 现实的场景就是,在开发新功能的时候,突然这个功能取消了,或者,开发了一段时间,代码写的太烂了,要重写,这时就用git reset.  

   那我们到底能不能从过去回到未来?那要使用git reflog,它会把所有的提交记录显示出来,找到对应的id, 然后git reset 这个id 就可以了。现在再回到刚才那个问题 ?如果git reset的时候,想要把工作区和缓存区都同步到指定版本的内容,使用git reset --hard d3be063,可以看到这时工作区也回退到了指定版本的状态。

   git checkout 也可以接受一个commit id, 移动HEAD 指针。

 

  可以看到工作目录改变了,变成了指定的 commit id 的状态。

 

   checkout 的结果就是 Head 指针和master 指针的分离,如果这时再进行提交,以前提交的历史记录也会消失,最好不做任何变动,提交记录, 不过我们可以在这里创建分支。它的主要场景就是快速查看旧版本。可以使用git ckeck master 回到最新的版本。

  git revert: revert 是撤销的意思,撤销那一次的修改,重新修改提交。但我们执行 git revert  a69243e 出现以下弹窗

 

  下面还有更多,滚动鼠标滚轮可以看到,它有几个选项,直接编辑(E), 退出Q 等,如果选择直接编辑,进入一处输入界面,这应该是一个vim 的界面,可以输入解释信息,为什么要执行撤消操作,输入完成后,按esc 键退出,然后再输入:wq 退出编辑器。这时再看一下我们的工作目录,可以看到它是回到了指定的状态。这时git log 你会出现,它会当成一次新的提交,我们原来的提交历史没有消失,这时一种安全的操作。

  但是,如果我们只想回退到前一版本,在commit id 的方式就有点麻烦了,因为我们先要git log 找到这个id; 这时git 提供了简单的操作,用HEAD;  HEAD^ 表示上一个版本, HEAD^^ 表示回退到上两个版本,当有几个版本的时候,这种操作就不方便了,这时提供了 HEAD ~num 的模式,num 表示要回退到第几个版本, HEAD ~5,表示回退到上5个版本。 git reset –hard HEAD^^, 或 git reset –hard HEAD ~2  也表示回退两个版本。 git checkout 和git revert 也是同样的用法。

  最后说一点,提交的修改。比如,本来是想一次提交三个文件(a.js, b.js c.js),但不知什么情况,只提交了一个文件(a.js) git commit -a -m "change js". 这时怎么办,又不想再对其它两个文件作另外一次提交,因为它们是一伙的。这时用到  git commit --amend 命令。首先,把另外两个文件a.js, b.js  添加到暂存区,git add . , 然后 git commit -m "change three js " --amend. 成功以后,git log 可以看到,a.js,b.js c.js 的改变成了一个提交。

转载于:https://www.cnblogs.com/SamWeb/p/9452884.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值