文章目录
0 基础知识
0.1 关于版本控制
许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。为了解决这个问题,版本控制系统应运而生。
版本控制系统可以分为本地版本控制系统、集中化的版本控制系统以及分布式版本控制系统,而Git就属于分布式的版本控制系统。
在这类分布式的系统中,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
0.2 什么是 Git
大部分的版本控制系统(CVS、Subversion、Perforce、Bazaar 等
) 都是以文件变更列表的方式来存储信息的,称作基于差异(delta-based)的版本控制。这类系统将它们存储的信息看作是一组基本文件和每个文件随时间逐步累积的差异。
而Git对待数据更像是一个快照流,它把数据看作是对小型文件系统的一系列快照。在Git中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。
0.3 Git的工作流程
我们在Git中的文件有三种状态:已修改(modified)、已暂存(staged)和已提交(committed)。
- 已修改 表示修改了文件,但还没保存到数据库中。
- 已暂存 表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
- 已提交 表示数据已经安全地保存在本地数据库中。
因此我们的 Git 项目也拥有三个阶段:工作区、暂存区以及 Git 目录。
- 工作区 是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
- 暂存区 是一个文件,保存了下次将要提交的文件列表信息(一般在 Git 仓库目录中)。
- Git 仓库目录 是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机Clone仓库时,复制的就是这里的数据。
基本的 Git 工作流程如下:
- 在工作区中修改文件;
- 将你想要下次提交的更改选择性地暂存,将更改的部分添加到暂存区;
- 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。
1 Git 常用操作
1.1 获取 Git 仓库
通常有两种获取 Git 项目仓库的方式:
- 将自己本地的目录转换成 Git 仓库。
- 从 Github 上克隆别人的仓库。
1.1.1 本地目录转换成 Git 仓库:
- 进入该目录,用Git Bash等命令行(我用的Windows)下执行
git init
,初始化。 - 执行
git add <file>
,把想要用Git管理的文件添加到暂存区。(为了方便起见,可以git add <file1> <file2>
同时添加多个文件,或者git add *.txt
把当前目录下的所有.txt文件都添加进来) - 执行
git commit -m "描述信息"
把暂存区的文件进行提交,完成。
1.1.2 从 Github 克隆现有仓库:
使用命令行,执行git clone <url>
,把该仓库完整地拷贝到了当前目录下,完成。
例如,在D:\learngit
目录下执行:git clone https://github.com/libgit2/libgit2
,完成后可以看到,在这个目录下创建了一个名叫“libgit2”的文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。
也可以给克隆下来的仓库重新其一个名字“newname”:git clone https://github.com/libgit2/libgit2 newname
1.2 检查当前文件状态
1.2.1 git status
可以用git status
命令来了解工作区的状态,看看文件是否还未被 Git 追踪、是否修改了但还没暂存、提交。
从打印的信息可以看出这几类状态:
Untracked files:
—— 没被 Git 追踪的文件,即新建的文件但还没提交过。Changes not staged for commit:
——已被 Git 追踪的文件,做了修改但还没添加到暂存区(add)。Changes to be committed:
—— 已被 Git 追踪的文件,做了修改并添加到了暂存区(add),等待被提交(commit)。nothing to commit, working tree clean
—— 该提交的内容都提交了。
git status
命令的输出十分详细,但其用语有些繁琐,可以使用 git status -s
或 git status --short
命令,输出更为紧凑的格式。
$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
- 新添加的未跟踪文件前面有
??
标记 - 新添加到暂存区中的文件前面有
A
标记 - 修改过的文件前面有
M
标记。
输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。
例如,上面的状态报告显示:
README
文件在工作区已修改,但是尚未暂存,Rakefile
文件已修改,但是暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分。lib/git.rb
新添加添加到暂存区。lib/simplegit.rb
文件已修改且已暂存。LICENCE.txt
新添加的文件,Git未跟踪。
1.2.2 git diff
-
git diff <file>
——详细查看文件内容修改前后的对比。 可以见到,当只做出了修改(我去掉了最后一行的“123”),但是没有
add
的时候,git diff readme.txt
是可以输出信息的。其中,红色的是旧信息,绿色的是修改过后的新信息,可以看到少了一行“123”。 当
add
之后,再次git diff readme.txt
就没有输出了,说明它比较的是①文件执行git add
前后的区别。
1.3 版本回退
1.3.1 查看信息
-
git log
——查看我们每次==commit==**(注意:只修改文件或者add
是不会有这个记录的)**的历史记录,越上面的记录越新。 -
git log --pretty=oneline
——单行打印上面的信息,前面黄色是十六进制表示、SHA1计算出来的commit id
(版本号)。
1.3.2 回退
git reset --hard HEAD^
——回退到上一个版本。HEAD
表示当前版本,故:- 回退到上上一个版本——
HEAD^^
; - 回退到往前100个版本——
HEAD~100
。
- 如果想看着每次commit时的message选择版本,可以:
- 记住上面
git log --pretty=oneline
想选择的版本号(前面四五个字符就行,不用全记); git reset --hard <commit id>
在上面的例子中可以看到,我选择看最初始的那个版本,比它更新的版本记录都没了!
1.4 从旧版本返回新版本
git reflog
——记录你的每一次命令,越往上的越新。
- 可以看到,倒数第二次操作的版本号是
d8b9107
; - reset到这一版本:
git reset --hard d8b9107
,再次打印log,可以看到记录又回来了。
2 分支
(待填坑…)