git使用介绍
Git简单介绍
参考网址:
这个教程推荐使用:git教程
git和svn的差异
git和svn的最大差异在于git是分布式的管理方式而svn是集中式的管理方式。如果不习惯用代码管理工具,可能比较难理解分布式管理和集中式管理的概念。下面介绍两种工具的工作流程(团队开发),通过阅读下面的工作流程,你将会很好的理解以上两种概念。
集中式管理
集中式管理的工作流程如下图:
集中式管理的核心是服务器,所有的开发者在开始的新一天的工作之前必须要从服务器获取代码,然后开发,最后解决冲突,提交。所有的版本信息都放在服务器上面。如果脱离了服务器,开发者基本上就不可以工作了。一次开发者需要老是对代码进行更新,老是会有冲突需要解决。
svn有下面的优缺点:
优点:
- 管理方便,逻辑明确,符合我们的思维逻辑
- 易于管理,集中式服务器更能保证安全性
- 代码一致性高
- 适合开发人数不多的项目开发
缺点
- 服务器压力太大
- 如果我们连接不到服务器上,基本上就是不可以工作了。因为我们不可以从服务器上进行操作了,不可以下载和提交。
- 不适合人数多的人开发
分布式管理
分布式管理的工作流程如下图:
分布式和集中式的最大区别就在于开发者可以在本地提交。每一个开发者机器上都有一个服务器的数据库。
根据上面的分布式管理的图片,对分布式管理进行简单介绍:
一般开发者的角度:
- 从服务器上克隆数据库(包括代码和版本信息)到单机上
- 在自己的机器上创建分支,修改代码
- 在单机上自己创建的分支上提交的代码
- 在单机上合并分支
- 建立一个分支,把服务器上最新版的代码fetch下来,然后跟自己的主分支合并
- 生成补丁,把补丁发送给主开发者
- 看主开发者的反馈,如果主开发者发现两个开发者之间有冲突,要求他们进行协调,然后一个人提交。
- 一般开发者之间解决冲突的方法,开发者之间可以使用pull命令解决冲突,解决完冲突之后再向主开发者提交补丁
主开发者的角度
- 查看邮件或者通过其他方式查看一般开发者的提交状态
- 打上补丁,解决冲突
- 向公共服务器提交结果,然后通知所有开发者人员
优点
- 适合分布式开发,强调个体
- 公共服务器压力和数据量都不会太大
- 速度快,灵活
- 任意两个开发者之间都可以解决冲突
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
严格来说不是指向提交的,而是指向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分支:
Git远程仓库的创建
github网站为我们提供了一个免费的git仓库托管服务,我们可以在这个网站上建立远程代码仓库。
由于你的本地的Git仓库和github仓库之间的传输是通过ssh加密的,所以需要一点的设置:
创建SSH Key。在用户主目录下,看看有没有.ssh,注意.ssh是一个隐藏文件,我们需要命令行
ls -ah
来查看,如果有,看进入到这个目录下有没有id_rsa
和id_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是公钥,可以放心地告诉任何人。
登陆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添加远程代码仓库
首先在github里面创建一个远程代码仓库,然后将本地库与远程库进行关联在本地创建的learngit仓库中运行下面命令:
$ git remote add origin git@github.com:michaelliao/learngit.git
请千万注意,把上面的
michaelliao
替换成你自己的GitHub
账户名,否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的SSH Key
公钥不在我的账户列表中。添加后,远程库的名字就是
origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。下一步,将本地库中的内容添加到到远程库中:3.
$ git push -u origin master
把本地库的内容推送到远程,用
git push
命令,实际上是把当前分支master推送到远程。由于远程库是空的,我们第一次推送
master
分支时,加上了-u
参数,Git不但 会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。之后,我们要做本地提交,执行下面命令即可:
$ 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
因此,多人协作的工作模式通常是这样:
- 首先,可以试图用git push origin branch-name推送自己的修改;
- 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
- 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
- 如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
git使用介绍的更多相关文章
- SourceTree 01 - git 客户端介绍
SourceTree - git客户端介绍 SourceTree系列第1篇 --->> SourceTree 01 - git 客户端介绍(http://www.cnblogs.com/g ...
- 1、git基础介绍及远程/本地仓库、分支
1. Git基础介绍 基于Git进行开发时,首先需要将远程仓库代码clone到本地,即为本地仓库.后续大部分时间都是基于本地仓库上的分支进行编码,最后将本地仓库的代码合入远程仓库. 1.1. 远程仓库 ...
- git基础介绍
git基础介绍 这是git操作的基础篇,是以前的写的操作文档,就没有进行手打,直接把图片贴进来了,你们担待哈,有不正确的地方可以指正出来,我将在第一时间去修改,多谢哈! 一.文件状态:git系统的文件 ...
- GitHub的SSH key配置以及常用的git命令介绍
一. GitHub的SSH key配置 (以windows为例,Mac iOS系统类似) SSH Key 是一种方法来确定受信任的计算机,从而实现免密码登录.Git是分布式的代码管理工具,远程的代码管 ...
- 版本控制工具(SVN/Git)介绍
文章大纲 一.SVN介绍二.Git介绍三.IDEA使用SVN和Git四.总结五.参考文章 一.SVN介绍 1. SVN服务器搭建和使用 首先来下载和搭建SVN服务器,下载地址如下: http:// ...
- GIT命令介绍
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下. 区别与集中式的分布式实现!!!! 集中 ...
- Git基本介绍(三大分区及核心内部构造)
1. Git三大工作区(工作区.暂存区和版本库) 工作区(WORKING DIRECTORY): 直接编辑文件的地方,肉眼可见直接操作: 暂存区(STAGIN AREA):数据(快照)暂时存放的地方: ...
- Git的介绍以及安装
Git的简单介绍 Git是一个开源的分布式版本控制系统,可以有效,高速的处理从很小到非常大的项目管理,GIT是为了帮助linux内核开发而开发的一个开放源码的版本控制软件 Git的安装 Linux平台 ...
- Git&Github介绍
git&github 什么是GIT 是一个源代码管理工具 源代码为什么要管理起来? 你写的东西就叫源代码,第三方的库和框架都不算. 让源代码可以被追溯,主要记录每次变更了什么,谁主导这次变化. ...
随机推荐
- (转载)css垂直水平居中的整理
方法一 .demo1 { width:180px; height:180px; line-height:180px; *font-size:160px; border:1px solid #ddd; ...
- Node 之 Express 学习笔记 第二篇 Express 4x 骨架详解
周末,没事就来公司加班继续研究一下Express ,这也许也是单身狗的生活吧. 1.目录结构: bin, 存放启动项目的脚本文件 node_modules, 项目所有依赖的库,以及存放 package ...
- PHP 用户注册
注册页面 reg.html 负责收集用户填写的注册信息.教程里只列出关键的代码片段,完整的代码附在本节最后. 注册表单 <fieldset> <legend>用户注册</ ...
- nginx——location 优先级
一. location 的匹配符1.等于匹配符:=等于匹配符就是等号,特点可以概括为两点:精确匹配不支持正则表达式2.空匹配符空匹配符的特点是:匹配以指定模式开始的 URI不支持正则表达式3.正则匹配 ...
- jQuery API中文文档
jQuery API中文文档 http://www.css88.com/jqapi-1.9/category/events/event-handler-attachment/ jQuery UI AP ...
- 关于Look and Say序列的感想
今天无意间翻到了<PHP经典实例>中字符串章节中关于Look and Say序列的那个程序: <?php function lookandsay($s) { //将保存返回值的变量初 ...
- 在 LINQ to Entities 查询中无法构造实体或复杂类型
public List<CustomerType> GetCustomerTypesBySchemaTypeCode(int schemaTypeCode) { var query = ( ...
- ps批量修改图片
批量更改图片尺寸的ps脚本 高端干货!PHOTOSHOP实用脚本大合集
- Java高阶面试问题合集
下面总结一下在Java面试中常用的一些问题,不具体解答,我只附上一些精彩的博文链接. Spring IOC AOP 底层原理 JAVA的反射机制和动态代理 Java反射机制和动态代理 多线程 Spri ...
- Laravel框架——增删改查
增: //save返回true false $res = new member(); res->username = 'a'; $res->password = 'b'; dd($res- ...