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

先说集中式版本控制系统,版本库是集中存放在中央服务器的,而大家工作的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始工作,工作完成,再把自己的修订推送给中央服务器。这类系统,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。

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

git的初始化

在使用git进行代码管理之前,首先要对git进行初始化。

Git 配置

使用Git的第一件事就是设置名字和email,这些就是在提交commit时的签名,每次提交记录里都会包含这些信息。使用git config命令进行配置:

$ git config --global user.name ""

$ git config --global user.email ""

一般配置方法是git config --global <配置名称> <配置的值>

如果想使项目里的某个值与前面的全局设置有区别,可以在项目中使用git config 命令不带 --global 选项来设置. 这会在当前的项目目录下创建 .git/config,从而使用针对当前项目的配置。

获得一个Git仓库

有两种方法可以得到一个Git仓库:一种是从已有的Git仓库中clone (克隆,复制);还有一种是新建一个仓库,把未进行版本控制的文件进行版本控制。

Clone一个仓库

为了得一个项目的拷贝(copy),需要知道这个项目仓库的地址(Git URL). Git能在许多协议下使用,所以Git URL可能以ssh://, http(s)://, git://. 有些仓库可以通过不只一种协议来访问。

$git clone url

初始化一个新的仓库

可以对一个已存在的文件夹用下面的命令让它置于Git的版本控制管理之下。

创建代码目录project

$mkdir project

进入到代码目录,创建并初始化Git仓库:

$cd project

$git init

正常的工作流程

正常的工作流程

git的基本流程如下:

  1. 创建或修改文件
  2. 使用git add命令添加新创建或修改的文件到本地的缓存区(Index)
  3. 使用git commit命令提交到本地代码库
  4. (可选,有的时候并没有可以同步的远端代码库)使用git push命令将本地代码库同步到远端代码库

使用git status命令查看当前git仓库的状态。

文件处于untracked状态,需要用git add命令将文件加入到缓存区(Index)。

$git add file

使用 git diff 命令再加上 --cached 参数,看看缓存区中哪些文件被修改了。进入到git diff --cached界面后需要输入q才可以退出:

$git diff --cached

如果没有--cached参数,git diff 会显示当前所有已做的但没有加入到索引里的修改。

当所有新建,修改的文件都被添加到了缓存区,使用git commit提交到本地仓库:

$git commit -m "message"

需要使用-m添加本次修改的注释,完成后就会记录一个新的项目版本。除了用git add命令,还可以用下面的命令将所有没有加到缓存区的修改也一起提交,但-a命令不会添加新建的文件。

$git commit -a -m "message"

需要注意的是如果是修改文件,也需要使用git add命令添加到缓存区才可以提交。如果是删除文件,则直接使用git rm命令删除后会自动将已删除文件的信息添加到缓存区,git commit提交后就会将本地仓库中的对应文件删除。

这个时候如果本地的仓库连接到了远程Git服务器,可以使用下面的命令将本地仓库同步到远端服务器:

$git push origin master

这时候可能需要你输入在Git服务器上的用户名和密码。

分支与合并

Git的分支可以在主线(master分支)之外进行代码提交,同时又不会影响代码库主线。分支的作用体现在多人协作开发中,比如一个团队开发软件,你负责独立的一个功能需要一个月的时间来完成,你就可以创建一个分支,只把该功能的代码提交到这个分支,而其他同事仍然可以继续使用主线开发,你每天的提交不会对他们造成任何影响。当你完成功能后,测试通过再把你的功能分支合并到主线。

分支

一个Git仓库可以维护很多开发分支。创建一个新的分支:

$git branch branchname

运行git branch命令可以查看当前的分支列表,以及目前的开发环境处在哪个分支上:星号标识了你当工作在哪个分支下。输入git checkout 分支名可以切换到其他分支。

将多个分支进行合并:可以通过下面的git merge命令来合并分支到主线分支master:

#切换到master分支

$git checkout master

#将分支合并到master

$git merge -m "message" branchname

-m参数仍然是需要填写合并的注释信息。

由于两个branch修改了两个不同的文件,所以合并时不会有冲突,执行上面的命令后合并就完成了。

如果有冲突,比如两个分支都改了一个文件file3,则合并时会失败。

合并失败后先用git status查看状态,会发现file3显示为both modified,查看file3内容会发现:

$ cat file3
test
<<<<<<< HEAD
master: update file3
=======
experimental: update file3
>>>>>>> experimental

上面的内容也可以使用git diff查看,先前已经提到git diff不加参数可以显示未提交到缓存区中的修改内容。

