Git讲解
一、Git简介
版本控制工具提供完备的版本管理功能,用于存储、追踪目录(文件夹)和文件的修改历史,是软件开发者的必备工具,是软件公司的基础设施。版本控制软件的最高目标,是支持软件公司的配置管理活动,追踪多个版本的开发和维护活动,及时发布软件。
目前已有版本控制工具有CVS 2006年前、SVN 2006年左右、GIT 2010年左右。
比较:
名称 |
版本库模型 |
并发模式 |
历史模式 |
变更范围 |
网络协议 |
原子提交性 |
部分克隆 |
CVS |
Client-server (集中式) |
Merge |
Changeset |
File |
Pserver,ssh |
No |
Yes |
SVN |
Client-server (集中式) |
3-way merge, recursive merge, octopus merge |
Changeset and Snapshot |
Tree |
custom (svn), custom (svn) over ssh, HTTP and SSL (usingWebDAV) |
Yes |
Yes |
Git |
Distributed (分散式) |
Merge or lock |
Snapshot |
Tree |
custom, custom over ssh, rsync, HTTP/HTTPS, email, bundles |
Yes |
No |
集中式和分布式对比:
图1 集中式
图2 分布式
分布式与集中式最大的区别: 在于开发者可以本地提交,每个开发者机器上都有一服务数据库。
Git是当前最为先进的分布式版本管理控制和源码管理系统。最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑。后来有人把它移植到了Windows上。现在Git可以在Linux、Unix、Mac和Windows这几大平台上正常运行了。
Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 可以保存任何文档,最善于保存文本文档,因为它本来就是为解决软件源代码 (也是一种文本文档)版本管理问题而开发的,提供了许多有助于文本分析的工具。对于非文本文档,Git 只是简单地为其进行备份并实施版本管理。
二、Git安装及配置
安装地址:https://git-scm.com/downloads
配置作者信息:
// 设置全局
git config --global user.name "Author Name“
git config --global user.email "Author Email“
// 或者设置本地项目库配置
git config user.name "Author Name"
git config user.email "Author Email"
//查看配置信息
git config --list
创建版本库:
1、本地创建文件夹
2、 通过git init命令把这个目录变成Git可以管理的仓库
初始化本地仓库,会在当前目录下生成一个.git目录,见上图,该目录中记录了git仓库的相关信息。
3、将需要管理的文件放入目录中,如test.txt
4、通过git add <file>命令提交版本到缓存区
5、使用git status查看版本库的状态。
6、通过git commit -m <message: 对此次提交的描述信息>版本到版本库。提交等同add。
如果没有提交,又修改了文件的内容,则两次修改的信息都可以通过status命令查看到
需要关注的命令有:git init、git add、git commit、git status。
管理修改:
对一个文件做以下操作:
第一次修改 -> git add -> 第二次修改 -> git commit
会发现,第二次的修改没有被提交…
正确做法是:第一次修改 -> git add -> 第二次修改 -> git add -> git commit
查看历史及对比数据:
1、 如果需要查看版本库的改动情况,可以使用:
git diff,查看当前修改和暂存区的不同
git diff –cached,查看暂存区与当前分支的不同
对于此二者的不同,我们需要知道在git中有三个区域保存下面三种状态的文件:修改未添加(当前修改)、修改已添加(缓存区)、提交(当前分支)。
git diff是前两个的比较,git diff --cached是后两者的比较。如下图:
分别作了两次修改,第一次修改增加了一行1并且进行了add操作,第二次修改增加了一行2删除原行1,没有进行add操作。
2、使用git log显示从最近到最远的提交日志,
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=onelin
$ git log --pretty=oneline
在Git中,用HEAD(HEAD@{0})表示当前版本,也就是最新的提交17b6bc...
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD@{1},上上一个版本就是HEAD@{2}。
在版本之间做切换,使用命令git reset --hard commit_id 或 git reset --hard HEAD@{4}要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本
提交文件忽略:
对gitignore 文件进行编辑,实现文件的提交忽略。,.gitignore文件过滤有两种模式,开放模式和保守模式。
vim .gitignore
bin/: 忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件
/bin: 忽略根目录下的bin文件,开放模式
/*.c: 忽略 cat.c,不忽略 build/cat.c
debug/*.obj: 忽略 debug/io.obj,不忽略 debug/common/io.obj 和 tools/debug/io.obj
**/foo: 忽略/foo, a/foo, a/b/foo等
a/**/b: 忽略a/b, a/x/b, a/x/y/b等
!/bin/run.sh: 不忽略 bin 目录下的 run.sh 文件,保守模式
*.log: 忽略所有 .log 文件
config.php: 忽略当前路径的 config.php 文件
工作区和暂存区:
图3 工作区和暂存区
git 基本概念以及操作流程:
文件目录——仓库(repository)
代码仓库可以理解为一个目录,这里面的所有文件都是通过git实现版本管理,git对版本进行跟踪和记录在该目录下发生的更新。先来看一下git的基本框架。
Directory:仓库。包括工作空间和管理空间。
workspace:目录和文件构成工作空间。
.git :存放git管理信息目录,由git init初始化初始化创建
Index/Stage:暂存区,通常我们在git add 之后只是将文件提交至暂存区,下一步就是git commit操作。
HEAD: 当前活跃分支(branch)的游标,可以理解为程序运行指针(PC指针),git 现在在哪个分支,HEAD就指向哪里。通常理解为current指针。
git stash
git stash 可用来暂存当前正在进行的工作,保存当前的工作现场,切换到其他分支进行工作。git stash list 可以查看stash队列。通常每次git stash就会切换一个分支,在该分支上工作也需要保存它的工作现场。这种工作方式可以结合嵌入式中断工作方式的进行理解。中断需要保存断点寄存器状态以及现场保存,当中断服务程序执行完毕以后就会从断点处进行返回。这个过程中会有pop和push操作,同样git stash也有pop:
git stash apply读取暂存区数据,用过apply后暂存区数据依然存在。
git stash pop取出最新的一次暂存数据,取出后这次数据就不会存在于暂存区。
版本管理流程:
分支管理基本命令:
git branch 命令会列出所有分支,当前分支前面会标一个*号。
git branch dev1 命令会新建一个名为dev1的分支。
git checkout dev1 命令会将当前版本指向dev1分支。
git checkout -b dev1 创建并切换到dev1分支。
git merge dev1 将dev1分支合并到当前分支。
git branch -d dev1 删除dev1分支。
解决冲突:
两个性能命令:
git gc
由于在以上图所示的流程中不断修改版本,虽然能够进行记录和跟踪,但是过多的版本会占用过多的磁盘和内存。在大的仓库中git靠压缩历史信息来节约磁盘和内存空间,但是需要注意的是:这种压缩并不是自动压缩,是需要手动操作的。因此在适当时候执行一下git gc指令会提高系统的使用效率。通常在较大的仓库中使用git gc比较耗时间,最好在没做其他任务的时候进行该操作。
git fsck
运行一些仓库的一致性检查, 如果有任何问题就会报告. 这项操作也有点耗时, 通常报的警告就是“悬空对象”(dangling objects).git fsck 保证可靠性。这种悬空可能是多次add造成,除了fsck 命令还有reflog。执行该项操作也是较耗时间。
此次演示mac小技巧:
MAC复制文件或文件夹路径:Option+Command+C
打开终端,输入下面的命令,能在顶部看见完整的地址:
defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES