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分支工作状态

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


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文件的内容

    )

    为什么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。

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

git使用介绍的更多相关文章

  1. SourceTree 01 - git 客户端介绍

    SourceTree - git客户端介绍 SourceTree系列第1篇 --->> SourceTree 01 - git 客户端介绍(http://www.cnblogs.com/g ...

  2. 1、git基础介绍及远程/本地仓库、分支

    1. Git基础介绍 基于Git进行开发时,首先需要将远程仓库代码clone到本地,即为本地仓库.后续大部分时间都是基于本地仓库上的分支进行编码,最后将本地仓库的代码合入远程仓库. 1.1. 远程仓库 ...

  3. git基础介绍

    git基础介绍 这是git操作的基础篇,是以前的写的操作文档,就没有进行手打,直接把图片贴进来了,你们担待哈,有不正确的地方可以指正出来,我将在第一时间去修改,多谢哈! 一.文件状态:git系统的文件 ...

  4. GitHub的SSH key配置以及常用的git命令介绍

    一. GitHub的SSH key配置 (以windows为例,Mac iOS系统类似) SSH Key 是一种方法来确定受信任的计算机,从而实现免密码登录.Git是分布式的代码管理工具,远程的代码管 ...

  5. 版本控制工具(SVN/Git)介绍

    文章大纲 一.SVN介绍二.Git介绍三.IDEA使用SVN和Git四.总结五.参考文章   一.SVN介绍 1. SVN服务器搭建和使用 首先来下载和搭建SVN服务器,下载地址如下: http:// ...

  6. GIT命令介绍

    Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下. 区别与集中式的分布式实现!!!! 集中 ...

  7. Git基本介绍(三大分区及核心内部构造)

    1. Git三大工作区(工作区.暂存区和版本库) 工作区(WORKING DIRECTORY): 直接编辑文件的地方,肉眼可见直接操作: 暂存区(STAGIN AREA):数据(快照)暂时存放的地方: ...

  8. Git的介绍以及安装

    Git的简单介绍 Git是一个开源的分布式版本控制系统,可以有效,高速的处理从很小到非常大的项目管理,GIT是为了帮助linux内核开发而开发的一个开放源码的版本控制软件 Git的安装 Linux平台 ...

  9. Git&Github介绍

    git&github 什么是GIT 是一个源代码管理工具 源代码为什么要管理起来? 你写的东西就叫源代码,第三方的库和框架都不算. 让源代码可以被追溯,主要记录每次变更了什么,谁主导这次变化. ...

随机推荐

  1. (转载)css垂直水平居中的整理

    方法一 .demo1 { width:180px; height:180px; line-height:180px; *font-size:160px; border:1px solid #ddd; ...

  2. Node 之 Express 学习笔记 第二篇 Express 4x 骨架详解

    周末,没事就来公司加班继续研究一下Express ,这也许也是单身狗的生活吧. 1.目录结构: bin, 存放启动项目的脚本文件 node_modules, 项目所有依赖的库,以及存放 package ...

  3. PHP 用户注册

    注册页面 reg.html 负责收集用户填写的注册信息.教程里只列出关键的代码片段,完整的代码附在本节最后. 注册表单 <fieldset> <legend>用户注册</ ...

  4. nginx——location 优先级

    一. location 的匹配符1.等于匹配符:=等于匹配符就是等号,特点可以概括为两点:精确匹配不支持正则表达式2.空匹配符空匹配符的特点是:匹配以指定模式开始的 URI不支持正则表达式3.正则匹配 ...

  5. jQuery API中文文档

    jQuery API中文文档 http://www.css88.com/jqapi-1.9/category/events/event-handler-attachment/ jQuery UI AP ...

  6. 关于Look and Say序列的感想

    今天无意间翻到了<PHP经典实例>中字符串章节中关于Look and Say序列的那个程序: <?php function lookandsay($s) { //将保存返回值的变量初 ...

  7. 在 LINQ to Entities 查询中无法构造实体或复杂类型

    public List<CustomerType> GetCustomerTypesBySchemaTypeCode(int schemaTypeCode) { var query = ( ...

  8. ps批量修改图片

    批量更改图片尺寸的ps脚本 高端干货!PHOTOSHOP实用脚本大合集

  9. Java高阶面试问题合集

    下面总结一下在Java面试中常用的一些问题,不具体解答,我只附上一些精彩的博文链接. Spring IOC AOP 底层原理 JAVA的反射机制和动态代理 Java反射机制和动态代理 多线程 Spri ...

  10. Laravel框架——增删改查

    增: //save返回true false $res = new member(); res->username = 'a'; $res->password = 'b'; dd($res- ...