1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-20 22:17:09 +08:00
2019-03-25 17:19:36 +08:00

259 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- TOC -->
- [版本控制](#版本控制)
- [什么是版本控制](#什么是版本控制)
- [为什么要版本控制](#为什么要版本控制)
- [本地版本控制系统](#本地版本控制系统)
- [集中化的版本控制系统](#集中化的版本控制系统)
- [分布式版本控制系统](#分布式版本控制系统)
- [认识 Git](#认识-git)
- [Git 简史](#git-简史)
- [Git 与其他版本管理系统的主要区别](#git-与其他版本管理系统的主要区别)
- [Git 的三种状态](#git-的三种状态)
- [Git 使用快速入门](#git-使用快速入门)
- [获取 Git 仓库](#获取-git-仓库)
- [记录每次更新到仓库](#记录每次更新到仓库)
- [推送改动到远程仓库](#推送改动到远程仓库)
- [远程仓库的移除与重命名](#远程仓库的移除与重命名)
- [查看提交历史](#查看提交历史)
- [撤销操作](#撤销操作)
- [分支](#分支)
- [推荐阅读](#推荐阅读)
<!-- /TOC -->
## 版本控制
### 什么是版本控制
版本控制是一种记录一个或若干文件内容变化以便将来查阅特定版本修订情况的系统 除了项目源代码你可以对任何类型的文件进行版本控制
### 为什么要版本控制
有了它你就可以将某个文件回溯到之前的状态甚至将整个项目都回退到过去某个时间点的状态你可以比较文件的变化细节查出最后是谁修改了哪个地方从而找出导致怪异问题出现的原因又是谁在何时报告了某个功能缺陷等等
### 本地版本控制系统
许多人习惯用复制整个项目目录的方式来保存不同的版本或许还会改名加上备份时间以示区别 这么做唯一的好处就是简单但是特别容易犯错 有时候会混淆所在的工作目录一不小心会写错文件或者覆盖意想外的文件
为了解决这个问题人们很久以前就开发了许多种本地版本控制系统大多都是采用某种简单的数据库来记录文件的历次更新差异
![本地版本控制系统](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3/本地版本控制系统.png)
### 集中化的版本控制系统
接下来人们又遇到一个问题如何让在不同系统上的开发者协同工作 于是集中化的版本控制系统Centralized Version Control Systems简称 CVCS应运而生
集中化的版本控制系统都有一个单一的集中管理的服务器保存所有文件的修订版本而协同工作的人们都通过客户端连到这台服务器取出最新的文件或者提交更新
![集中化的版本控制系统](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3/集中化的版本控制系统.png)
这么做虽然解决了本地版本控制系统无法让在不同系统上的开发者协同工作的诟病但也还是存在下面的问题
- **单点故障** 中央服务器宕机则其他人无法使用如果中心数据库磁盘损坏有没有进行备份你将丢失所有数据本地版本控制系统也存在类似问题只要整个项目的历史记录被保存在单一位置就有丢失所有历史更新记录的风险
- **必须联网才能工作** 受网络状况带宽影响
### 分布式版本控制系统
于是分布式版本控制系统Distributed Version Control System简称 DVCS面世了 Git 就是一个典型的分布式版本控制系统
这类系统客户端并不只提取最新版本的文件快照而是把代码仓库完整地镜像下来 这么一来任何一处协同工作用的服务器发生故障事后都可以用任何一个镜像出来的本地仓库恢复 因为每一次的克隆操作实际上都是一次对代码仓库的完整备份
![分布式版本控制系统](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3/分布式版本控制系统.png)
分布式版本控制系统可以不用联网就可以工作因为每个人的电脑上都是完整的版本库当你修改了某个文件后你只需要将自己的修改推送给别人就可以了但是在实际使用分布式版本控制系统的时候很少会直接进行推送修改而是使用一台充当中央服务器的东西这个服务器的作用仅仅是用来方便交换大家的修改没有它大家也一样干活只是交换修改不方便而已
分布式版本控制系统的优势不单是不必联网这么简单后面我们还会看到 Git 极其强大的分支管理等功能
## 认识 Git
### Git 简史
Linux 内核项目组当时使用分布式版本控制系统 BitKeeper 来管理和维护代码但是后来开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束他们收回了 Linux 内核社区免费使用 BitKeeper 的权力 Linux 开源社区特别是 Linux 的缔造者 Linus Torvalds基于使用 BitKeeper 时的经验教训开发出自己的版本系统而且对新的版本控制系统做了很多改进
### Git 与其他版本管理系统的主要区别
Git 在保存和对待各种信息的时候与其它版本控制系统有很大差异尽管操作起来的命令形式非常相近理解这些差异将有助于防止你使用中的困惑
下面我们主要说一个关于 Git 其他版本管理系统的主要差别**对待数据的方式**
**Git采用的是直接记录快照的方式而非差异比较我后面会详细介绍这两种方式的差别**
大部分版本控制系统CVSSubversionPerforceBazaar 等等都是以文件变更列表的方式存储信息这类系统**将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异**
具体原理如下图所示理解起来其实很简单每个我们对提交更新一个文件之后系统记录都会记录这个文件做了哪些更新以增量符号Δ(Delta)表示
<div align="center">
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3deltas.png" width="500px"/>
</br>
</div>
**我们怎样才能得到一个文件的最终版本呢**
很简单高中数学的基本知识我们只需要将这些原文件和这些增加进行相加就行了
**这种方式有什么问题呢**
比如我们的增量特别特别多的话如果我们要得到最终的文件是不是会耗费时间和性能
Git 不按照以上方式对待或保存数据 反之Git 更像是把数据看作是对小型文件系统的一组快照 每次你提交更新或在 Git 中保存项目状态时它主要对当时的全部文件制作一个快照并保存这个快照的索引 为了高效如果文件没有修改Git 不再重新存储该文件而是只保留一个链接指向之前存储的文件 Git 对待数据更像是一个 **快照流**
<div align="center">
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3snapshots.png" width="500px"/>
</br>
</div>
### Git 的三种状态
Git 有三种状态你的文件可能处于其中之一
1. **已提交committed**数据已经安全的保存在本地数据库中
2. **已修改modified**已修改表示修改了文件但还没保存到数据库中
3. **已暂存staged**表示对一个已修改文件的当前版本做了标记使之包含在下次提交的快照中
由此引入 Git 项目的三个工作区域的概念**Git 仓库(.git directoty) ****工作目录(Working Directory)** 以及 **暂存区域(Staging Area)**
<div align="center">
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3areas.png" width="500px"/>
</div>
**基本的 Git 工作流程如下**
1. 在工作目录中修改文件
2. 暂存文件将文件的快照放入暂存区域
3. 提交更新找到暂存区域的文件将快照永久性存储到 Git 仓库目录
## Git 使用快速入门
### 获取 Git 仓库
有两种取得 Git 项目仓库的方法
1. 在现有目录中初始化仓库: 进入项目目录运行 `git init` 命令,该命令将创建一个名为 `.git` 的子目录
2. 从一个服务器克隆一个现有的 Git 仓库: `git clone [url]` 自定义本地仓库的名字: `git clone [url]` directoryname
### 记录每次更新到仓库
1. **检测当前文件状态** : `git status`
2. **提出更改把它们添加到暂存区**`git add filename ` (针对特定文件)`git add *`(所有文件)`git add *.txt`支持通配符所有 .txt 文件
3. **忽略文件**`.gitignore` 文件
4. **提交更新:** `git commit -m "代码提交信息"` 每次准备提交前先用 `git status` 看下是不是都已暂存起来了 然后再运行提交命令 `git commit`
5. **跳过使用暂存区域更新的方式** : `git commit -a -m "代码提交信息"` `git commit` 加上 `-a` 选项Git 就会自动把所有已经跟踪过的文件暂存起来一并提交从而跳过 `git add` 步骤
6. **移除文件** `git rm filename` 从暂存区域移除然后提交
7. **对文件重命名** `git mv README.md README`(这个命令相当于`mv README.md README``git rm README.md``git add README` 这三条命令的集合)
### 推送改动到远程仓库
- 如果你还没有克隆现有仓库并欲将你的仓库连接到某个远程服务器你可以使用如下命令添加·`git remote add origin <server>` ,比如我们要让本地的一个仓库和 Github 上创建的一个仓库关联可以这样`git remote add origin https://github.com/Snailclimb/test.git`
- 将这些改动提交到远端仓库`git push origin master` (可以把 *master* 换成你想要推送的任何分支)
如此你就能够将你的改动推送到所添加的服务器上去了
### 远程仓库的移除与重命名
- test 重命名位 test1`git remote rename test test1`
- 移除远程仓库 test1:`git remote rm test1`
### 查看提交历史
在提交了若干更新又或者克隆了某个项目之后你也许想回顾下提交历史 完成这个任务最简单而又有效的工具是 `git log` 命令`git log` 会按提交时间列出所有的更新最近的更新排在最上面
**可以添加一些参数来查看自己希望看到的内容**
只看某个人的提交记录
```shell
git log --author=bob
```
### 撤销操作
有时候我们提交完了才发现漏掉了几个文件没有添加或者提交信息写错了 此时可以运行带有 `--amend` 选项的提交命令尝试重新提交
```console
git commit --amend
```
取消暂存的文件
```console
git reset filename
```
撤消对文件的修改:
```
git checkout -- filename
```
假如你想丢弃你在本地的所有改动与提交可以到服务器上获取最新的版本历史并将你本地主分支指向它
```
git fetch origin
git reset --hard origin/master
```
### 分支
分支是用来将特性开发绝缘开来的在你创建仓库的时候*master* 默认的分支在其他分支上进行开发完成后再将它们合并到主分支上
我们通常在开发新功能修复一个紧急 bug 等等时候会选择创建分支单分支开发好还是多分支开发好还是要看具体场景来说
创建一个名字叫做 test 的分支
```console
git branch test
```
切换当前分支到 test当你切换分支的时候Git 会重置你的工作目录使其看起来像回到了你在那个分支上最后一次提交的样子 Git 会自动添加删除修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样
```console
git checkout test
```
<div align="center">
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3切换分支.png" width="500px"/>
</div>
你也可以直接这样创建分支并切换过去(上面两条命令的合写)
```console
git checkout -b feature_x
```
切换到主分支
```
git checkout master
```
合并分支(可能会有冲突)
```java
git merge test
```
把新建的分支删掉
```
git branch -d feature_x
```
将分支推送到远端仓库推送成功后其他人可见
```
git push origin
```
## 推荐阅读
- [Git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html)
- [图解Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html)
- [猴子都能懂得Git入门](https://backlog.com/git-tutorial/cn/intro/intro1_1.html)
- https://git-scm.com/book/en/v2