Git使用入门教程
大纲图

起步 - 关于版本控制
- 什么是“版本控制”?
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
本地版本控制系统
- 使用本地数据库记录文件的历次更新差异

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。
这么做唯一的好处就是简单,但是特别容易犯错。
为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
其中最流行的一种叫做 RCS,它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
集中化的版本控制系统 Centralized Version Control Systems,简称 CVCS
接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 于是,集中化的版本控制系统
- 优点:方便协作、权限控制、相比于维护本地数据库成本更低
- 缺点:容错率低(服务器宕机、服务器数据丢失导致不可恢复的问题)

分布式版本控制系统
- 客户端把代码仓库完整地镜像下来。每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
- 这类系统都可以指定和若干不同的远端代码仓库进行交互。

Git 简介
什么是Git
Git 是目前世界上被最广泛使用的现代软件版本管理系统。
优点
- 速度
- 简单的设计
- 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
- 完全分布式
- 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
安装 Git
- Mac 用户:Xcode Command Line Tools 自带 Git (
xcode-select --install) - Linux 用户:
sudo apt-get install git - Windows 用户:下载 Git SCM
- 对于 Windows 用户,安装后如果希望在全局的 cmd 中使用 git,需要把 git.exe 加入 PATH 环境变量中,或在 Git Bash 中使用 Git。
初始化
基础配置
1 | $ git config --global user.name "your_username" |
git config 常用配置
1 | # 默认情况下,Git 会调用环境变量($VISUAL 或 $EDITOR)设置的任意文本编辑器 |
Git 将配置项保存在三个单独的文件中,允许你分别对单个仓库、用户和整个系统设置。
.git/config– 特定仓库的设置。~/.gitconfig– 特定用户的设置。这也是--global标记的设置项存放的位置。$(prefix)/etc/gitconfig– 系统层面的设置。
所有配置项都储存在纯文本文件中,所以 git config 命令其实只是一个提供便捷的命令行接口。
拓展阅读
How do I make Git use the editor of my choice for commits?
Git log pretty formats
检出仓库
语法
1 | git clone <repo> <directory> |
例子
1 | # 本地仓库 |
克隆某个分支
1 | git clone -b master git@git.hypers.com:Godfery/git-share-salloto.git |
HTTPS和 SSH
- HTTPS:拿到url可以随便clone,但是在push的时候需要验证用户名和密码;可以缓存密码
- SSH:安全,需要在clone前添加SSH Key。SSH 在push的时候,是不需要输入用户名的,如果配置SSH key的时候设置了密码,则需要输入密码的,否则直接是不需要输入密码的。
创建新仓库
1 | git init |
无论什么时候,都可以通过 git status 来查看你的 git 仓库状态。
-—bare标记创建了一个没有工作目录的仓库,这样我们在仓库中更改文件并且提交了。中央仓库应该总是创建成裸仓库,因为向非裸仓库推送分支有可能会覆盖已有的代码变动。将-—bare看成是用来将仓库标记为储存设施,而不是一个开发环境。也就是说,对于所有的 Git 工作流,中央仓库是裸仓库,开发者的本地仓库是非裸仓库。
管理 remote
1 | # 查看当前 remote |
工作方式
本地工作流

你的本地仓库由 git 维护的三棵“树”组成。
第一个是你的工作目录,它持有实际文件;
第二个是缓存区(Index),它像个缓存区域,临时保存你的改动;
最后是HEAD,指向你最近一次提交后的结果。
工作原理

