一、git简介
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
git不仅是一个版本控制系统,还是一个内容管理系统和工作系统,下面用SVN来介绍一下区别:
- git是分布式的:
- git把数据按元数据的方式存储:把文件的元信息放在类似 .svn .cvs等文件夹里
- git分支与svn分支不同
- git没有一个全局的版本号
- git的内容完整性优于svn
二、安装配置
git支持linux、mac和windows系统,但是运行需要curl、zlib等库的代码,因此需要安装依赖。
2.1 安装
在CentOS、Redhat上使用如下命令:
#安装依赖
$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
#安装git
$ yum -y install git-core
#查看是否安装成功
$ git --version
也可以进行源码安装,命令如下:
#安装依赖
$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
#解压源码包
$ tar -zxf git-1.7.2.2.tar.gz
$ cd git-1.7.2.2
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
在windows上安装msysGit的安装包,安装后就可以使用,内置了客户端和一个图形化界面。
2.2 配置
git有一个git config的工具用来配置和读取工作环境变量,这些环境变量决定了git工作的方式和行为,一般存储在下面三个位置:
- /etc/gitconfig:系统级的配置,对所有用户可用,使用git config --system时读的就是这个目录下的文件。
- ~/.gitconfig:用户目录下的配置文件,只适用于当前用户,git config --global命令读取的就是这个文件
- 当前项目的git目录的配置文件:在工作目录的.git/config文件,每个配置文件会覆盖上级的同名变量,如,.git/config文件会覆盖/etc/gitconfig文件的同名配置。
在windows系统会找用户目录下的.gitconfig文件,此外还会寻找/etc/gitconfig文件,默认以安装目录为根目录。
2.2.1 用户信息
使用命令:
#配置用户名和邮箱
$ git config --global user.name "centos"
$ git config --global user.email test@126.com
上述的配置因–global选项会写入用户目录下的配置文件,如果想写入当前项目的文件,去掉–global即可。用了–global后,之后的项目就会默认去这个文件中读取配置。
2.2.2 查看配置信息
使用命令:
$ git config --list
会输出配置信息,但有时会有同名变量,说明他们来自不同的配置文件,可以直接查看某一个变量:
$ git config user.name
三、git的工作流程
一般工作流程如下:
- 克隆git资源作为工作目录
- 在克隆的资源上添加或修改
- 如果其他人修改了,可以更新
- 提交前查看所有修改
- 提交修改
- 修改完成后,发现错误可以撤回提交再次修改并提交
看下流程图:
四、git工作区、暂存区和版本库
先了解一下概念:
- 工作区:就是我们看到的目录
- 暂存区:英文叫stage或index,一般存放在.git目录下的index文件中,所以有时也把暂存区成为索引
- 版本库:工作区有一个隐藏的目录.git
下面看一下三者之间的关系:
左侧是工作区,右侧版本库,版本库中index为暂存区,master为分支的目录树。
HEAD实际上是一个指向master分支的一个游标,因此命令中出现head的地方可以用master替换。
图中的objects是git的对象库,实际位于.git/objects下,包含了创建的各种对象和内容。
当对工作区执行git add命令时,暂存区的目录树被更新,同时工作区修改的内容被写入对象库中的一个新对象,而该对象的ID被记录到暂存区的文件索引中。
当执行提交git commit操作时,暂存区的目录树写到版本库中,master分支做出相应的更新,即master指向的目录树就是提交时暂存区的目录树。
当执行git reset HEAD时,暂存区的目录树别重写,被master指向的分支替换,但工作区不受影响。
当执行git rm --cached<file>时,会直接从暂存区删除文件,工作区不做修改。
执行git checkout或git checkout --<file>时,会用暂存区的全部或指定的文件替换工作区的文件,会清除工作区未添加到暂存区的改动。
git checkout HEAD .或git checkout HEAD <file> 时,会用HEAD指向的master分支中的全部或指定的文件替换暂存区和工作区中的文件,会清除暂存区和工作区中未提交的改动。
四、git创建仓库
git init:
对于git而言,很多命令需要在一个仓库中运行,因此需要初始化一个仓库,使用命令:
$ git init
使用上述命令会在当前目录生成一个.git目录,包含资源的所有元数据,其他目录不变。使用指定目录为仓库:
$ git init project1
会在project1中生成一个.git目录。将所有需要的数据和资源放在这个目录下。如果想将该项目的其他文件放入版本控制,使用命令:
$ git add *.txt
$ git add README
$ git commit -m "初始化项目版本"
上述命令将project1中后缀为txt和README文件放入仓库中
git clone:
使用git clone命令从现有的仓库拷贝项目:
$ git clone <repo> <directory>
参数说明:
- repo:git仓库
- directory:本地目录
如:
$ git clone git://github.com/schacon/grit.git mygrit
上述命令是从git://github.com…仓库中克隆项目并下载到当前项目的mygrit目录中。
五、git基本操作
Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比,下面看一些常用的命令:git clone、git push、git add、git commit、git checkout、git pull:
说明:
- workspace:工作区
- staging area:暂存区
- local repository:本地仓库
- remote repository:远程仓库
看如下命令:下面是提交和修改的相关命令
命令 | 说明 |
---|---|
git add | 添加文件到仓库 |
git status | 查看当前仓库的状态,显示有变更的文件 |
git diff | 比较暂存区好工作区的文件的不同 |
git commit | 提交暂存区到本地仓库 |
git reset | 回退版本 |
git rm | 删除工作区文件 |
git mv | 移动或重命名工作区文件 |
下面是提交日志的相关命令:
命令 | 说明 |
---|---|
git log | 查看历史提交记录 |
git blame <file> | 以列表的形式查看指定文件的历史修改记录 |
远程操作:
命令 | 说明 |
---|---|
git remote | 远程仓库操作 |
git fetch | 从远程获取代码库 |
git pull | 下载远程代码并合并 |
git push | 上传远程代码并合并 |
六、git分支管理
分支代表可以从开发主线上分离出来,在不影响主线的同时继续工作。
下面看一些命令:
#创建分支
$ git branch (branchname)
#切换分支,在切换分支的时候,git会用该分支最后提交的快照替换你的工作目录的内容,所以多个分支不需要多个目录
$ git checkout (branchname)
#合并分支,可以多次合并到同一分支,也可以在合并之后直接删除被并入的分支
$ git merge
下面使用一个简单的案例来演示:
#创建一个测试目录
$ mkdir demo
$ cd demo/
$ git init
$ touch README
$ git add README
$ git commit -m "第一次版本提交"
下面列出一些分支:
$ git branch
上述命令默认会列出在本地的分支,执行后会得到一个 * master信息,这是在git init初始化后默认生成的master分支,如果要手动创建分支,执行git branch ( branchname )即可:
$ git branch testbranch
此时有了一个新的分支,如果在进行更新操作后再创建分支,然后再进行更新,之后切换到了创建的分支,git将还原工作目录到创建分支时候的样子,看下面的例子:
$ ls
README
$ echo "git.com" > test.txt
$ git add .
$ git commit -m 'add text.txt'
[master 3esad964] add text.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
$ ls
README test.txt
$ git checkout testbranch
Switched to branch 'testbranch'
$ ls
README
可以看出,当我们切换到testbranch分支后,新的test.txt文件被移除,切换回master后又会出现。
也可以使用命令来创建并切换分支:
$ git checkout -b newtest
删除分支:
$ git branch -d (branchname)
分支合并:
git merge (branch)
七、查看提交历史
一般有两个命令:
- git log:查看历史提交记录
- git blame <file>:以列表的形式查看指定文件的历史修改记录
#使用--oneline选项查看简洁版本
git log --oneline
#使用--graph选项查看何时分支,何时合并
git log --graph
#使用--reserve参数逆向查看记录
git log --reserve --oneline
#使用--author查看指定用户的修改,并显示五条
git log --author=luo --oneline -5
还可以查看更多的如指定日期等操作,详细信息请查看官网。
八、远程仓库
git不像SVN那样有一个中心服务器,目前git操作都在本地,可以通过连接远程服务器来分享以及和其他人合作项目。下面以github和gitee为例进行介绍。
8.1 github
添加远程仓库:
$ git remote add [shortname] [url]
由于git和github是使用SSH加密传输的,因此需要配置验证信息,使用以下命令来生成SSH key:
$ ssh-keygen -t rsa -C "github注册的电子邮箱"
之后会要求确认路径和输入密码,如果使用默认的,一路回车就可。成功后会在~/下生成 .ssh文件夹,进去,打开id_rsa.pub,复制里面的key。
之后回到github上,进入Account => Settings(账户设置),左边选择SSH and GPG keys,然后点击New SSH key按钮,将复制的值粘在key文本里,之后点击add按钮,为了验证是否成功,输入以下命令:
$ ssh -T git@github.com
出现上述信息表示成功,之后登陆github,然后点击 New repository,输入远程仓库名,其他默认,点击创建即可。下面演示案例:
$ mkdir runoob-git-test # 创建测试目录
$ cd runoob-git-test/ # 进入测试目录
$ echo "# Git 测试" >> README.md # 创建 README.md 文件并写入内容
$ ls # 查看目录下的文件
README
$ git init # 初始化
$ git add README.md # 添加文件
$ git commit -m "添加 README.md 文件" # 提交并备注信息
[master (root-commit) 0205aab] 添加 README.md 文件
1 file changed, 1 insertion(+)
create mode 100644 README.md
# 提交到 Github
$ git remote add origin git@github.com:[username]/[remote-repository].git
$ git push -u origin master
其中提交到github命令中的username是用户名,remote-repository是远程仓库名。
查看当前的远程库:
git remote
实例:
$ git remote
origin
$ git remote -v
origin git@github.com:tianqixin/runoob-git-test.git (fetch)
origin git@github.com:tianqixin/runoob-git-test.git (push)
添加-v参数可以查看每个别名的实际连接地址
提取远程仓库:
$ git fetch #从远程库下载新分支与数据,之后需要执行git merge合并到我们所在的分支
假设此时配置好了远程库,下面可以执行git fetch [alias]告诉git去获取数据,然后可以执行,git merge [alias]/[branch]将服务器上的任何更新合并到当前分支,接下来在github上修改点内容,然后在本地更新修改:
$ git fetch origin
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:tianqixin/runoob-git-test
0205aab..febd8ed master -> origin/master
以上信息说明master分支以被更新,使用如下命令将更新同步到本地:
$ git merge origin/master
Updating 0205aab..febd8ed
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
推送到远程仓库
推送新分支与数据到某个远程仓库:
$ git push [alias] [branch]
以上命令是将[branch]分支推送为[alias]远程库的[branch]分支,实例如下:
$ touch runoob-test.txt # 添加文件
$ git add runoob-test.txt
$ git commit -m "添加到远程"
master 69e702d] 添加到远程
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 runoob-test.txt
$ git push origin master # 推送到 Github
删除远程仓库:
命令:
$ git remote rm [别名]
实例:
$ git remote -v
origin git@github.com:tianqixin/runoob-git-test.git (fetch)
origin git@github.com:tianqixin/runoob-git-test.git (push)
# 添加仓库 origin2
$ git remote add origin2 git@github.com:tianqixin/runoob-git-test.git
$ git remote -v
origin git@github.com:tianqixin/runoob-git-test.git (fetch)
origin git@github.com:tianqixin/runoob-git-test.git (push)
origin2 git@github.com:tianqixin/runoob-git-test.git (fetch)
origin2 git@github.com:tianqixin/runoob-git-test.git (push)
# 删除仓库 origin2
$ git remote rm origin2
$ git remote -v
origin git@github.com:tianqixin/runoob-git-test.git (fetch)
origin git@github.com:tianqixin/runoob-git-test.git (push)
8.2 Gitee
gitee是位于国内的服务器,速度比github要快许多。
和github一样,与gitee连接也需要使用SSH加密,因此配置验证信息,同样是添加SSH-key,然后创建一个远程库,之后将库连接到本地,注意:连接的远程库不可与github上的同名,但是可以起不同的别名,git默认提供的是origin,可以自定义。之后就可以进行同样的push、pull等操作了。