版本控制

集中式版本控制:

  • 单一的集中管理的服务器,保存所有文件的修订版本
  • 协同开发人员通过客户端连接到这台服务器,取出最新的文件或者提交更新
  • 集中式版本控制也有一个核心的问题:中央服务器不能出现故障
    • 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作
    • 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据

分布式版本控制:

  • 客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录
  • 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复
  • 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份

Bash – CMD – GUI

Bash,Unix shell 的一种,Linux 与 Mac OS X 都将它作为默认 shell。

  • Git Bash 就是一个 shell,是 Windows 下的命令行工具,可以执行 Linux 命令
  • Git Bash 是基于 CMD 的,在 CMD 的基础上增添一些新的命令与功能
  • 所以建议在使用的时候,用 Bash 更加方便

Git CMD

  • 命令行提示符(CMD)是 Windows 操作系统上的命令行解释程序
  • 在 Windows 上安装 git 并且习惯使用命令行时,可以使用 cmd 来运行 git 命令

Git GUI

  • 基本上针对那些不喜欢黑屏(即命令行)编码的人
  • 它提供了一个图形用户界面来运行 git 命令

配置

每台计算机上只需要配置一次,程序升级时会保留配置信息

可以在任何时候再次通过运行命令来修改它们

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量:

  • /etc/gitconfig 文件:包含系统上每一个用户及他们仓库的通用配置
  • 如果在执行 git config 时带上 –system 选项,那么它就会读写该文件中的配置变量
  • 由于它是系统配置文件,因此需要管理员或超级用户权限来修改它。(开发中通常不修改)
  • ~/.gitconfig 或 C/用户/coderwhy/.gitconfig 文件:只针对当前用户
    • 可以传递 –global 选项让 Git 读写此文件,这会对你系统上 所有 的仓库生效
  • 当前使用仓库的 Git 目录中的 config 文件(即 .git/config):针对该仓库
    • 你可以传递 –local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它(不经常使用)
1
2
3
4
5
git config --global user.name ""
git config --global user.email ""

git config list 查看配置信息

别名

Git 并不会在输入部分命令时自动推断出你想要的命令

如果不想每次都输入完整的 Git 命令,可以通过 git config 文件来轻松地为每一个命令设置一个别名

git 仓库

方式一:

  • 初始化一个 Git 仓库,并且可以将当前项目的文件都添加到 Git 仓库中(目前很多的脚手架在创建项目时都会默认创建一个 Git 仓库) git init

方式二:

  • 从其它服务器 克隆(clone) 一个已存在的 Git 仓库(第一天到公司通常我们需要做这个操作) git clone 仓库地址

文件状态

两个状态

  • 未跟踪:默认情况下,Git 仓库下的文件也没有添加到 Git 仓库管理中,我们需要通过 add 命令来操作
  • 已跟踪:添加到 Git 仓库管理的文件处于已跟踪状态,Git 可以对其进行各种跟踪管理

已跟踪的文件又可以进行细分状态划分:

  • staged:暂缓区中的文件状态
  • Unmodified:commit 命令,可以将 staged 中文件提交到 Git 仓库
  • Modified:修改了某个文件后,会处于 Modified 状态

Git 操作流程图

git commit -a -m “提交说明” 可以一次性 add 在 commit

检测状态 git status

校验和

Git 中所有的数据在存储前都计算校验和,然后以 校验和 来引用。

查看提交的历史 – git log

git log

git log —pretty=online

git log —pretty=online —graph (多分支)

版本回退 – git reset

通过 HEAD 来改变 Git 目前的版本指向:

  • 上一个版本就是 HEAD^,上上一个版本就是 HEAD^^
  • 如果是上 1000 个版本,我们可以使用 HEAD~1000
  • 我们可以可以指定某一个 commit id
  • git reset –hard HEAD^
  • git reset –hard HEAD~1000
  • git reset –hard 2d44982

