zoukankan      html  css  js  c++  java
  • 细说GIT分布式版本控制器

    一.Git介绍

    Git是目前世界上最先进的分布式版本控制器。Svn CVS

    版本控制器:就是用来追溯自己书写的代码的记录信息。好处:可以非常方便的记录何时何地何人操作了哪些代码。

    什么是分布式版本控制器?

    集中式:对于集中式的版本控制器,需要搭建一个中央服务器,然后在这个中央服务器里面作为代码的仓库。

    分布式:就是每个用户的电脑都是一个独立的仓库,可以记录代码的变化,即使不联网,完全也可以自己独立开发。

    二.Git安装

    https://git-for-windows.github.io/

    安装完后还需要最后一步设置,在命令行输入:告诉你是谁

    $ git config --global user.name "Your Name"

    $ git config --global user.email "email@example.com"

    三.Git操作

    1.创建仓库

    1).创建仓库目录

    2).通过git init命令把这个目录变成Git可以管理的仓库

     

    注意:Git仓库创建好后,会在该文件存在一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

    注意:如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -ah命令就可以看见。

    小结:git init 初始化仓库

    2.添加文件到版本库

    把文件添加到版本分两步,首先将文件添加到暂存区,然后再提交到版本库

    1).创建文件并把文件添加到暂存区(git add

    git add . 表示将当前目录下的所有文件都添加到暂存区

    2).将文件从暂存区提交到版本库

     

    -m 表示本次提交的描述

    小结:

                       git add xxx 添加单个文件到暂存区

                       git add .   将当前文件夹下的所有文件都添加到暂存区

                       git commit -m ‘xxx’ 将文件提交到版本库  -m 表示描述

    3.修改文件查看状态与不同

    此时我们将文件内容修改

     

    1).查看状态

       

    git status 命可以让我们时刻掌握仓库当前的状态,上面的命令告诉我们,readme.txt被修改过了,但还没有准备提交的修改。

    2).查看此次修改的文件与之前的不同

        

    git diff顾名思义就是查看difference,可以从上面的命令输出看到,我们添加了一行hello单词        

    知道了对readme.txt作了什么修改后,再把它提交到仓库就放心多了,提前命令与之前相同。

     

    小结:

                       git status 查看仓库状态

                      git diff   查看修改后文件与之前的不同。

    4.版本回退

             如果此时我们因为某种原因想回退到之前的某个版本该怎么办?

    1).首先通过git log 查看之前的提交日志

               

              如果嫌这样看着太乱的话可以试试加上—pretty=oneline参数

            

             其中85d58ac82a21e8c587da900edff9a21566b1d708和78c5b099e84439c9b640a5028ee1fcb224432576 代表的是commit id(版本号),

             它是通过SHA1计算出来的一个非常大的数字,用十六进制表示,而且你的commit id 和我的肯定不一样,实际以你自己的为准。

    2).回退到之前某个版本

             知道了之前的提交日志那如何回退到之前的版本呢?

             首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交85d58ac82a21e8c587da900edff9a21566b1d708(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

                       我们现在回退到上一版本使用命令:git reset –hard HEAD^    

                       查看此时的文件:cat readme.txt   

                       通过查看文件发现确实是回到了上一个版本,那么我们再通过git log查看此时版本库的状态。 

                       最新的“修改readme.txt文件”这个版本已经不见了,就相当于我们坐了时光机一样,穿越到了之前的版本,

    3).回退到未来某个版本

                       现在肯定又有人想我穿越到了过去,那我再怎么穿越回来呢?

                       在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^回退到”添加readme.txt文件”版本时,再想恢复到”修改readme.txt文件”,就必须找到”修改readme.txt文件”的commit id。Git提供了一个命令git reflog用来记录你的每一次命令:

                       然后通过git reset –hard 85d58ac回退到”修改readme.txt文件”版本。

                               

                       我们再通过查看文件内容,和历史提交记录发现又回到了”修改readme.txt文件”的版本

                               

                      

    小结:

                       git log 查看提交历史记录,以便确认回退到历史哪个版本。

                       git reflog 查看命令历史,以便确定要回到未来哪个版本

                       git reset –hard commit_id 版本之间的穿梭回退

     

     

    5.工作区与暂存区

    1).工作区:

                       就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区:

    2).暂存区:

    是逻辑上的一个概念,是看不到的。

    3).版本库:

    工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

    Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

    分支和HEAD的概念我们以后再讲。

    前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:

    第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

    第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

    因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

    你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

    俗话说,实践出真知。现在,我们再练习一遍,先对readme.txt做个修改,比如加上一行内容:

    然后,在工作区新增一个LICENSE文本文件(内容随便写)。

    先用git status查看一下状态:

    Git非常清楚地告诉我们,readme.txt被修改了,而LICENSE还从来没有被添加过,所以它的状态是Untracked

    现在,使用两次命令git add,把readme.txtLICENSE都添加后,用git status再查看一下:

    现在,暂存区的状态就变成这样了:

    所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。

    一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:

    现在版本库变成了这样,暂存区就没有任何内容了:

     

     

    小结:

             工作区是指我们本地能够目录,暂存区是逻辑上的定义,我们想提交某个文件时,需要将工作区的文件放入到暂存区(git add),然后再提交。

    6.管理修改

    场景:比如说你修改readme.txt文件,并且git add 了,随后你又修改了readme.txt文件,但是此时你没有git add,直接git commit的了,这种情况下,你的第二次修改将不会被提交。

    原因是你第二次修改没有放入暂存区,而git commit 是将暂存区的内容提交到版本库的。

    下面实际操作一下:

             1)第一次修改readme.txt文件:添加一行first update

                      

             2)git add 此次的修改

                      

             3)第二次修改readme.txt文件,添加一行second update

                      

             4)直接git commit 提交

                      

             发现第二次的修改没有被提交。验证了上面的结论,只有在暂存区的数据才能被提交。所以要想被提交必须先将文件放入到暂存区,然后再提交

            

             我们在修改了某些文件时,也可以直接使用git commit -a -m ‘xxxx’ 提交。-a就相当于git add .操作,将当前目录下所有修改了的文件放入暂存区。

                      

            

    小结:

             在暂存区的数据才能被提交到版本库。

             修改了某些文件时,也可以直接使用git commit -a -m ‘xxxx’ 提交

    7.撤销修改

             场景1:修改了工作区的某个文件内容如何丢弃修改?

             场景2:不但修改了工作区的某个文件内容,而且还添加到了暂存区,如何丢弃修改?

             场景3:不但添加到了暂存区而且还提交到了版本库,如何丢弃修改?

            

             场景1:修改了工作区的某个文件内容如何丢弃修改?

                                1.修改readme.txt文件  添加一行working undo

                                        

                                2.git status 查看状态

                                        

                                         你可以发现git会提示你,git checkout – file 可以丢弃工作区的修改

                                3.git checkout – file 丢弃修改

                                        

             场景2:不但修改了工作区的某个文件内容,而且还添加到了暂存区,如何丢弃修改?

    1.修改readme.txt文件  添加一行stage undo

    2.git status查看状态

                                         Git同样告诉我们,用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区.

    3.git reset HEAD file 撤销暂存区的修改,重放回工作区。

    此时修改的文件已经被放回到工作区。

                                4.从工作区中撤销本次修改

                                        

                                         此时修改内容已被丢弃。

             场景3:不但添加到了暂存区而且还提交到了版本库,如何丢弃修改?

                                 这种情况就需要参考版本回退这一节了,回退到上一个版本

    1. 修改readme.txt文件,添加一行repository undo
    1. 提交到版本库

     

    1. 回退到上一个版本

     

                                        

    小结:

                       对于只在工作区修改了文件内容,撤销此次修改使用 git checkout – file撤销

                       对于提交到了暂存区的文件内容修改,撤销此次修改需要分两步,第一步:git reset HEAD file 重放回工作区,第二步:git checkout – file 从工作区中撤销。

                       对于已经提交到版本库的文件内容修改,撤销需要回退到上一个版本,使用git reset –hard commit_id.

     

     

    8.删除文件

             如何将已经提交到版本库的文件删除?

    1. 添加文件到版本库

     

    1. 从版本库中删除

     

    小结:

    将文件从版本库删除也是分为两步:

                                第一步:git rm file 从版本库删除

                                第二步:git commit -m ‘xxx’ 提交本次的操作

    四.远程仓库

    1.添加远程仓库

             以Github为例

             1).在github上创建仓库

            

             创建完成之后

                       仓库创建完成之后,github会提示我们从这个仓库里克隆出新的仓库,或者创建新的仓库与之个管理,或者推送已存在的仓库与之关联。

                      

                       2).把本地的仓库与github仓库关联。

                               

                                origin 是远程库的名字,github的默认叫法

                      

                       3).把本地仓库的内容推送到github仓库

                               

                                -u 的意思是如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用Git push

                                推送完成后,github上就有了你提交的内容

                      

                                从现在起,只要本地作了提交,就可以通过命令:

                                         git push origin master

                                把本地master分支的最新修改推送至github上。

    小结:

                       git remote add origin xxx关联一个远程库

                       git push -u origin master 第一次将master分支的所有内容推送到远程库

                       git push origin master 上面命令第一次推送之后,以后的每次本地提交,使用不带-u 参数的即可。

     

     

    2克隆远程仓库

             上面讲了如何将本地仓库与远程仓库关联,还有一种情况就是将远程仓库克隆到本地

     

                       此时我将仓库克隆到了E盘

            

    这样你的E盘就会出现你克隆的那个仓库。

    小结:

                       要克隆一个仓库,首先你必须要知道仓库的地址,然后使用git clone命令克隆

     

     

     

    五.分支管理

             分支:是指在开发主线上又开辟了一条线,这样能在不影响主线的同时继续工作

            

    1.     创建与合并分支

    在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。

    一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

     

    每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:

    当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

     

    你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

    不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

     

    假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

     

    所以Git合并分支也很快!就改改指针,工作区内容也不变!

    合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

     

     

    实战:

    1).创建并切换分支

              

               git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

               git branch dev

               git checkout dev

     

    2).查看当前分支

              

               git branch命令会列出所有分支,当前分支前面会标一个*号。

     

    3).修改文件内容提交

              

     

    4).切换回主分支

              

               切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:

              

     

    5).将dev分支合并到master分支

            

    git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。

    注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

    当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。

    合并完成后,就可以放心地删除dev分支了:

                       6).删除dev分支

                               

                                删除后,再看branch,就只剩下master分支了。

                      

             小结:

                       查看分支:git branch

    创建分支:git branch <name>

    切换分支:git checkout <name>

    创建+切换分支:git checkout -b <name>

    合并某分支到当前分支:git merge <name>

    删除分支:git branch -d <name>

                               

    2.     解决冲突

    场景:你新建并切换到了分支feature1,然后修改了readme.txt文件并提交。随后你又切换到了master分支,同样修改了readme.txt文件并提交

                 这时如果你要合并feature1分支时,即会产生冲突。

              

               模拟并解决:

               1).创建并切换分支feature1,修改readme.txt文件,最后提交

                       

     

               2).切换到主分支,修改readme.txt文件,并提交

                       

                        现在,master分支和feature1分支各自都分别有新的提交,变成了这样:

                       

     

               3).合并分支

                       

                        这是git告诉我们 readme.txt文件产生冲突,必须手动解决冲突后再提交

                        git status 也告诉我们冲突的文件。

              

               4).查看冲突文件

                       

                        Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存

               5).修改文件,手动解决冲突

                       

                       

                                        

                                6).查看分支合并情况

                                        

                                7).删除分支

                                        

                               

             扩展:

    git merge xxx 默认是使用fast-forward,fast-forward方式就是当条件允许的时候,git直接把HEAD指针指向合并分支的头,完成合并。属于“快进方式”,不过这种情况如果删除分支,则会丢失分支信息。因为在这个过程中没有创建commit。

    git merge --no-ff xxx  其中—no-ff指的是强行关闭fast-forward方式,使得合并分支后能够保留分支的commit的历史记录。

            

             小结:

                       当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。

    用git log --graph命令可以看到分支合并图。

     

     

    3.     Bug分支

    bug在软件开发中就像家常便饭一样,有了bug就需要修复,而git又特别提倡使用分支,所以每个bug都可以通过创建一个临时分支来修复,修复后,合并分支,然后再删除临时分支。

    场景:当你接到线上环境代号为007的bug时,很自然的会去创建一个bug分支,分支名为bug007,但是,此时你正在dev分支上进行工作还没有提交,并不是你不想提交,而是你的工作还没完成还没法提交,但是现在这个bug又非常紧急,要求你尽快解决,这时我们该怎么办?

    模拟并解决:

             1).创建bug007分支

                      

             2).模拟在dev上正在工作还没有提交

                               

                               

                       3).git提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作

                         使用git stash将当前dev正在开发的工作储藏起来

                               

                                再通过git status查看发现工作区现在是干净的了。

                                此时我们就可以切换到bug分支进行bug修复

                      

                       4).切换到bug007分支修复bug   

                               

                               

                                此时bug已经修改,那么我们就可以很放心的合并到主分支并将bug007分支删掉。

                                因为bug007是在主分支上建立的,所以此时需要切换到主分支上删除

            

                       5).合并并删除bug007分支

                               

                       6).之前为了修改bug,我们将dev的内容储藏起来了,那么现在我们怎么恢复呢?

                                首先通过git stash list 查看

                               

                                我们发现之前的工作现场还在。

                                那我们可以通过git stash pop来恢复现场

            

                       7).恢复工作现场

                               

                                再git stash list 发现已经没有内容了。

            

             小结:

                                修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

    当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

    4.Feature分支

                       软件开发中,总有无穷无尽的新的功能要不断添加进来。

    添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

                       现在你收到了一个新需求,要求你完成一个书籍管理的功能,

                       于是准备开发创建feature分支

                      

                       半天后你开发完毕:

                      

                       切换回dev分支准备合并

                      

                       如果一切顺利的话,合并删除分支。

                       但是就在这时,接到上级命令说这个功能必须取消。

                       于是我们使用git branch -d 命令删除这个feature分支

                      

                       这时git会提示我们,feature_book没有被合并,如果真的要强行删除使用git branck -D 命令来删除

                      

                       删除成功

    小结:

             开发一个新feature,最好新建一个分支;

    如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

            

  • 相关阅读:
    JSONP
    函数式编程
    Cookie
    IE userData
    Web Storage
    前端学PHP之会话Session
    数据结构之归并排序
    数据结构之冒泡排序
    数据结构之插入排序
    数据结构之选择排序
  • 原文地址:https://www.cnblogs.com/jiaoda/p/7260505.html
Copyright © 2011-2022 走看看