
Git学习
版本控制
集中式版本控制:
- 单一的集中管理的服务器,保存所有文件的修订版本
- 协同开发人员通过客户端连接到这台服务器,取出最新的文件或者提交更新
- 集中式版本控制也有一个核心的问题:中央服务器不能出现故障
- 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作
- 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据
分布式版本控制:
- 客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录
- 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复
- 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份
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 | git config --global user.name "" |
别名
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 add
- git remote add gitlab http://152.136.185.210:7888/6666/gitremotedemo.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