git reflog 记录完整的操作记录 回退到 1 版本,如果想回退回来,通过 git reflog 拿到 id,回退回来

远程仓库

本地 init 一个 git 仓库,需要和远程仓库建立连接

添加远程仓库

查看远程仓库

  • git remote
  • git remote –v

重命名远程仓库

  • git remote rename gitlab glab

移除远程仓库

  • git remote remove gitlab

一些问题

交互

从远程仓库 clone 代码:将存储库克隆到新创建的目录中

将代码 push 到远程仓库:将本地仓库的代码推送到远程仓库中

  • git push
  • git push origin master
  • 默认情况下是将当前分支(比如 master)push 到 origin 远程仓库的

从远程仓库 fetch 代码:从远程仓库获取最新的代码

  • git fetch
  • git fetch origin
  • 默认情况下是从 origin 中获取代码

获取到代码后默认并没有合并到本地仓库,我们需要通过 merge 来合并

  • git merge

从远程仓库 pull 代码:上面的两次操作有点繁琐,我们可以通过一个命令来操作

  • git pull
  • git fetch + git merge(rebase)

git clone 的分支默认就追踪分支了

Git 提交对象

进行提交操作时,Git 会保存一个提交对象(commit object):

  • 该提交对象会包含一个指向暂存内容快照的指针
  • 该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针
    • 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象
    • 而由多个分支合并产生的提交对象有多个父对象

git cat-file -p 查看文件内容

git cat-file -b 查看文件类型

分支

master 分支

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。

Git 的默认分支名字是 master,在多次提交操作之后,其实已经有一个指向最后那个提交对象的 master 分支

master 分支会在每次提交时自动移动

Git 的 master 分支并不是一个特殊分支。

  • 它就跟其它分支完全没有区别
  • 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它

创建分支

Git 是怎么创建新分支的呢?

  • 很简单,它只是创建了一个可以移动的新的指针

比如,创建一个 testing 分支, 你需要使用 git branch 命令:

  • git branch testing

Git 又是怎么知道当前在哪一个分支上呢?

  • 也很简单,它有一个名为 HEAD 的特殊指针

git checkout testing 相当于 HEAD 指针指向了 testing

分支提交

是互相不影响的,这也就是为什么可以多人合作

git checkout -b 一条命令搞定创建并切换

分支开发与合并

一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流。

  • 开发某个项目,在默认分支 master 上进行开发
  • 实现项目的功能需求,不断提交
  • 并且在一个大的版本完成时,发布版本,打上一个 tag v1.0.0
  • 继续开发后续的新功能,正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补, 你将按照如下方式来处理:
  • 切换到 tag v1.0.0 的版本,并且创建一个分支 hotfix;
  • 想要新建一个分支并同时切换到那个分支上,你可以运行一个带有 -b 参数的 git checkout 命令

分支上开发、修复 bug:

  • 我们可以在创建的 hotfix 分支上继续开发工作或者修复 bug
  • 当完成要做的工作后,重新打上一个新的 tag v1.0.1
  • 切换回 master 分支,但是这个时候 master 分支也需要修复刚刚的 bug,所以我们需要将 master 分支和 hotfix 分支进行合并
    • git checkout master
    • git merge hotfix

merge 后 commit 会有两个 parent 指向 如 C5

查看 删除

git branch # 查看当前所有的分支

git branch –v # 同时查看最后一次提交

git branch –merged # 查看所有合并到当前分支的分支

git branch –no-merged # 查看所有没有合并到当前分支的分支

git branch –d hotfix # 删除当前分支

git branch –D hotfix # 强制删除某一个分支

git flow

release 一般指待发布版本,需要测试完成在发布

远程分支

git rebase

它的原理是首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master) 的最近共同祖先 C2;

然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件;

然后将当前分支指向目标基底 C3;

最后以此将之前另存为临时文件的修改依序应用

git checkout master

git merge experiment