本文概述:
Git概述 | ① 什么是版本管理系统 | ② Git和SVN的区别 |
③ Git的四个组成部分 | ④ Git中文件的几个状态 | |
⑤ Git中的四类对象 | ||
Git下载安装配置 | ||
Git本地基本操作 | ① 配置「git config」 | ② 获取帮助「git help」 |
③ 创建Git仓库「git init」 | ||
④ 添加文件到暂存区「git add」 | ||
⑤ 让Git不跟踪特定文件「.gitignore文件」 | ||
⑥ 暂存区内容提交到本地仓库「git commit」 | ||
⑦ 查看工作区与暂存区状态「git status」 | ||
⑧ 内容变化,差异对比「git diff」 | ||
⑨ 查看历史提交记录「git log」 | ||
⑩ 查看某个文件的改动记录「git blame」 | ||
⑪ 设置Git命令别名「git config --global alias」 | ||
⑫ 为重要提交打标签「git tag」 | ||
Git文件恢复与版本回退 | ① 文件恢复,未add「git checkout」 | |
② 文件恢复,已add未commit「git reset HEAD」 | ||
③ 版本回退,已commit「git reset --hard」 | ||
④ 查看输入过的指令记录「git reflog」 | ||
⑤ 撤销某次提交「git revert」 | ||
⑥ 查看某次提交的修改内容「git show」 | ||
⑦ 查看分支最新commit的Hash值「git rev-parse」 | ||
⑧ 找回丢失对象的最后一点希望「git fsck」 | ||
Git本地分支 | ① 分支的概念 | ② 创建其他分支的原因 |
③ 一个简单的分支管理策略 | ||
④ 分支的创建于切换「git branch」 | ||
⑤ 分支合并「git merge」 VS 「git rebase」 | ||
⑥ 解决合并冲突 | ⑦ 删除分支 | |
⑧ 恢复误删分支「git log --branches」 | ⑨ 分支重命名 | |
⑩ 切换分支时暂存未commit的更改「git stash」 | ||
⑪ 把commit从一个分支挪到另一个分支「git cherry-pick」 | ||
Git远程仓库 | ① 远程仓库概述 | |
② 本地仓库与远程仓库建立关联「git remote」 | ||
③ 推送本地仓库到远程仓库「git push」 | ||
④ 克隆远程仓库「git clone」 | ||
⑤ 同步远程仓库更新「git fetch」VS「git pull」 | ||
⑥ git push 时的unrelated history问题 | ||
⑦ SSH Key避免每次push重复输入账号密码 | ||
Git工作流 | ① 集中式工作流 | ② 功能分支工作流 |
③ Gitflow工作流 | ④ Forking工作流 | |
⑤ Pull Request工作流 | ||
其他杂项 | ① 为开源项目贡献代码 | ② SourceTree使用详解 |
0x1、Git概述——分布式版本控制系统
了解Git相关的概念,有助于后续命令的掌握~
1. 什么是版本管理系统
VCS(Version Control System),一种用于记录一个或多个文件内容变化 历史,以便将来能对特定版本的历史记录进行查看,更改,备份还原的系统。 可以简单类比为「游戏存档」,打Boss前存下档,没过关,重新读档; 分支剧情,想体验不同选择触发的不同剧情,可以存多个档, 想玩哪个读哪个。
VCS一般分为下述三类:
1.本地VCS
使用简单的数据库来记录文件的历史更新差异,比如RCS。
2.集中式VCS
用一个服务器来保存所有文件的修订版本,协同工作的人连接这个服务器, 获取或提交文件更新,比如SVN。
这种协同方式有个两个明显的缺点: 1.「需要联网」:同步和推送更新速度受带宽限制,内网还好,外网可能会有点慢了(大文件); 2.「依赖中央服务器」:每个人的本地只有以前所同步的版本,如果服务器宕(dang)机了,谁都无法获取或提交更新。
3.分布式VCS
每个用户拥有完整的提交历史,支持离线提交更改,查看历史提交记录等。中央服务器更多的只是用作更改合并,同步的工具,比如Git。
从根本上来说,Git是一个内存寻址的文件系统,根据文件的Hash值来定位文件。 这个40位的Hash值使用SHA1算法生成,由两部分拼接:header = "<type>" + content.length + "\0"(参数依次为:对象类型,数据字节长度,空字节(用于分隔header与content)hash = sha1(header+content),这里的拼接是二进制级别的拼接,而非字符串拼接。
2. Git与SVN的区别
Git和SVN除了上面说的联网需求不同外,还有「存储差异」:
SVN关心:文件内容的具体差异;而Git关心:文件整体是否发生改变。 SVN每次提交记录的是:「哪些文件进行了修改,修改了哪些行的哪些内容」。
如图,Version 2中记录的是文件A和C的变化,而Version 3中记录文件C的变化,以此类推; 而Git中,并不保存这些前后变换的差异数据,而是保存整个缓存区中的所有文件, 又称快照,「有变化的文件保存,没变化的文件不保存,而是对上次保存的快照做一个链接」, 因为这种不同的保存方式,使得Git切换分支的速度比SVN快上不少。
当然SVN也有它的优点,比如「权限控制」,可以设定每个账户的读写权限,而Git中 则没有响应的权限控制。至于用哪个的,还是看公司要求吧~
3. Git的四个组成部分
简单说下Git的四个组成部分:
- 工作区:不包含.git文件夹在内的整个项目目录,所有修改都在工作区内进行。
- 暂存区:又称索引区,本地文件修改后,执行add操作会把工作区的修改添加到缓存区。
- 本地仓库:当执行commit操作时,暂存区的数据被记录到本地仓库中。
- 远程仓库:托管项目代码的服务器,多人协作时通过远程仓库进行代码同合并与同步。
接下来说下这几个部分是如何协同工作的:
工作区与暂存区:工作区更改,通过git add命令可以把更改提交到暂存区; 也可以git checkout命令使用暂存区内容覆盖当前的工作区的内容。
暂存区与本地仓库:可以通过git commit命令把暂存区的内容提交到本地仓库, 每次commit都会生成一个快照,快照使用Hash值编号。可以通过git reset Hash值, 把某个快照还原到暂存区中。
工作区和本地仓库:通过git checkout 快照编号,直接把某个快照还原到工作区中。
本地仓库和远程仓库:可以通过git push命令把commit推送到远程仓库,多人协作的 时候可能还需要进行一些冲突处理;还有通过git clone拉取某个远程仓库的项目到本地, 或通过git fetch拉取远程仓库的最新内容,检查后决定是否合并到本地仓库中。
工作区和远程仓库:这里两者的协作一般是git pull,即把远程主机的最新内容拉取下来后直接合并。
4. Git中文件的几个状态
按照大类划分,可以分为两种状态:Tracked(已跟踪)和Untracked(未跟踪), 依据是:「该文件是否已加入版本控制」?
文件状态变化周期流程图:
流程简述:
假设某个项目已加入Git版本控制系统
- 1.新建一个文件,该文件处于
Untracked
状态;
- 2.通过git add命令添加到缓存区,此时文件处于**
Tracked
状态又或者说 此时这个文件已经被版本控制系统所跟踪,而且他处于Staged
**(暂存)状态;
- 3.通过git commit命令把暂存区的文件提交提交到本地仓库,此时文件处于
Unmodified
(未修改)状态;
- 4.此时如果去编辑这个文件,文件又会变成**
Modified
**(修改)状态;
5. Git中的四类对象
在Git系统中有四种类型的对象,几乎所有的Git操作都是在这四种对象上进行的,依次为:Blob
(块)对象,Tree
(树)对象,Commit
(提交)对象,Tag
(标签)对象。前三者的关系如图所示:
接着我们来详解的讲解这四类对象:
① 块对象(Blob)
一块二进制数据,「仅存放文件内容」,不包括文件名、权限等信息。Git会根据文件内容计算 出一个Hash值,以这个Hash值作为文件索引保存起来。意味着,相同文件内容的文件,只会保存 一个,即共享同一个Blob对象。可以使用:
git hash-object 文件名
来计算文件内容的Hash值。 如果你知道已经添加到Git中的某个文件的hash值,还可以通过git cat-file hash值
来读取数据 对象,可选参数:-p
(查看Git对象内容) ,-t
(查看Git对象类型),示例如下:
② 树对象(Tree)
保存一个或多个块对象的引用,每次commit对应一个树对象,这里生成一个commit, 然后调用**
git ls-tree Hash值
** 查看树对象的内容:
利用上面的 git cat-file -p hash值
来查看blob块的具体内容:
除了保存块对象的引用外,树对象还可以引用「其他树对象」,从而构成一个「目录层次结构」。 新建一个test目录,复制一个1.txt文件到这个路径下,提交一个commit,然后查看树对象的内容:
可以指向了另一个tree对象,这个tree对象指向另一个1.txt文件,树对象解决了文件名的问题。 而对于提交的人、时间、说明信息等,我们还需要通过提交对象进行了解。
③ 提交对象(Commit)
保存树对象的Hash值,父Commit的Hash值,提交作者、时间、说明信息。 同样可以使用**
git cat-file
**命令查看commit对象:
④ 标签对象(Tag)
一般会对某次重要的commit加TAG,以示重要,分为两种情况:
- 轻量级标签:不会创建真正的TAG对象,而是直接引用commit对象的Hash值。
- 附加标签:会创建TAG对象,TAG对象中包含commit对象的引用,除此之外会创建 一个文件:
.git/refs/tags/标签名
,里面保存TAG对象的引用。
这里为我们上面的两个commit一次打上两种标签,然后看下具体的结果:
0x2、Git下载安装配置
- Windows系统:到 Git For Windows 或 git-for-windows.github.io下载,傻瓜式下一步。
- Linux系统:到 Download for Linux and Unix 下载,如果是Ubuntu的话,直接Terminal键入:
sudo apt-get install git
安装即可。
- Mac系统:到 Installing on Mac 下载,不过新系统貌似默认已经带有Git了,另外如果安装了 Homebrew的话可以直接命令行键入:
brew install git
进行安装。
0x3、Git本地基本操作
1. 相关配置「git config」
安装完后,使用Git还需要进行环境的配置,配置信息保存在gitconfig文件中,有三种级别:
- system(系统):系统中所有用户都会生效,配置文件:
C:\Program Files\Git\mingw64\etc\gitconfig
, 不同的系统可能不一样,你可以通过:git config -e --system
,底部可以找到配置文件的路径:
- global(全局):当前系统用户下生效,配置文件:
C:/Users/当前用户/.gitconfig
, 同样可以采用上面的:git config -e --global
查看配置文件的位置。
- local(本地):配置仅在当前项目生效,配置文件:
项目路径/.git/config
配置生效优先级:local > global > system,常用命令:
# 配置 git config --global user.name "用户名" # 配置用户名 git config --global user.email "用户邮箱" # 配置邮箱 git config --global core.editor 编辑器 # 配置编辑器,模式使用vi或者vim # 查看配置 git config --global user.name # 查看配置的用户名 git config --global user.email # 查看配置的邮箱 # 查看所有配置列表 git config --global --list # 查看全局设置相关参数列表 git config --local --list # 查看本地设置相关参数列表 git config --system --list # 查看系统配置参数列表 git config --list # 查看所有Git的配置(全局+本地+系统)
除了命令行的方式外,你还可以直接去编辑对应的配置文件。
2. 获取帮助「git help」
git help 命令 # 查看某个git命令的介绍,用法 git 命令 --help # 另一种写法
3. 创建本地仓库「git init」
git init 仓库名 # 创建一个新的带Git仓库的项目 git init # 为已存在的项目生成一个Git仓库
4. 添加文件到暂存区「git add」
git add 文件名 # 将工作区的某个文件添加到暂存区。 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件 git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件 git add . # 将当前工作区的所有文件都加入暂存区 git add -i # 进入交互界面模式,按需添加文件到缓存区
很多人应该没用过交互界面模式,这里演示下用法:
流程简述:
- 在GitTest文件夹中新建两个文件;
- 键入git add -i,进入交互界面模式,键入4,选择添加untracked(未标记)的文件;
- 根据未标记文件的序号来添加文件,输入?会弹出相关提示,直接回车,结束选择;
- 键入4,可以看到已经不存在untracked的文件了。