可以看到冲突的内容都被添加到了file3中,使用vim编辑这个文件,去掉git自动产生标志冲突的<<<<<<等符号后,根据需要只保留需要的内容后保存,然后使用git add file3git commit命令来提交合并后的file3内容,这个过程是手动解决冲突的流程。

下面的命令删除分支:

$git branch -d branchname

git branch -d只能删除那些已经被当前分支合并的分支. 如果要强制删除某个分支的话就用git branch –D

撒销一个合并

如果想把当前的修改都放弃,可以用下面的命令回到合并之前的状态:

$ git reset --hard HEAD^

# 查看file3的内容,已经恢复到合并前的master上的文件内容

$ cat file3

快速向前合并

通常,一个合并会产生一个合并提交(commit), 把两个父分支里的每一行内容都合并进来。

但是,如果当前的分支和另一个分支没有内容上的差异,就是说当前分支的每一个提交(commit)都已经存在另一个分支里了,git 就会执行一个“快速向前"(fast forward)操作;git 不创建任何新的提交(commit),只是将当前分支指向合并进来的分支。

Git日志

查看日志

git log命令可以显示所有的提交(commit):

$git log

如果提交的历史纪录很长,回车会逐步显示,输入q可以退出。

git log有很多选项,可以使用git help log查看。

Git会根据git log命令的参数,按时间顺序显示相关的提交(commit)。

日志统计

如果用--stat选项使用'git log',它会显示在每个提交(commit)中哪些文件被修改了, 这些文件分别添加或删除了多少行内容,这个命令相当于打印详细的提交记录:

$ git log --stat

格式化日志

按要求来格式化日志输出。--pretty 参数可以使用若干表现格式,如oneline:

$ git log --pretty=oneline

也可以使用 short 格式:

$ git log --pretty=short

也可用medium,full,fuller,email 或raw。 如果这些格式不完全符合要求, 也可以用--pretty=format参数定义格式。

--graph 选项可以可视化提交图(commit graph),会用ASCII字符来画出一个很漂亮的提交历史(commit history)线:

$ git log --graph --pretty=oneline

日志排序

日志记录可以按不同的顺序来显示。如果要指定一个特定的顺序,可以为git log命令添加顺序参数。

按默认情况,提交会按逆时间顺序显示,可以指定--topo-order参数,让提交按拓扑顺序来显示(就是子提交在它们的父提交前显示):

$ git log --pretty=format:'%h : %s' --topo-order --graph

也可以用 --reverse参数来逆向显示所有提交日志。

小结

基本命令:

  • git config:配置相关信息
  • git clone:复制仓库
  • git init:初始化仓库
  • git add:添加更新内容到索引中
  • git diff:比较内容
  • git status:获取当前项目状况
  • git commit:提交
  • git branch:分支相关
  • git checkout:切换分支
  • git merge:合并分支
  • git reset:恢复版本
  • git log:查看日志

比较内容

比较提交 - Git Diff

查看修改的文件内容需要使用git diff命令。git diff命令的作用是比较修改的或提交的文件内容。

上面的命令执行后需要使用q退出。命令输出当前工作目录中修改的内容,并不包含新加文件,请注意这些内容还没有添加到本地缓存区。

将修改内容添加到本地缓存区,通配符可以把当前目录下所有修改的新增的文件都自动添加:

$ git add *

再执行git diff会发现没有任何内容输出,说明当前目录的修改都被添加到了缓存区,查看缓存区内与上次提交之间的差别需要使用--cached参数:

$ git diff --cached

提交代码:

$ git commit

提交后git diffgit diff --cached都不会有任何输出了。

比较分支

可以用 git diff 来比较项目中任意两个分支的差异。

首先创建一个新的分支test,并在该分支上提交一些修改:

然后查看test分支和master之间的差别:

$ git diff master test

git diff 是一个难以置信的有用的工具,可以找出项目上任意两个提交点间的差异。可以使用git help diff详细查看其他参数和功能。

更多的比较选项

如果要查看当前的工作目录与另外一个分支的差别,可以用下面的命令执行:

# 切换到master

$ git checkout master

# 查看与test分支的区别

$ git diff test

也以加上路径限定符,来只比较某一个文件或目录:

$ git diff test file1

--stat 参数可以统计一下有哪些文件被改动,有多少行被改动:

$ git diff test --stat

分布式的工作流程

分布式的工作流程

合并修改到gitproject的git仓库:可以在仓库中把改给拉 (pull)下来。执行下面几条命令:

$ git pull /tmp/myrepo master

这就把myrepo的主分支合并到了gitproject的当前分支里了。

如果gitprojectmyrepo修改文件内容的同时也做了修改的话,可能需要手工去修复冲突。

如果要经常操作远程分支(remote branch)可以定义它们的缩写:

$ git remote add myrepo /tmp/myrepo

