Git初学指南
# GitHub初学指南
[toc]
专家盲点(expert blind spot)就是对一个事物知道的越多,就越发不记得“不知道这个事”的情形。
写教程的人都是几年以上的程序员,他们往往直接就告诉你所有命令的含义或者整个体系。
# 什么是 Github ?
# 为什么每个人都需要学会使用 GitHub?
先介绍一下 GitHub:如果你去百度 GitHub 是什么,很可能会看到下面这句话:
GitHub 是一个软件代码托管平台。
这句话没有什么问题,但对不是做技术的人来说,就比较难以理解。 按我的理解,这句话直白的解释就是:GitHub 是一个存放软件代码的网站。
之所以要将代码放在网站上,可能有这么两个原因:
- 软件开源,即编写软件的代码对所有人公开,所有人可以在现有代码的基础上进行二次开发,减少不必要的重复劳动( 简称不要重复「造轮子」)
- 方便团队协作。这个过程有点像是我们把文档放在石墨或语雀这类支持团队协作的平台上,而 GitHub 上存放的是代码,参与编写软件的人可以通过 Git(版本控制工具)从 GitHub 拉取或往 GitHub 上传代码
Github是代码托管平台,是协作的工具;而Git是版本控制工具。Git不需要联网,在本机就可以使用,例如我经常用它来保存论文修改的中间状态文稿。Git也可以和其他的代码托管平台结合使用。
Git 是由 Linux 之父 Linus Tovalds 为了更好地管理linux内核开发而创立的分布式版本控制/软件配置管理软件。
简单来说,Git 是一个管理你的「历史记录」的工具。
注意 Git 是一个独立软件,是一个版本控制工具,而 Github 是一个网站,二者要区分开。注意 Git 是一个独立软件,是一个版本控制工具,而 Github 是一个网站,二者要区分开。
在很多人的印象中,GitHub主要是程序员写代码会使用到的工具。事实上,GitHub最主要的特性是版本管理和协同工作,这意味着不仅是程序员,非技术人员也可以使用它更高效地完成很多工作。
# 如何快速入门Github?
首先请熟悉GitHub使用过程中的常见术语:
- 仓库(Repository):可以看作是存代码和文件一个文件夹,当你作为仓库管理者时,可以设置访问权限
- 远程仓库(Remote Repository):可以看作仓库的副本,通常在此完成修改,日后用于补充到仓库主干上
- 主干(master或main):当前项目所在的状态
- 分支(Branch):可以看作主干的副本,可暂时存储修改的状态,常用于针对主干做更新
- 提交更新(Push):将修改提交到仓库中
- 获取更新(Pull):将仓库上的更新同步到现在的工作状态
- 观察(watch):如果我们Watch了一个项目,之后,如果这个项目有了任何更新,我们都会在第一时候收到该项目的更新通知。
- 分支(fork):如果我们对某一个项目比较感兴趣,并且想在此基础之上开发新的功能,这时我们就可以Fork这个项目,这表示复制一个完成相同的项目到我们的 GitHub 账号之中,而且独立于原项目。之后,我们就可以在自己复制的项目中进行开发了。
- 合并请求(Pull request):用于将分支上的修改合并到主干上。此功能是建立在Fork之上的,如果我们Fork了一个项目,对其进行了修改,而且感觉修改的还不错,我们就可以对原项目的拥有者提出一个Pull请求,等其对我们的请求审核,并且通过审核之后,就可以把我们修改过的内容合并到原项目之中,这时我们就成了该项目的贡献者。
- 合并(Merged):分支上的更改被合并到主干上,仓库状态更新。如果别人Fork了我们的项目,对其进行了修改,并且提出了Pull请求,这时我们就可以对这个Pull请求进行审核。如果这个Pull请求的内容满足我们的要求,并且跟我们原有的项目没有冲突的话,就可以将其合并到我们的项目之中。
- 问题(Issues):如果我们开源一个项目,别人看了我们的项目,并且发现了bug,或者感觉那个地方有待改进,他就可以给我们提出Issue,等我们把Issues解决之后,就可以把这些Issues关闭。
- 收藏(Star):当我们感觉某一个项目做的比较好之后,就可以为收藏这个项目,我们收藏过的项目,都会保存到我们的Star之中,方便我们随时查看。在 GitHub 之中,如果一个项目的点星数能够超百,那么说明这个项目已经很不错了。
- Gist:如果我们没有项目可以开源或者只是单纯的想分享一些代码片段的话,我们就可以选择Gist。不过说心里话,如果不翻墙的话,Gist并不好用。
GitHub 上的多数内容都为英文,但这没关系,你可以使用浏览器右键自带的翻译功能,将页面内容翻译为中文,基本可以忽视语言带来的影响。
如果你想快速找到某个 GitHub 项目提供的「安装包」下载链接,可以查看项目右侧是否有一个「Releases」的模块。Releases 翻译为「发布」,即常说的软件发版或上线,点击下方的软件版本号,一般就可以快速找到软件的下载链接啦。
当多人协作时,建议在不同的分支上工作,当完成更新后,可以通过合并请求(⌘/Ctrl + R)将你的分支上的更新合并到主干上。此时,软件会自动引导你跳转到网页端创建请求,团队的成员就可以审核更改,如果符合要求,更新就可以被合并到主干上。建议设置合并请求的模板,将更新的信息填写清楚会节省很多沟通的时间,日后回看时也有迹可循。可以在我们的仓库中找到对应的模板,并根据自己的需求对模板进行修改,运用在你自己的项目中。
有时同步(Pull)仓库时会发生冲突,原因大多是本地的更新没有同步到分支上,而其他人已经更新了分支,这时,在同步前需要将你的更新搁置(Stash)或者放弃(Discard),这两个操作可以在顶部Branch菜单里找到。掌握了这些基本知识和技能后,你能够很顺利地使用GitHub进行文件管理、协同合作。
# 如何使用GitHub
# 创建新的仓库
Github 上的操作都是围绕一个个的项目展开的。Github 上的项目有一个新名称叫做「repositories」也就是你的仓库,Repository 是放项目的地方。
一个项目其实就是一个文件夹,里面放着所有的项目文件,可以是代码,也可以是任意的文档。但是在 Github 这里,每一个项目都不仅仅是最新版本的代码,还保持着所有的历史版本和修改记录。
登录后再到首页,看到的就不是欢迎界面了,而是「 dashboard 」控制面板。
注意要勾选 「 Initialize this repository with a README」(如果要导入现有存储库,请跳过此步骤)如果在自己项目中初始化好了,然后要提交到远程仓库中去,这个时候就不勾选。
如果想模拟一下开发环境,就是已经有了一个线上项目初始化过了,这个时候就先勾上。然后创建这个项目。也会看到 Create Repository ,也就是创建仓库按钮的上方还有两个选择框,一个是关于 .gitignore 的,另一个是关于 LICENSE 的。这两项如果选择了就是在项目中又多了两个文本文件,一个是 .gitignore 文件,另一个是 LICENSE 文件,暂时都不选就可以,回头需要了可以自己用编辑器新建。
点创建按钮,属于我们自己的一个项目就创建成功了。
# 编辑项目
创建项目完成后,就会跳转到页面。这里的几乎每一个可以点的地方都会涉及到一个新概念,不用着急,咱们一点点的学。先来瞄准一个最为重要的,叫 commit 。
「commit 」执行某个重要的操作。每次项目修改后,点击 commit 按钮就可以生成一个新的版本。例如 commit suicide(自我了断)。但是在 GitHub里,意思是版本或保存版本的意思。
「 Create new file」创建一个新文件。新建一个文件叫泽米人设.md。填写文件名和文件内容。
下面 Commit new file 部分填写的是“版本留言”( Commit message ),说明一下为什么要做这次修改,一方面这是跟队友沟通的一种形式,另一方面如果项目版本多了,这个留言也相当于自己的笔记。上面填写一个一行的留言,下面还可以写详细留言,不过详细留言这一项是可选的。最后,点击 Commit new file ,也就是”把这个文件做到版本中“,按钮,一个新版本就做好了。
回到客户端在你头像旁边给你这次提交内容起一个名字(必填),再次寻找会很方便。然后点下面的 Commit to master,还有右上角的 Sync(同步) 就好啦!
如果是云端要提取到本地git pull即可。
回到GitHub desktop客户端,选择History 然后点击小齿轮,选择roll back to this commit就可以回退到之前的版本。
这样,一次项目编辑工作就结束了,不但是做了文件修改,而且也新添加了一个版本。
# 项目历史线
所有的版本就构成了「 Project History」项目历史线。
编辑操作进行完毕,自动跳转回项目页面之后,会发现原来 1 commit 的地方,现在已经变成 2 commits 。
点击2 commits就进入了项目历史界面,看到的就是项目历史线了,可以看到历史线上已经有了两个版本。点开历史线上的最新一个版本,可以看到这个版本的详细情况。一个版本中最核心的内容就是这 4 个 w 了,谁( who )在什么时间( when )改了那些内容( what ),最后一个是为什么要改( why ),这个是版本留言发挥的作用。
这里还可以看到「Commit id 」当前版本号,同时还显示了它之前的一个 commit 的版本号,也就是它的「parent 」父版本的版本号。
有些版本工具是以 1,2,3… 作为版本号的,但是 Git 这里每个版本号都是 40 位十六进制数,当然有时候可以采用简写形式,取前几位来代表整个的版本号。这样的长长的版本号,表面看起来稍微麻烦一些,但是实际上妙用无穷,这里我们暂时不展开了。
好,对项目历史线的介绍就是这些了。
# 克隆到本地
如果你不想新建一个存储库,看到杜嘉禾之前写过一个好的项目,想把他的直接全部偷过来,修改修改就成你自己的了,这应该怎么办呢?「fork」就可以把他的「仓库」变成你自己的。
「仓库」在云端,你要把它摘下来放到自己的电脑上修改才方便,这就被叫做「clone」
# 发布一个GitHub仓库时需要注意的东西
首先,一个稍微正常点的Git仓库都一定要注意的东西:
- 不要上传目标文件,除非你以非程序员为目标用户
- 不要上传与仓库本身无关的文件(你需要gitignore)
- 尽可能有LICENSE和README
# 为什么不要上传目标文件
先说一句,目标文件包含Code Generator生成的代码,比如Lex和Yacc生成的Lexer和Parser。
根据评论区,JavaScript库要上传一个
什么意思呢?举个例子,我有一个Java的仓库, 然后我把所有编译生成的*.class文件全部上传(注意是编译生成的,如果你有手写的字节码当我没说),这就很智障了。 你当用户是傻的啊。。。
- 如果是想review你的代码,不需要看也无法看*.class的内容
- 大量的*.class以及每次编译都导致的更新(因为你编译一次,对应的*.class也会变)会让仓库变得巨大(因为Git等同对待二进制文件),每次push都会很慢
- 如果是想clone你的仓库,看见那巨大的仓库体积一般人都会知难而退
- 几乎每次增量编译都会影响到Git监控,虽然目前我没遇到过不过这一定会导致后期git gc和git commit很慢
这已经是十分充分的理由了。所以,JVM程序员把*.class,.apk和.jar加入gitignore吧; Rust程序员把*.exe和.d之类的加入gitignore吧; Gradle用户把build目录和.gradle目录加入gitignore吧。
一般情况下,目标文件是放在GitHub的release界面的。比如我之前看到过一个E站客户端,就是在release界面放了个apk。毕竟这种东西有时体积不能控制,但你又要面向不方便自己构建的人使用,那就在release里面放目标文件吧。
# 与仓库本身无关的文件
我觉得这没什么难理解的。比如:
- 我写了一个音乐播放器,我上传了我拿来测试的一堆wav/ape/flac文件了,只上传代码就好。
- 我写了一个压缩工具,然后把我拿来测试的100多mb的文件上传上去了。
- 我上传了.idea/workspace.xml
- 我上传了测试用的.db文件
这都是不好的,而且为什么不好,我觉得用屁股想都想得到。
如果确实有这个需求怎么办呢?
举个例子,我要部署我的项目到某个CI(持续集成)上去,然而我的项目用到了JNI, 原本两部分(CMake和Gradle)是我手动分别编译。
所以我最后还是想办法让CI编译了JNI部分。。。
# 临时解决方案
我有一个替代解决方案。考虑到国内Git仓库,比如http://Coding.net和OSC的clone速度是相当之快的(我学校机房里的批网速(打开我的GitHub平均需要五秒)都能达到10mb/s的clone速度)。
这时我们就可以先在国内Git源开个仓库用来堆这种破玩意,然后使用Git的submodule来解决(submodule怎么用,自己股沟)。
# 关于IntelliJ的workspace.xml
比较了解IntelliJ系的IDE的同学应该注意到过,.idea目录下有很多各种各样的配置,其中有一个巨大的workspace.xml,它的大小飘忽不定,不过一般在20kb到70kb之间。
这其实是IntelliJ的一个对你编辑状态的缓存,比如你复制粘贴了什么东西, 你剪切了什么东西,你光标怎么移动了一下,你Git commit时写了什么commit message,IntelliJ都会把这些存进去。
而且编辑时,这破玩意是会大大改变的,有时你代码都没动,它变了,你commit的时候就会无意中把这些commit进去,造成commit log和整个仓库的污染。
看完上面这段,你还会上传workspace.xml吗?
# 尽可能有LICENSE和README
重要性我就不说了,LICENSE你懂得,这里推荐最邪恶的GPLv3.0,最不推荐MIT。协议怎么选,网上很多教程,我就不赘述了。
MIT一时爽,抄袭火葬场。
README尽可能使用人性化的语言写,尽可能用英文写,里面一般包含:
- 尽可能简洁的简介
- 特色,吸引别人
- 如果是软件类,放截图,可以考虑录制GIF
- Wiki的链接
- LICENSE
- 装逼用的badge,比如CI,比如Gitter,比如CodeCov,比如CodeClimate
- clone、build说明
- 维护指北等各种指北的链接
- release的binary的下载链接
- 如果是库性质的,放构建工具远端仓库地址(比如JitPack,或者你牛逼,你上Maven Central)
- Contributors