1. 基本操作
git init
$ mkdir git-tutorial # 新建目录
$ cd git-tutorial # 进入目录
$ git init # 初始化仓库
- 执行初始化操作会生成一个
.git
目录(该目录存储着管理当前目录内容所需的仓库数据); - 文件的编辑等操作在工作树中进行,然后记录到仓库中,以此管理文件的历史快照;
- 如果想将文件恢复到原先的状态,可以从仓库中调取之前的快照,在工作树中打开。
git status
$ git status # 显示 Git 仓库的状态
git add
$ git add README.md # 向暂存区添加文件
- 如果这是用 Git 仓库的工作树创建了文件,那么该文件并不会被记入 Git 仓库的版本管理对象当中(Untracked files);
- 要让文件成为管理对象,需要加入到暂存区(Stage 或者 Index);
- 暂存区是提交之前的一个临时区域。
git commit
$ git commit -m "First commit" # 保存仓库的历史记录
- 该命令将当前暂存区中的文件实际保存到仓库的历史记录中;
- 通过这些记录,我们可以在工作树中复原文件;
-
-m
参数后面的字符串称作提交信息,是对这个提交的概述; - 如果要记述详细信息,请不加
-m
,直接执行git commit
命令。
git log
$ git log # 查看提交日志
$ git log --pretty=short # 只显示提交信息的第一行
$ git log README.md # 只显示指定目录、文件的日志(README.md)
$ git log -p # 显示文件的改动
$ git log -p README.md # 查看README.md 文件的提交日子以及提交前后的差别
git diff
$ git diff # 查看工作树和暂存区的差别
$ git diff HEAD # 查看工作树和最新提交的差别
PS:不妨养成这样一个好习惯:在执行git commit
命令之前先执行git diff HEAD
命令,查看本次提交与上次提交之间有什么差别,等确认完毕后再进行提交。这里的HEAD
是指向当前分支中最新一次提交的指针。
2. 分支的操作
master -----> master
|---> feature-A
|---> fix-B
- 创建分支后,往往会存在多个最新代码状态;
-
master
分支是 Git 默认创建的分支,基本上所有开发都是以这个分支为中心进行的; - 不同分支进行不同的作业,等该分支完成之后再与
master
分支合并。
/---\ fix-B
master ---------------> master
\--------/ feature-A
git branch
$ git branch # 显示分支一览表
* master # master 分支左侧标有 `*`(星号),表示当前所在分支
git checkout -b
$ git checkout -b # 创建、切换分支
$ git checkout -b feature-A # 切换到 feature-A 分支并进行提交(下面两条命令等同该条命令)
$ git branch feature-A # 创建 feature-A 分支
$ git checkout feature-A # 将当前分支切换为 feature-A 分支
$ git checkout master # 切换到 master 分支
$ git checkout - # 切换回上一分支
- Git 与 SVN 不同,创建分支时不需要连接中央仓库,这让创建分支变得相对轻松;
- 当今大部分工作流程都用到了
特性(Topic)分支
,即集中实现单一特性(主题),除此之外不进行任何作业的分支; - 日常开发中,往往会创建数个特性分支,同时在此之外再保留一个随时可以发布软件的稳定分支;
- 稳定分支通常由
master
分支担当; - 基于特定主题的作业在特性分支中进行,主题完成后再与
master
分支合并。只要保持这样一个开放流程,就能保证master
分支可以随时供人查看。这样一来,其他开发者也可以放心大胆地从master
分支创建新的特性分支; - 主干分支是特性分支的原点,同时也是合并的终点。通常人们会用
master
分支作为主干分支; - 有时我们需要让这个主干分支总是配置在正式环境中,有时又需要用标签 Tag 等创建版本信息,同时管理多个版本发布。拥有多个版本发布时,主干分支也有多个。
git merge
下面演示如何将分支 feature-A
合并到 master
:
首先,切换到 master
分支:
$ git checkout master
Switch to branch 'master'
然后合并 feature-A
分支:
为了在历史记录中明确下本次分支合并,我们需要创建合并提交。因此在合并时加上
--no-ff
参数。
$ git merge --no-ff feature-A
随后编辑器会启动,用于录入合并提交的信息。随后,feature-A
分支的内容就合并到 master
分支中了。
git log --graph
$ git log --graph # 用图表形式输出提交日志
该命令可以清楚看到特性分支的创建以及合并。
3. 更改提交的操作
git reset
/------> fix-B
master ---------------> master
\------------/ feature-A
$ git reset --hard fd0cbf0d4a234f67sjdkfjklbj6786a # 回溯历史版本
HEAD is now at fd0cbf0 Add index
- 要让仓库的 HEAD、暂存区、当前工作树回溯到指定状态,需要用到
git reset --hard
命令,只要提供目标时间点的哈希值,就可以完全恢复至该时间点的状态; - 使用
git reflog
命令可以查看当前仓库执行过的操作日志,只要不进行 Git 的GC
(Garbage Collection,垃圾回收),就可以通过日志随意调取近期的历史状态,就像给时间机器指定一个时间点,在过去未来中自由穿梭一般; - 即便开发者错误执行了 Git 操作,基本也都可以利用
git reflog
命令恢复到原先的状态,请务必牢记!(因为git reflog
命令打印出来的操作前面都有版本哈希码,可以拿来使用)
git commit --amend
$ git commit -amend # 修改提交信息
git rebase -i
$ git rebase -i # 压缩历史
4. 推送至远程仓库
git remote add
$ git remove add origin [email protected]:github-book/git-tutorial.git # 添加远程仓库
git push
$ git push -u origin master # 推送至 master 分支
$ git checkout -b feature-D # 创建 feature-D 分支
$ git push -u origin feature-D # 推送至 feature-D 分支
- 参数
-u
可以在推送的同时,将origin
仓库的master
分支设置为本地仓库当前分支的upstream
(上游); - 添加了这个参数,将来运行
git pull
命令从远程仓库获取内容时,本地仓库的这个分支就可以直接从origin
的master
分支获取内容,省去了另外添加参数的麻烦。
5. 从远程仓库获取
git clone
$ git clone [email protected]:github-book/git-tutorial.git # 获取远程仓库
$ git branch -a # 查看当前分支的相关信息
PS:参数
-a
可以同时显示本地仓库和远程仓库的分支信息。
git pull
git pull origin feature-D # 获取最新的远程仓库分支
6. 帮助深入理解 Git 的资料
- Pro Git 由就职于 GitHub 公司的 Scott Chacon 执笔,是一部零基础的 Git 学习资料。
- LearnGitBranching 是学习 Git 基本操作的网站。注重树形结构的学习方式非常适合初学者,点击右下角的地球标志还可切换各种语言进行学习。
- tryGit 可以让我们正在 Web 上一边操作一边学习 Git 的基本功能(只有英文版)。