git pull命令执行两个操作: 它从远程分支(remote branch)抓取修改git fetch的内容,然后把它合并git merge进当前的分支。

gitproject里可以用git fetch 来执行git pull前半部分的工作, 但是这条命令并不会把抓下来的修改合并到当前分支里:

$ git fetch myrepo

获取后,可以通过git log查看远程分支做的所有修改。

当检查完修改后,gitproject可以把修改合并到它的主分支中:

$ git merge myrepo/master

如果在myrepo目录下执行git pull,myrepo会从克隆的位置拉取代码并更新本地仓库,就是把gitproject上的修改同步到本地。

因为myrepo是从gitproject仓库克隆的,那么他就不需要指定gitproject仓库的地 址。因为Git把gitproject仓库的地址存储到myrepo的配置文件中,这个地址就是在git pull时默认使用的远程仓库:

$ git config --get remote.origin.url

如果myrepogitproject在不同的主机上,可以通过ssh协议来执行clone 和pull操作:

$ git clone localhost:/home/shiyanlou/gitproject test

公共Git仓库

开发过程中,通常大家都会使用一个公共的仓库,并clone到自己的开发环境中,完成一个阶段的代码后可以告诉目标仓库的维护者来pull自己的代码。

如果和维护者都在同一台机器上有帐号,那么可以互相从对方的仓库目录里直接拉所作的修改,git命令里的仓库地址也可以是本地的某个目录名:

$ git clone /path/to/repository

$ git pull /path/to/other/repository

也可以是一个ssh地址:

$ git clone ssh://yourhost/~you/repository

将修改推到一个公共仓库

通过http或是git协议,其它维护者可以通过远程访问的方式抓取(fetch)你最近的修改,但是他们没有写权限。如何将本地私有仓库的最近修改主动上传到公共仓库中呢?

最简单的办法就是用git push命令,推送本地的修改到远程Git仓库,执行下面的命令:

$ git push ssh://yourserver.com/~you/proj.git master:master

或者

$ git push ssh://yourserver.com/~you/proj.git master

git push命令的目地仓库可以是sshhttp/https协议访问。

当推送代码失败时要怎么办

如果推送(push)结果不是快速向前fast forward,可能会报像下面一样的错误:

error: remote 'refs/heads/master' is not an ancestor of
local 'refs/heads/master'.
Maybe you are not up-to-date and need to pull first?
error: failed to push to 'ssh://yourserver.com/~you/proj.git'

这种情况通常是因为没有使用git pull获取远端仓库的最新更新,在本地修改的同时,远端仓库已经变化了(其他协作者提交了代码),此时应该先使用git pull合并最新的修改后再执行git push

$ git pull

$ git push ssh://yourserver.com/~you/proj.git master

Git标签

轻量级标签

可以用 git tag不带任何参数创建一个标签(tag)指定某个提交(commit):

# 进入到gitproject目录

$ cd /home/shiyanlou/gitproject

# 查看git提交记录

$ git log

# 选择其中一个记录标志位stable-1的标签,注意需要将后面的8c315325替换成仓库下的真实提交内,commit的名称很长,通常我们只需要写前面8位即可

$ git tag stable-1 8c315325

# 查看当前所有tag

$ git tag

stable-1

这样,可以用stable-1 作为提交 8c315325 的代称。

前面这样创建的是一个“轻量级标签”。

如果想为一个tag添加注释,或是为它添加一个签名, 需要创建一个 "标签对象"。

标签对象

git tag中使用-a-s 或是 -u三个参数中任意一个,都会创建一个标签对象,并且需要一个标签消息(tag message)来为tag添加注释。 如果没有-m 或是 -F 这些参数,命令执行时会启动一个编辑器来让用户输入标签消息。

当这样的一条命令执行后,一个新的对象被添加到Git对象库中,并且标签引用就指向了一个标签对象,而不是指向一个提交,这就是与轻量级标签的区别。

下面是一个创建标签对象的例子:

$ git tag -a stable-2 8c315325 -m "stable 2"

$ git tag

stable-1

stable-2

签名的标签

签名标签可以让提交和标签更加完整可信。如果配有GPG key,那么很容易创建签名的标签。首先要在 .git/config 或~/.gitconfig 里配好key。

下面是示例:

[user]

  signingkey = <gpg-key-id>

也可以用命令行来配置:

$ git config (--global) user.signingkey <gpg-key-id>

现在可以在创建标签的时候使用-s 参数来创建“签名的标签”:

$ git tag -s stable-1 1b2e1d63ff

如果没有在配置文件中配GPG key,可以用-u参数直接指定。

$ git tag -u <gpg-key-id> stable-1 1b2e1d63ff

