本教程采用 Markdown 书写, 本教程书写于 2019-06-07 17:28:19. 全程采用问答式书写方法.
-
问: 这个教程是写给谁看的? 答: 写个对 Git 了解不多的人看的, 或者 Git 的新新手.
-
问: 这个教程我能学到什么?
答: 可以学到关于 Git 的基础入门知识和工作实用技巧, 以及我学习 Git 的故事. -
问: 为什么要写个教程?
答: 有三个原因:- 通过输出来检验输入, 这样能够更好的检验自己的知识.
- 我学 Git 浪费了很多时间,我希望把自己的经验更好的传播出去, 让每一个读到的人都少走弯路.
- 写教程或者技术贴有助于交友和提升自己形象.
- 最后补充: 其实也是互相学习, 我又很多不懂的地方, 我目前知识够用, 我未必对 Git的底层原理和某些工具熟悉多少.
-
问: Git 是什么? 答: 我通过以下几个方面来介绍:
- Git 是个版本控制工具.
那么什么是版本控制工具呢? 举个例子, 我国的宪法肯定是与时俱进的, 5 年前改了一次, 3 年前又改了一次, 假设今年又改了一次, 那么如果想记录每次的变化, TODO - Git 是个多人协作工具. TODO
- Git 是个版本控制工具.
-
问: 我为什么要学习 Git?
答: 如果你是程序员肯定要学啊. 如果你是以写作为主的人, 应该也要学学. 如果你跟风学学那也好. -
问: Git 的作者是谁? 答: Linux 的作者, 为了和世界程序员一起协作开发 Linux, 开发了 Git. 它们都是开源的, 具体细节可以去查资料.
-
问: 需要知道 Git 和其他版本控制工具的区别吗?
答: 这个问题不是必须知道的, 你至少需要了解 Git 就好了, 我认为做比较这种事需要了解或者熟悉比较对象. 如果你熟悉 Git或者 SVN, 或者 CVS, 还有很多别的版本管理工具, 你心里大概有数. 如果你不知道别的, 甚至连 Git也不了解, 那么说比较这个话题, 毫无意义. -
问: Git 的使用场合是什么? 答: 程序员开发的时候需要用到. 因为我就是一个程序员. Github 上面的资料不仅仅限于编程, 懂一点 Git也是极好的.
-
问: 怎么开始使用 Git? 答: 首先要下载, 安装, 然后配置一些自己的ID, 邮箱, 然后创建一个仓库或者下载一个仓库, 就可以开始干活了.
具体的细节, 不同的操作系统的过程不一样, 我的教程不是说这些没有意义的细节的. 网上有很多互相抄袭的教程, 说的很明白. [滑稽] -
问: Git 应该是用命令行还是界面工具? 答: 我认为各有优势. 命令行工具是程序员的传统工具, 面对黑乎乎的界面, 你需要从头开始记得很多命令, 需要有一个适应的过程.
但是命令行因为不需要构建 GUI(用户界面), 开发工作量小, 可以接受的参数多, 使用灵活, 所以功能非常的强大. 缺点刚刚也说了, 就是要记住很多命令.
命令行还有一个缺点, 就是阅读体验不好, 尤其是比较两个文件差异的时候, 可读性比较差.
而 GUI 则操作简单, 非常的人性化, 上手很快, 阅读体验好. 但是实现的功能是命令行的子集.
用哪一种, 看自己的与需要, 我本人是两者结合着用, 我喜欢的 GUI 是 Github 的 Git 本地客户端. -
问: Git 的常用命令是什么? 答: 我按顺序结合使用工作场景回忆一下开始使用 Git 的命令, 然后下面挑几个常用的命令来重点介绍一下.
- 下载别人的仓库: git clone 仓库地址
- 创建自己的仓库: mkdir directory_name(名字自取) ; cd directory_name; git init
- 配置自己的 ID 和邮箱, 方便在开发中协作
git config --global user.name notfresh
git config --global user.email [email protected] - 查看项目的历史: git log, 这个命令, 我认为是我使用频率最高, 最重要的命令之一, 我认为必须熟悉使用这个命令.
- 根据任务或者自己的想法, 创建一个文本文件, 然后准备再本地提交, git add new_file.
git add 也是个高频命令. - 我想看一下仓库的情况, 我决定使用 git status, 根据提示, 我清楚的知道了哪些文件修改了.
- 写好了自己的任务或者想法, 我提交一下, 使用 git commit -m '提交说明'.
- 我觉得应该看一下当前的历史, 我使用 git log 再次查看.
- 我觉得我应该把我写的东西拿给别人看了, 我使用 git push 命令. 关于上传代码, 还有多处细节, 我就大致一提.
- 有别的同事也提交了代码, 我赶紧去看看他写的啥, 我使用 git pull origin, 下载了他写的代码.
- 我每天继续循环 5-10,写啊写啊, 写了好久, 项目终于基本写完了.
- 当然, 还有很多意外和惊喜, 在工作中, 所以我必须使用别的命令来处理代码版本控制问题和别的同事的协作问题.
- 话外说一下, 版本控制 Git 在开发中只是起着辅助的作用, 但是用好了也对开发有着极大的帮助.
-
问: Git 使用真有意思, 我想知道更多生动的例子, 去哪里找? 答: 网上的教程很多, 但是写的少的却不多. 就我个人而言, 如何形象的感受 Git 在工作中的应用, 我推荐去看廖雪峰的 Git 教程.
传送门: 廖雪峰的Git教程
PS: 我为什么推荐他的呢? 因为我在学习 Git 的时候, 刚开始看了一些别的网站的教程, 都是一些支离破碎的命令和比较浅的没有系统讲述 Git 使用的, 而且很多教程是互相抄袭的, 你抄我, 我抄你, 特别是 CSDN 上, 批评一下 CSDN 对于创作者的版权保护不够, 现在乌烟瘴气的, 导出是抄袭的文章.
初学不易, 入门辛苦, 大家找对人去带你, 自然很轻松, 我推荐阅读廖雪峰的 Git 教程.
这个教程内容丰富, 生动形象, 白话为主, 学起来相对 Easy, 我觉得三天或者一周左右可以吃透这个教程.
学习的过程中 -
问: 看廖雪峰的教程够吗? 答: 我认为不够. 原因如下:
- 廖雪峰的教程只说了具体的操作, 却并没有说透里面的原理或者工作模型. 也许本身原理比较难说透, 但是, 我认为这个东西是非常重要的, 理解了才能更好地记忆. 知其然而不知其所以然, 特别是对于 Git 这个常用的工具, 是极其不利于工作的.
- 廖雪峰的教程不能完全满足其他高级需求, 有的东西, 我认为没有讲清楚, 也许是我的理解能力有限, 但我确认认为需要阅读别的材料补充和提升.
-
问: 那么看完廖雪峰的教程之后应该怎么办呢? 有哪些好的学习方法?
答: 我忘了说一点了, 写到这里, 其实我知道, 也是回到刚才开头的那个问题, 这个教程是给谁看的, 当然是希望对 Git 精进的新手看的.
凡事都讲究够用原则, 务实一点, 明白自己的需求. 我不是高手, 但是我要提醒一下曾经像我一样的菜鸟们, 接下来 Git 的精进之路.
下面要注意几点:- 使用命令行的时候注意命令的输出信息, 在 shell 里面, 输出的信息是非常重要的的, 出了问题或者有疑问, 提示信息都写的比较清楚, 当然要英语好一点. 在使用 Git 的时候, 每个命令, 都会有相关的操作提示和说明,要好好利用 Git 的提示信息.
- 使用帮助系统, 如果你对 git add 或者 git log 命令不熟悉, 你可以使用 git log --help, 或者 man git 命令. 这是 Linux 的本地文档帮助系统.
- 使用官方在线文档系统. 网址是 https://git-scm.com, 点击去打开 documentation, 里面有详细的内容, 文档分为三个部分, reference, book( ProGit book), videos.
分别指的是 经典的文档系统, 这里面全部用英文写的, 里面有对于各个子命令的解读和各种参数的详细说明, 关于 Git 的一本在线书籍, 阅读起来更友好, 还有就是对于 Git的介绍视频. 可能视频暂时无法观看, 估计是用 Youtube 播放的. 我重点推荐那本 Git 的书. 里面有各个语言版本的, 其中中文的链接在这里, https://git-scm.com/book/zh/v2 , 需要提的一点的是, 中文的翻译质量比较低, 如果英语好的同学自己去看英文. - 在 Github 上的一些仓库里有推荐的 Git 学习资料.
- 去博客园 https://cnblogs.com 里查看好一点的文章.
- 最后还有去 stackoverflow.com 或者知乎等问答网站找自己想要的答案.
以上, 我说了基本的 Git 的学习路径和入门之道. 现在我开始说一下我最想说的几个话题. 关于 Git 的工作模式和高级命令的使用.
-
问: Git 的工作模式是怎样的?
答: git 有三个区, 历史版本区(或者已经提交区), 待提交区(暂存区), 工作区. 还有其他的名字, 英文名分别叫 repository, index 或者 staging area, working directory. 无论他们叫什么名字, 他们的本质都一样的, 而我为了便于理解, 便给他们起名为上面所说的. git 的工作模式是:- 先在工作区工作.
- 然后把工作的东西加入到待提交区, 如果不满意, 还可以撤销.
- 然后检查一下待提交区, OK 了, 就把修改的内容正式提交到历史版本区. git 便会替我们保存起来, 以后恢复就很方便.
- 1-3 的循环往复.
题外话: Git 是如何保存文件的?
我有一个疑惑是Git 如何保存数据的, 为什么可以快速的在各个版本之间快速移动. ProGit 里面提到, Git 保存的是文件的快照, 而不是每次的修改, 所以 Git 可以实现在各个版本和分支(稍后我会解释)之间来回切换, 凭借这一点, Git 在所有版本控制系统之间独领风骚. 确实厉害, 但是直到现在为止, 我还是没有弄明白, 快照是什么, 如果一个 2M 大小的文本被修改了, 那么它的快照有多大呢? 快照是重新拷贝一份吗, 我曾经试过, 修改一个 特定大小的文件, 然后提交, 快照非常的小, 并不是修改后的文件的再次复制.
我并不知道快照在底层文件系统中是如何保存的, 曾经我有几个想法, 会不会是保存一份文件指针, 然后保存几个修改对象指针, 而所谓的快照就是初始文件和快照的集合, 在切换版本和分支的时候, 快速利用指针的集合拼凑成一个文件.
快照是什么, 我如今仍然不得而知. -
问: checkout 命令是什么?
答: 想要搞懂 checkout 命令,首先要理解分支的概念.
什么是分支, 有人说,分支, 就是 git branch new_branch old_branch(或者commitID), 这个命令创建的. 我们需要深入的理解一下, 不能光知其然而不知其所以然. 分支, 就是一个区域, 有起点, 有终点, 起点一个 CommitA, 终点 CommitB. 大名鼎鼎的 master 分支, 我们都熟悉, 自然起点是最早的那个提交, 而终点, 我们可以使用 git show master 查看master的终点.
我们先搁置这个问题, 继续往下看. -
问: 什么是提交?
答: 我在上面说过, 分支就是一段提交的区间, 有起点, 有终点.
在 git 中, 提交是最核心的概念, 提交涉及到很多的底层概念, 我知道的也不多, 因为我也不是专门研究 git的, 如果我专门去研究, 平时又用不到, 那么很快就会忘记.
一次 git commit 就是一次提交, 会生成一个 40 位长的 16 进制 sha1编号, 怎么生成的? 官方书上说的我记不清了,反正是根据文件大小, 时间吧,等多方因素生成的可保证唯一的一串字符.
一次提交记录了提交时间,提交人, 提交的标题, 详细的消息, 等等等等... -
问: 提交和分支的关系?
就我个人而言, 我提出以下理解:
假设有 10 个分支, 按时间从早到晚, C1, C2,.., C10. 有一个分支 master. master 现在指向 C5,起点是 C1.
在C2 的时候, 创建了branchX, 然后 branchX 目前指向 C5, 包含了 4 个分支, 那么如果删掉分支 branchX, C2C5会被删除吗? 不会. 因为 master 还有一段指向 C2C5
再假设, 在C2 的时候, 创建了branchX, 然后 branchX 目前指向 C10, 包含了 9 个分支, 那么如果删掉分支 branchX, 哪些分支被删除?
自然是 C6-C10, 因为包含他们的分支 branchX 已经被删除了.
而 C2-C5 不能被删除, 因为还有 master 分支包含着它们.
总结一下, 分支就是一段提交的区间, 分支的起点呢, 是创建它的那个提交点, 分支的终点, 就是目前
- 问: rebase 是个什么东西?
答: rebase 变基, 打个比方, 分支 master 包含 C1,C2,C3, 分支 branchX 包含 C2, C4, C5.
采用普通的merge策略, 会新建一个提交C6, 让C3, C5都指向C6. C6的内容包含master和branchX都有的内容.
采用rebase, 命令格式为 git rebase BASE_BRANCH TO_REPLAY_BRANCH
在这里使用git rebase master branchX
就是把 C4-C5在C3后续上, 然后branchX指针指向C5, master位置不变, 也就是说分支的指向位置都没变, 只不过提交历史的形状变了.
如果没有冲突顺利合并, 如果有冲突解决冲突.
如果 只写git rebase BASE_BRANCH, 那么git就会假定当前分支就是TO_REPLAY_BRANCH.
总结: 什么是rebase? 变基, 变谁的基? 就拿刚才一个具体的命令来说吧, 当前分支是branchX, 执行`git rebase master branchX`, 或者`git rebase master`, 我们这么理解, 变得就是branchX的基, 基, 英语base, 我们不妨理解为起点. 重新修改branchX的起点, 之前branchX的起点是C2, 现在我们让它的起点改为C3.
-
问: 什么情况下应该用 rebase?
第一种场景:
如果我想手动的自己处理分支, 比如远程仓库已经更新, 我执行如下操作: step1: git fetch origin
step2: git rebase origin/master master :这句话的意思是以origin/master 为base, 把master放到origin/master的末端 这样就可以把提交历史捋直了, 否则就会出现一次merge操作. 上面两句等同于 git pull --rebase: 把本地的放到远程的上面, 让本地的提交包括远程的提交.有一种错误的rebase, 在step2, 执行 git rebase master origin/master, 因为origin/master是不可以移动的, git会自动拷贝一个提交历史放到master的前面, 这样一来, 尽管内容是相同的, 可是本地的分支包含了远程分支没有的提交历史, 中间夹了几个本地提交的分支, 就会导致无法推送. 感兴趣的不妨试一下.
-
问: 远程分支怎么用? 如何查看远程分支? TODO
使用命令git branch -v
和git branch -vv
, 当然这看的都是离线版的, 如果想拉取远程最新的, 使用git fetch REMOTE
, 然后再执行. -
问: fetch 命令是什么?
拉取远程提交. -
什么是 cherry-pick 命令?
-
什么是 git clean 命令?
使用场景: 如果不小心给工作区加了很多垃圾, 想要批量删除这些还没暂存的垃圾, 就应该使用git clean命令.