zoukankan      html  css  js  c++  java
  • Git笔记

    Git笔记

    CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?

    先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。

    集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。

    那分布式版本控制系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

    和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

    在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

    在Windows上安装Git

    在Windows上使用Git,可以从Git官网直接下载安装程序,然后按默认选项安装即可。

    安装完成后,还需要最后一步设置,在命令行输入:

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

    因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。你也许会担心,如果有人故意冒充别人怎么办?这个不必担心,首先我们相信大家都是善良无知的群众,其次,真的有冒充的也是有办法可查的。

    注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

    创建版本库

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

    所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:

    $ mkdir learngit
    $ cd learngit
    $ pwd
    /Users/michael/learngit
    

    pwd命令用于显示当前目录。在我的Mac上,这个仓库位于/Users/michael/learngit。

    如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。

    第二步,通过git init命令把这个目录变成Git可以管理的仓库:

    $ git init
    Initialized empty Git repository in /Users/michael/learngit/.git/
    

    瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),细心的读者可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

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

    也不一定必须在空目录下创建Git仓库,选择一个已经有东西的目录也是可以的。

    把文件添加到版本库

    现在我们编写一个readme.txt文件,内容如下:

    Git is a version control system.
    Git is free software.
    

    一定要放到learngit目录下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。

    和把大象放到冰箱需要3步相比,把一个文件放到Git仓库只需要两步。

    第一步,用命令git add告诉Git,把文件添加到仓库:

    $ git add readme.txt
    

    执行上面的命令,没有任何显示,这就对了,Unix的哲学是“没有消息就是好消息”,说明添加成功。

    第二步,用命令git commit告诉Git,把文件提交到仓库:

    $ git commit -m "wrote a readme file"
    [master (root-commit) cb926e7] wrote a readme file
     1 file changed, 2 insertions(+)
     create mode 100644 readme.txt
    

    以一次提交很多文件,所以你可以多次add不同的文件,比如:

    $ git add file1.txt
    $ git add file2.txt file3.txt
    $ git commit -m "add 3 files."
    

    版本回退修改

    我们继续修改readme.txt文件,改成如下内容:

    Git is a distributed version control system.
    Git is free software.
    

    现在,运行git status命令看看结果:

    $ git status
    # On branch master
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #    modified:   readme.txt
    #
    no changes added to commit (use "git add" and/or "git commit -a")
    

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

    如果想看看具体修改了哪些地方,需要使用git diff 这个命令查看:

    $ git diff readme.txt 
    diff --git a/readme.txt b/readme.txt
    index 46d49bf..9247db6 100644
    --- a/readme.txt
    +++ b/readme.txt
    @@ -1,2 +1,2 @@
    -Git is a version control system.
    +Git is a distributed version control system.
     Git is free software.
    

    版本回退

    现在,再练习一次,修改readme.txt文件如下

    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    

    在git中,我们可以使用git log命令查看历史记录:

    $ git log
    commit 3628164fb26d48395383f8f31179f24e0882e1e0
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Tue Aug 20 15:11:49 2013 +0800
    
        append GPL
    
    commit ea34578d5496d7dd233c827ed32a8cd576c5ee85
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Tue Aug 20 14:53:12 2013 +0800
    
        add distributed
    
    commit cb926e7ea50ad11b8f9e909c05226233bf755030
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Mon Aug 19 17:51:55 2013 +0800
    
        wrote a readme file
    

    git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file。

    如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

    $ git log --pretty=oneline
    3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
    ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
    cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
    

    现在,我们要把当前版本“append GPL”回退到上一个版本“add distributed”,就可以使用git reset命令:

    $ git reset --hard HEAD^
    HEAD is now at ea34578 add distributed
    

    回退到指定的版本:

    $ git reset --hard 3628164
    HEAD is now at 3628164 append GPL
    

    版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。

    Git提供了一个命令git reflog用来记录你的每一次命令:

    $ git reflog
    ea34578 HEAD@{0}: reset: moving to HEAD^
    3628164 HEAD@{1}: commit: append GPL
    ea34578 HEAD@{2}: commit: add distributed
    cb926e7 HEAD@{3}: commit (initial): wrote a readme file
    

    工作区和暂存区

    工作区(Working Directory)

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

    版本库(Repository)

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

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

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

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

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

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

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

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

    Git is a distributed version control system.
    Git is free software distributed under the GPL.
    Git has a mutable index called stage.
    

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

    先用git status查看一下状态:

    $ git status
    # On branch master
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   readme.txt
    #
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
    #
    #       LICENSE
    no changes added to commit (use "git add" and/or "git commit -a")
    

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

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

    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       new file:   LICENSE
    #       modified:   readme.txt
    #
    

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

    $ git commit -m "understand how stage works"
    [master 27c9860] understand how stage works
     2 files changed, 675 insertions(+)
     create mode 100644 LICENSE
    

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

    $ git status
    # On branch master
    nothing to commit (working directory clean)
    

    管理修改

    Git跟踪并管理的是修改,而非文件。

    第一步:对readme.txt做一个修改,然后添加 git add readme.txt

    第二步:在修改readme.txt 然后提交

    查看状态 git status,发现第二次的修改没有被提交

    我们回顾一下操作过程:第一次修改 → git add → 第二次修改 → git commit

    你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。

    那怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:

    第一次修改 → git add → 第二次修改 → git add → git commit

    撤销修改

    git checkout -- file可以丢弃工作区的修改:

    $ git checkout -- readme.txt
    

    命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

    一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

    一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

    总之,就是让这个文件回到最近一次git commit或git add时的状态。

    git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。

    用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区:

    $ git reset HEAD readme.txt
    Unstaged changes after reset:
    M       readme.txt
    

    删除文件

    在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交:

    $ git add test.txt
    $ git commit -m "add test.txt"
    [master 94cdc44] add test.txt
     1 file changed, 1 insertion(+)
     create mode 100644 test.txt
    

    般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:

    这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:

    $ git status
    # On branch master
    # Changes not staged for commit:
    #   (use "git add/rm <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       deleted:    test.txt
    #
    no changes added to commit (use "git add" and/or "git commit -a")
    

    现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:

    $ git rm test.txt
    rm 'test.txt'
    $ git commit -m "remove test.txt"
    [master d17efd8] remove test.txt
     1 file changed, 1 deletion(-)
     delete mode 100644 test.txt
    

    另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

    $ git checkout -- test.txt
    

    git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

    远程仓库

    连接GitHub

    第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

    $ ssh-keygen -t rsa -C "youremail@example.com"
    

    你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。

    你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。

    如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

    第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:

    然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容。

    添加远程库

    现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。

    首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库:

    在Repository name填入learngit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库:

    目前,在GitHub上的这个learngit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。

    现在,我们根据GitHub的提示,在本地的learngit仓库下运行命令:

    $ git remote add origin http://github.com/zailushang1996/learngit.git
    

    添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

    下一步,就可以把本地库的所有内容推送到远程库上:

    $ git push -u origin master
    Counting objects: 19, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (19/19), done.
    Writing objects: 100% (19/19), 13.73 KiB, done.
    Total 23 (delta 6), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
     * [new branch]      master -> master
    Branch master set up to track remote branch master from origin.
    

    由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

    推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样

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

    $ git push origin master
    

    从远程库克隆

    首先,登陆GitHub,创建一个新的仓库,名字叫gitskills:

    我们勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件:

    现在,远程库已经准备好了,下一步是用命令git clone克隆一个本地库:

    $ git clone https://github.com/zailushang1996/gitskills.git
    Cloning into 'gitskills'...
    remote: Counting objects: 3, done.
    remote: Total 3 (delta 0), reused 0 (delta 0)
    Receiving objects: 100% (3/3), done.
    
    $ cd gitskills
    $ ls
    README.md
    
  • 相关阅读:
    Docker 安装 Logstash
    Docker 安装 Kibana
    go命令行参数
    小程序 表单提交
    小程序picker日历
    小程序,验证码倒计时效果
    flex图片垂直居中
    小程序单选框样式
    wechat-wxparse 使用
    小程序Banner跳转
  • 原文地址:https://www.cnblogs.com/zailushang1996/p/8635396.html
Copyright © 2011-2022 走看看