zoukankan      html  css  js  c++  java
  • git使用介绍

    Git简单介绍

    参考网址:

    git使用简介

    这个教程推荐使用:git教程


    git和svn的差异

    git和svn的最大差异在于git是分布式的管理方式而svn是集中式的管理方式。如果不习惯用代码管理工具,可能比较难理解分布式管理和集中式管理的概念。下面介绍两种工具的工作流程(团队开发),通过阅读下面的工作流程,你将会很好的理解以上两种概念。

    集中式管理

    集中式管理的工作流程如下图:

    集中式管理的核心是服务器,所有的开发者在开始的新一天的工作之前必须要从服务器获取代码,然后开发,最后解决冲突,提交。所有的版本信息都放在服务器上面。如果脱离了服务器,开发者基本上就不可以工作了。一次开发者需要老是对代码进行更新,老是会有冲突需要解决。

    svn有下面的优缺点:

    优点:

    1. 管理方便,逻辑明确,符合我们的思维逻辑
    2. 易于管理,集中式服务器更能保证安全性
    3. 代码一致性高
    4. 适合开发人数不多的项目开发

    缺点

    1. 服务器压力太大
    2. 如果我们连接不到服务器上,基本上就是不可以工作了。因为我们不可以从服务器上进行操作了,不可以下载和提交。
    3. 不适合人数多的人开发
    分布式管理

    分布式管理的工作流程如下图:

    分布式和集中式的最大区别就在于开发者可以在本地提交。每一个开发者机器上都有一个服务器的数据库。

    根据上面的分布式管理的图片,对分布式管理进行简单介绍:
    一般开发者的角度:

    1. 从服务器上克隆数据库(包括代码和版本信息)到单机上
    2. 在自己的机器上创建分支,修改代码
    3. 在单机上自己创建的分支上提交的代码
    4. 在单机上合并分支
    5. 建立一个分支,把服务器上最新版的代码fetch下来,然后跟自己的主分支合并
    6. 生成补丁,把补丁发送给主开发者
    7. 看主开发者的反馈,如果主开发者发现两个开发者之间有冲突,要求他们进行协调,然后一个人提交。
    8. 一般开发者之间解决冲突的方法,开发者之间可以使用pull命令解决冲突,解决完冲突之后再向主开发者提交补丁

    主开发者的角度

    1. 查看邮件或者通过其他方式查看一般开发者的提交状态
    2. 打上补丁,解决冲突
    3. 向公共服务器提交结果,然后通知所有开发者人员

    优点

    1. 适合分布式开发,强调个体
    2. 公共服务器压力和数据量都不会太大
    3. 速度快,灵活
    4. 任意两个开发者之间都可以解决冲突

    Git存储空间

    git中有两个空间,工作区,版本库

    工作区

    工作区(working directory)就是你在电脑里能看到的目录,比如我创建了一个learnGit的目录,然后在这个目录里面git init创建了git库,那么这个文件夹就是工作区。

    版本库

    版本库(repository)就是工作区中的一个隐藏目录.git,这个不算工作区,而是git的版本库。git里面有许多东西,其中最重要的就是称为stage的暂存区,还有git为我们自动创建的第一个分支master,以及指向master的一个指针head

    添加过程

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

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

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

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

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


    Git分支工作状态

    在每次提交的时候,git都把他们串成一条时间线,这条时间线就是一个分支。下面是一个例子,这里例子中是有一条主分支master分支,HEAD严格来说不是指向提交的,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支.

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

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

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

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

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

    假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
    git_creatBranch01
    所以Git合并分支也很快!就改改指针,工作区内容也不变!

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


    Git远程仓库的创建

    github网站为我们提供了一个免费的git仓库托管服务,我们可以在这个网站上建立远程代码仓库。

    由于你的本地的Git仓库和github仓库之间的传输是通过ssh加密的,所以需要一点的设置:

    1. 创建SSH Key。在用户主目录下,看看有没有.ssh,注意.ssh是一个隐藏文件,我们需要命令行ls -ah来查看,如果有,看进入到这个目录下有没有id_rsaid_rsa.pub这两个文件,如果已经有了,就直接跳过下一步。如果没有,那么在终端中创建一个SSH Key

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

      你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这 个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_romoteRepository_SSHKey)
      为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。

      当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。

    你也许还注意到,GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。

    使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。


    Git命令行

    git仓库创建

    $ mkdir learngit//创建一个目录
    $ cd learngit//进入目录
    $ pwd//查看所处文件位置
    /Users/michael/learngit
    $git init//将目录改为git仓库
    $ls -ah//显示隐藏文件,里面有一个.git文件,就代表了创建git成功
    

    向git仓库里面添加文件,并提交

    $ git add readme.txt
    $ git commit -m "wrote a readme file"//-m后面添加commit的时候的解释。便于合作开发的理解。
    [master (root-commit) cb926e7] wrote a readme file
    1 file changed, 2 insertions(+)
    create mode 100644 readme.txt
    

    git中查看工作区的状态

    $ git status
    $ git diff readme.txt //查看这个readme.txt文件的改变
    

    git版本回退

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

    下面是版本回退的编码

    $ git reset --hard HEAD^//回退到上一个版本
    $ git reset --hard 3628164//回退到id号为3628164的版本,这个版本号(3628164)不需要写全,系统会搜索
    $ git log//可以查看当前版
    $ git reflog//查看所有版本
    

    穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
    要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

    git撤销修改

    $ git checkout -- readme.txt
    

    当修改还没有add到暂存区里面的时候,可以使用上面的命令行来撤销对readme.txt文件的修改

    $ git reset HEAD readme.txt
    

    git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。这句话要在我们已经将修改传到了暂存区里面的时候,我们就使用命令行来将暂存区中的修改退回,然后在使用一开始的命令行来撤销readme.txt的修改

    git添加远程代码仓库

    1. 首先在github里面创建一个远程代码仓库,然后将本地库与远程库进行关联在本地创建的learngit仓库中运行下面命令:

      $ git remote add origin git@github.com:michaelliao/learngit.git
      

      请千万注意,把上面的michaelliao替换成你自己的GitHub账户名,否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的SSH Key公钥不在我的账户列表中。

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

    2. 下一步,将本地库中的内容添加到到远程库中:3.

      $ git push -u origin master
      

      把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

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

    3. 之后,我们要做本地提交,执行下面命令即可:

      $ git push origin master
      

    git克隆远程代码库

    $ git clone git@github.com:michaelliao/gitskills.git
    

    在本地仓库中运行命令行来克隆远程代码库

    创建与合并分支

    可能我总结的不是很好,下面是原版大神教程:git教程——创建与合并分支

    创建一个new分支,然后查看分支

    $ git checkout -b dev
    $ git branch
    

    然后更改工作区中的文件

    $git add readme.txt
    $git commit -m"branch test"
    

    然后切换到master分支中去

    $ git checkout master
    

    我们发现刚刚添加的更改不见了,因为我们切换到了另一个分支,这个分支的指针还是指向原来状态的文件的。因此没有看到改变。

    最关键的工作来了,就是合并两个分支:现在,我们把dev分支的工作成果合并到master分支上

    $ git merge dev
    Updating d17efd8..fec145a
    Fast-forward
    readme.txt |    1 +
    1 file changed, 1 insertion(+)
    

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

    删除分支命令行:

    $ git branch -d dev
    

    git推送分支

    重点:我总结的不是很好,下面是原版大神教程:git教程——推送分支

    推送分支就是把该分支上的所有本地提交到远程库。推送时,要指定本地分支,这样,git就会把该分支推送到远程库对应的远程分支上:

    $git push origin master
    

    如果要推送其他分支,只要将master改为dev,就ok了

    但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?

    master分支是主分支,因此要时刻与远程同步;

    dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;

    bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;

    feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

    git抓取分支

    重点:我总结的不是很好,下面是原版大神教程:git教程——抓取分支

    多人协作时,大家都会往master和dev分支上推送各自的修改。

    现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:

    $ git clone git@github.com:michaelliao/learngit.git
    Cloning into 'learngit'...
    remote: Counting objects: 46, done.
    remote: Compressing objects: 100% (26/26), done.
    remote: Total 46 (delta 16), reused 45 (delta 15)
    Receiving objects: 100% (46/46), 15.69 KiB | 6 KiB/s, done.
    Resolving deltas: 100% (16/16), done.
    

    当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支。不信可以用git branch命令看看:

    $ git branch
    * master
    

    现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:

    $ git checkout -b dev origin/dev
    

    现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:

    $ git commit -m "add /usr/bin/env"
    [dev 291bea8] add /usr/bin/env
     1 file changed, 1 insertion(+)
    
    $ git push origin dev
    Counting objects: 5, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 349 bytes, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
    fc38031..291bea8  dev -> dev
    

    你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:

    $ git add hello.py 
    $ git commit -m "add coding: utf-8"
    [dev bd6ae48] add coding: utf-8
     1 file changed, 1 insertion(+)
    
    $ git push origin dev
    To git@github.com:michaelliao/learngit.git
     ! [rejected]        dev -> dev (non-fast-forward)
    error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
    hint: before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:

    $ git pull
    remote: Counting objects: 5, done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 3 (delta 0)
    Unpacking objects: 100% (3/3), done.
    From github.com:michaelliao/learngit
       fc38031..291bea8  dev        -> origin/dev
    There is no tracking information for the current branch.
    Please specify which branch you want to merge with.
    See git-pull(1) for details
    
    git pull <remote> <branch>
    
    If you wish to set tracking information for this branch you can do so with:
    
    git branch --set-upstream dev origin/<branch>
    

    git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:

    $ git branch --set-upstream dev origin/dev
    Branch dev set up to track remote branch dev from origin.
    

    再pull:

    $ git pull
    Auto-merging hello.py
    CONFLICT (content): Merge conflict in hello.py
    Automatic merge failed; fix conflicts and then commit the result.
    

    这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:

    $ git commit -m "merge & fix hello.py"
    [dev adca45d] merge & fix hello.py
    $ git push origin dev
    Counting objects: 10, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (5/5), done.
    Writing objects: 100% (6/6), 747 bytes, done.
    Total 6 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
       291bea8..adca45d  dev -> dev
    

    因此,多人协作的工作模式通常是这样:

    1. 首先,可以试图用git push origin branch-name推送自己的修改;
    2. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
    3. 如果合并有冲突,则解决冲突,并在本地提交;
    4. 没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
    5. 如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。

    这就是多人协作的工作模式,一旦熟悉了,就非常简单。

  • 相关阅读:
    C# 动态加载控件 (转)
    SQL 周月时间段
    js调用xml数据显示div层上下滚动的公告
    使用半透明的DIV实现禁用页面功能(转)
    学习jQuery第一天"Hello!How are you!"
    HTML生成类
    从无限畅想转来的
    SQL递归查询子类型
    js 图片缩显
    2020年统计用区划代码和城乡划分代码:安徽省乡镇编码
  • 原文地址:https://www.cnblogs.com/AbeDay/p/5026938.html
Copyright © 2011-2022 走看看