Git 实战教程的更多相关文章

  1. 实验楼-Git实战教程

    实验1-git介绍 1.版本控制系统: 1)集中式版本控制系统:版本库是集中存放在中央服务器的,工作时需要先从中央服务器取得最新的版本,然后工作完成后把自己的修订推送给中央服务器.这类系统都有一个单一 ...

  2. Github 快速上手实战教程

    一.实验介绍 1.1 实验内容 本次课程讲的是在实验楼的在线环境中,如何使用 Github 去管理在在线环境中使用的代码.配置.资源等实验相关文件,怎样去添加.同步和下拉在远程仓库中的实验文件,以此来 ...

  3. ActiveReports 9实战教程(3): 图文并茂的报表形式

    基于上面2节内容,我们搭建了AR9的开发环境,配置好了数据源.在本节,我们以官方提供的3个中文图文并茂的报表来展示AR9的功能,并通过实战的方式一一分享. 以往做报表相关的工作时,最害怕的是报表的UI ...

  4. Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(三)--前后端环境配置

    前言 之前都是介绍一些基础知识,在这一节,我们就要开始实战coding了.正所谓磨刀不误砍柴工,准备工作显得尤为重要.很多demo只是追求效果的实现,并不注重整个demo的架构性.从我个人的角度看来, ...

  5. 【ASP.NET实战教程】ASP.NET实战教程大集合,各种项目实战集合

    [ASP.NET实战教程]ASP.NET实战教程大集合,各种项目实战集合,希望大家可以好好学习教程中,有的比较老了,但是一直很经典!!!!论坛中很多小伙伴说.net没有实战教程学习,所以小编连夜搜集整 ...

  6. [译]Atlassian Git系列教程

    国庆期间把Atlassian的Git系列教程看完了.边看边翻译了相关文章. 原教程: https://www.atlassian.com/git/tutorials/ 我翻译的: git init g ...

  7. 【转】mybatis实战教程(mybatis in action),mybatis入门到精通

    MyBatis 目录(?)[-] mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis ...

  8. Git使用教程【转】

    Git使用教程 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是 ...

  9. Git 使用教程

    Git 使用教程 更详细请参考:廖雪峰的官方网站 - Git教程 1. 安装Git客户端软件 Git for Windows http://msysgit.github.io/ 2. 创建版本库 两点 ...

随机推荐

  1. 贪心 Codeforces Round #287 (Div. 2) A. Amr and Music

    题目传送门 /* 贪心水题 */ #include <cstdio> #include <algorithm> #include <iostream> #inclu ...

  2. MFC 单文档 根据数据 绘图

    以VS2015中创建SDI为例 选择生成的类为:C***View,基类为CView,***为项目名 在***Doc.h和***Doc.cpp中创建数据模型,在***View.cpp的OnDraw()中 ...

  3. URAL1996 Cipher Message 3(KMP + FFT)

    题目 Source http://acm.timus.ru/problem.aspx?space=1&num=1996 Description Emperor Palpatine has be ...

  4. Java 读取配置文件 Properties

    String filePath="src/cn/ac/iscas/pebble/ufe/conf/id.properties"; InputStream in = new Buff ...

  5. iframe更新与隐藏

    http://blog.sina.com.cn/s/blog_535161d80100aho6.html 从近期项目中抽取出来的一个关于iframe进行控制的代码,不是很全,不过大体功能已经显示出来了 ...

  6. 桌面每日一句--桌面翻译工具(有道翻译,微软翻译,Google翻译)

    现在的翻译软件功能越来越多,也越来越臃肿,还不时弹广告,真的很烦恼. 鉴于这种情况,自己做了个翻译软件,能满足日常需求就好了.需要用的时候可以直接在桌面输入单词翻译,或者直接使用快捷键呼出翻译窗口.最 ...

  7. ACM 变态最大值

    变态最大值 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 Yougth讲课的时候考察了一下求三个数最大值这个问题,没想到大家掌握的这么烂,幸好在他的帮助下大家算是解 ...

  8. UITableView常见 UI 问题总结

    一,经历 1.让 group 形式的UITableView的单元格也可以修改separatorStyle属性来设置. 2.修改group形式的UITableView的 cell 之间的间距,可以更改s ...

  9. tableFooterView中的按钮点击没反应

    一,经历 1.查了按钮没有响应的几个方法,排除了是用户交互设置为 NO 的情况. 2.然后打印了一下tableFooterView,尽然发现其高度为0,而且我也没有设置 frame, 却可以显示按钮, ...

  10. This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.

    一,经历 <1> 使用SDWebImage下载 成功图片后,将图片设置给 self.imageView.image,提示如题所示的错误提示. <2>第一反应就是慢慢注释掉代码进 ...