| 术语 | 解释 |
|---|---|
| 仓库(Repository) | 一个仓库包括了所有的版本信息、所有的分支和标记信息。在Git中仓库的每份拷贝都是完整的。仓库让你可以从中取得你的工作副本。 |
| 分支(Branches) | 一个分支意味着一个独立的、拥有自己历史信息的代码线(code line)。 |
| 标签(Tags) | 一个标记指的是某个分支某个特定时间点的状态。 |
| 提交(Commit) | 提交代码后,仓库会创建一个新的版本。这个版本可以在后续被重新获得。 |
| 修订(Revision) | 用来表示代码的一个版本状态。最新的版本可以通过HEAD来获取。之前的版本可以通过”HEAD~1”来获取,以此类推。Git通过用SHA1 hash算法表示的id来标识不同的版本。每一个 SHA1 id都是160位长,16进制标识的字符串。 |
添加与提交
git add
1 | # 添加某个文件 |
git commit
1 | $ git commit |
忽略特定的文件
可以配置 Git 忽略特定的文件或者是文件夹。这些配置都放在 “.gitignore” 文件中。这个文件可以存在于不同的文件夹中,可以包含不同的文件匹配模式。
1 | # 工作目录下的 gitignore,对所有的 clone 有效 |
忽略已被跟踪的文件的更改
1 | # 忽略某个文件的变更 |
拓展阅读
git-ls-files
储藏与取出储藏
git stash
1 | # 储藏当前所有的未提交 回到 HEAD 的状态 |
检查仓库状态
git status
用法
1 | $ git status |

- new file:新文件
- modified:修改的文件
- deleted:删除的文件
- Untracked file:未跟踪的文件
git log
1 | #使用默认格式显示完整地项目历史 |
检出之前的提交
git checkout 这个命令有三个不同的作用:检出文件、检出提交和检出分支。
1 | # 查看文件之前的版本。它将工作目录中的 `<file>` 文件变成 `<commit>` 中那个文件的拷贝,并将它加入缓存区。 |
回滚错误的修改
git revert 和 git reset
1 | # 用来撤销一个已经提交的快照。 |

通过搞清楚如何撤销这个提交引入的更改,然后在最后加上一个撤销了更改的新提交,而不是从项目历史中移除这个提交。这避免了Git丢失项目历史,这一点对于你的版本历史和协作的可靠性来说是很重要的。
撤销(revert)应该用在你想要在项目历史中移除一整个提交的时候。比如说,你在追踪一个 bug,然后你发现它是由一个提交造成的,这时候撤销就很有用。与其说自己去修复它,然后提交一个新的快照,不如用 git revert,它帮你做了所有的事情。
git revert
1 | # 编辑一些文件 |

要将你的 feature 分支整合进 master 分支,你有两个选择:直接 merge,或者先 rebase 后 merge。前者会产生一个三路合并(3-way merge)和一个合并提交,而后者产生的是一个快速向前的合并以及完美的线性历史。下图展示了为什么 rebase 到 master 分支会促成一个快速向前的合并。

1 | $ git reset --hard 9d43f81 |
使用
git reset,就有可能能将master变回之前的那个提交。务必记住,引用日志提供的安全网只对提交到本地仓库的更改有效
保持同步
git remote
1 | # 显示你和其他远程仓库的连接。 |
当你用
git clone克隆仓库时,它会自动创建了一个名为 origin 的远程连接,指向被克隆的仓库。
git fetch
1 | # 拉取仓库中所有的分支。同时会从另一个仓库中下载所有需要的提交和文件。 |
🌰
1 | $ git fetch origin |

1 | # 查看 master 与 origin/master 的区别 |
1 | $ git pull |
用法
1 | # 拉取当前分支对应的远程副本中的更改,并立即并入本地副本。 |
--rebase标记可以用来保证线性的项目历史,防止合并提交(merge commits)的产生。很多开发者倾向于使用 rebase 而不是 merge,因为「我想要把我的更改放在其他人完成的工作之后」。
git push
Push 是你将本地仓库中的提交转移到远程仓库中时要做的事。
1 | # 将指定的分支推送到 `<remote>` 上 |
将本地提交推送到中央仓库的一些标准做法。
1 | # 切换到 master 分支 |
因为我们已经确信本地的
master分支是最新的,它应该导致快速向前的合并,git push不应该抛出非快速向前之类的问题。
1 | # 列出仓库中所有分支。 |
使用分支
git checkout
1 | # 查看特定分支,分支应该已经通过 `git branch` 创建。之后 `<existing-branch>` 成为当前的分支,并更新工作目录的版本。 |
git merge
合并是 Git 将被 fork 的历史放回到一起的方式。git merge 命令允许你将 git branch 创建的多条分支合并成一个。
1 | git merge <branch> |

Git cheat sheet
最后附上cheat sheet 下载链接