@author
cuter44
@version 3.0.0-prerelease1+build20141030
@licenseCC 3.0 BY CN
@acknowledge Github & Github Pages, SCAU-SIDC, GitBook-zh_CN, MarkLodato/visual-git-guide, StackEdit, MarkdownPad2,exoticknight,
FTS
@source hosted on Github:scau-sidc/git-tutorial
通常来说这个时候应该说下 git是什么, 不过为了为了让这篇教程跟国产垃圾教材有所区别, 这里啥都不写有兴趣的话自己翻维基去. 现在, 只需要将 git 理解成 一个可以在多人环境下随时保存和合并源代码的工具 即可.
还有 Github, Github 就是依托 git 所建立的代码托管平台/社区, 如果非要做个对比的话它有点像 Google Code 和 SourceForge. 你可以在那里四处乱逛, 寻找自己想要的代码, 吐槽别人; 或者直接脑洞大开自己写个软件出来, 搞不好还会受到路过大神的加持...
然后呢, 我们的目标是, 写一个"萌萌哒"的"一个一两个钟能学会, 并且一两个钟之后还想回头看的教程". 在这个教程中我们会以一种实践的态度完成对git的学习, 各位一定要全力地去do哦 ^▽^
那当然就是在自机部署一个 git 了.
一个命令搞掂:
apt-get install git
, 或者等价的包管理器指令(yum, pacman 等)
这里是适合普通人的操作步骤:
作为一个有强烈责任心精神洁癖的软件攻城狮, 我会墙裂推荐从官方软件源获得软件:
然后按蓝星人的风俗一路 Next 下去, 除了这些点:
建议这么点, 理由是我有精神洁癖
建议这么点, 理由是这样对蓝星人友好
建议这么点, 理由是: 现在除了Microsoft Notepad以外已经没有哪个编辑器不能 handle \r\n 这个问题了, 这样可以避免引入污染.
(征稿)
这里先说明一点, git是一种对等的分布式仓库系统, i.e. 它不是非要一个服务器端才能互相交流. 它支持多种通信协议 包括 git://
, ssh://
, https://
, 甚至file:///
或者 svn://
. 换句话说, 只要能够读写对应的文件, 任何一台机器/存储设备都可以作为远程仓库, 甚至不必在上面安装 git .
辣么为啥要有 Github 呢? ...这问题谁也说不清楚. 其中一点或许是他实践了开源精神, 将代码作为交流话题, 并使他看得见摸得着, 看到代码推动世界的前进甚至亲手影响世界... 起码比刷微博来得有意义.
不对我要说的不是这个!! ≧□≦"
Github 除了有作为 git 的远程仓库, 提供代码可视化, 版本可视化之外, 还集成了问题追踪(Issue), 代码速记(Gist), Pull Request 等有效提升程序猿战斗力的工具. 反正...用过都说好...
废话了这么多总该去注册个 Github 帐号吧? 快去!! → https://github.com/join
然后找到组织→ https://github.com/scau-sidc , 加不进去对吧? 嗯这坑爹的至今都没有站内信功能, 所以只能私下找老邝或者副主任等老油条把你拉进去了.
英文界面不会撸? 可以去看看 Github官方的新手教程 (←还是英文的), 或者在本教程关于Github的章节会点到一些.
当然不可能立即就碉堡到这种程度↑咯 (´・ω・`)
对于 Windows 来说, 安装的 git 会附带一个 gui , 可以从开始菜单, 文件管理器的上下文菜单 或者 git gui
来启动它. 简单起见我们将从这里入手, 对应的命令行指令使用 行内引用
标示, 详细的参数请自行 git help
.
假如你不是在一个本地仓库中启动 Git GUI 的话他会弹出下面这个框框:
意思很明确, 你要新建(init
)呢? 还是克隆(clone
)呢? 还是打开呢?
这里咱们选克隆, 然后填入以下参数:
Source Location: https://github.com/scau-sidc/git-tutorial.git
Target Location: ${ws}\git-tutorial
完事之后会变成以下的样子(略微会有些不同, 这种细节不用在意 (・ω・`)っ彡/ ):
红黄绿的很好看对吧? 时间关系我就不画箭头什么的了...
左上角红色的部分 表示 工作目录(Working Copy), 也就是你以传统方式写代码时(i.e. 不使用 git ), 打开项目文件夹会看到的文件集合. 仅当你新建/修改/删除文件时, 他们会被列出在这里.
左下角绿色的部分 表示 Index(可以理解成缓存区, 目前没有公认的中文翻译), 是你在缓存改动准备用于提交的地方, 关于提交的概念将在后文详述.
WC 和 Index 中的文件图标是可以点击的(注意我说的是图标= =b). WC 中的文件被点后会进入 Index, 意思是你缓存( stage
)这个改动; Index 中的文件被点后会进入 WC, 意思是你放弃缓存这个文件的改动( reset --mixed
);
右上角黄色的部分 表示 差异(diff) 仅在你在点击 WC 或者 Index 中的文件名时(注意我说的是文件名= =b), 这个区域会列出这个文件改动了哪些行.
右下角是用来写 提交说明 这个也在后文讲.
嗯...总之选择 菜单栏 的 版本库(repository)
> 图示所有分支的历史(Visualize all barnches history)
, 然后会弹出一个新的窗口. 这货叫做 gitk , 大概长得像下面的样子:
界面上方由线和点组成的部分称为版本树
, (默认会)按时间顺序倒序排列. 现在看到的是一条直线, 但随着项目的多人合作这个它会逐渐产生分叉和合并. 这条线上的每一个小圆点表示一个 提交(commit)
, 各种小圆点/小标签都有不同的含义:
HEAD
, 也就是当前所处的提交点, 或者说(打游戏时)目前读出的存档点.History
, 这些点是不能修改的而你写的代码或者别的什么东西就是经过 红点→绿点→<蓝点 这个过程逐步进化成整个版本树的.
每个提交都有一个唯一的 SHA1 ID
, 这个值是通过提交内容等一堆因子算出来的, 理论上全球唯一.
分支(branch)
, 其中有些带有 嫩肉色前缀 的表示 远程分支(remote branch)
. 两者的区别是前者是由你建立和管理的, 可以随便操作, 后者是别人建立和管理的, 对远程分支的操作需要经过分支主人的同意. 跟踪分支(tracking branch)
, 意指他们是同一个分支在不同仓库的映像, 跟踪分支只有在相容(其中一个为另一个的子集)的前提下进行 push 操作(后面我们就解释这一条) tag
或者 里程碑(milestone)
, 通常会写着类似 1.0.0 的版本号, 这是给大牛发行用的, 小朋友没事不要玩这种危险的东西. (‾w‾ ) 那么这个版本树的存在意义是什么呢? 首先请将它想象成一个 有向无环图 (数据结构学得不好的同学请想象成 有向链表 ‾ω‾b ). 那么每一个 ● 提交 都是这个图的节点. 而每一个 分支/tag 可以想象成指向这个节点的指针/引用. 通过将指针随便乱指(大误), 你可以读出任意一个节点的完整代码然后加以修改. 这就跟打游戏时的S/L大法一样bug. (。・ω´・)っ
不过呢, 如果只是用版本树来开挂那也太low逼了(因为现在随便一个现代编辑器都有按时备份的功能). gitk或者说版本树本身还提供额外的信息, 比如说...看到提交记录里的邮件地址和时间了吗? 合作编程时被人捣乱? No problem! 除了能用 git 回滚之外你还能通过提交记录找到凶手然后冲过去揪住那人的衫领打他个半死...
呃...我们还是来做实验吧! ヾ(*ΦωΦ)ノ︵◇
首先我必需假定你们已经完成上述步骤了, 没完成的按前文 HINT 真的就只能干瞪眼.
实验内容依然是毫无新意的订外卖...假定我们现在要订外卖, 以前我们会找一个人负责拿着纸笔逐个收集订单. 但这样很累, 而且很容易数多或是数漏. 所以我们这次要用 git 来收集订单, 然后自动向外卖店下订.
分支(branch)
> 新建(create...)
> (名字里面随便输点什么, 我建议用你们的Github id, 这样可以避免重复, 其余默认即可). > 新建版本库(repository)
> Explorer Working Copy
> (打开了文件浏览器, 显示的是这个项目的根目录) > 打开 experiment 文件夹重新扫描(Rescan)
> (看到 WC 里有个很醒目的列表项?) > 将它缓存到 Index > 点 提交(commit)
> (弹框!! 要先写提交记录才能提交!!)提交描述(Commit Message)
> 写点什么, 比如 ${自己的名字}点了${餐点的名字}
> 再次点 提交(commit)
> (弹框!! 你是谁!?)编辑(edit)
> 选项(option)
> (弹一个大框出来) > 用户名(User Name)
Email Address
理论上可以随便填, 但现在请填写你在Github的id和email. > 保存
提交(commit)
> (终于交上去了...)有没有一种荡气回肠傲娇的感觉? 事实上诸如 代码要留名 提交有理由 都是良好的软件工程实践, git 以一种还算友好的方式督导你完成这些工作, 习惯了就好.
分步解释:
在上面的最后一步时你看到的分支树大概会像这个样子:
可能会有分叉, 可能会没有, 但总之以你名字命名的分支和gh-pages
分支已经不在同一个提交上了.
分支(branch)
> Checkout
> 本地分支(Local branch)
> gh-pages
检出(checkout)
指令, 他允许你读取任意branch/commit的内容, 大致相当于游戏的 Load. 本来在上一节新建分支的下一步是要进行一次checkout操作以切换分支的, 但新建时下面有个默认勾选的在创建后Checkout
, 所以 git 就自动切换分支了.合并(merge)
> 本地合并(Local Merge)
> 选择你自己的分支 > merge
在这个教程的情景中, 这个操作应该会顺利完成. 之后你的版本树看起来大概会像这样:
可能会出现两条线, 也可能不会, 这取决于具体情境.
到目前为止, 这些改动都是在你本地完成的, 表示服务器端的仓库的 remotes/origin 还停留在比较早的阶段. git 用于将本地更新发往远程仓库的操作名为 上传(push)
.
远端(remote)
> 上传(push)
> 选择 gh-pages
> 上传(push)
好了麻烦的时候来了. 之前提到过只有相容的跟踪分支可以互相推送, 然后在上面这种错误示范下...是肯定会出问题的. 除了第一个 push 的童鞋之外的 push 都会被阻止.
在上一节 上传(push) 中, 大部分同学会看到下面这个框框:
大体意思是有人先于你上传, 因为违反相容性所以不能接受你的上传, 后面还给出了说明, 让你先合并服务器端的更新再次提交.
commit
或者 stash
(将在进阶篇讲授) 保存你当前的 WC.然后在下列等价操作中任选其一:
远端(remote)
> 从...获取(fetch from)
> origin
, 合并(merge)
> 本地合并
> (自动选择了跟踪分支(Tracking Branch)
的 origin/gh-pages
) > 合并(merge)
(这个只能命令行做)
git pull origin gh-pages
然后会继续弹出红色的框:
大意是以下文件冲突, 请手动合并.
回到 Git GUI, 大概显示为以下样子:
左侧用特殊的图标显示出有冲突的文件, 点击它之后会显示出冲突详情, 重点是这里:
<<<<<<< HEAD
+
+5+0 醇香咖啡 ¥8
=======
+
+ kuangyj 焦糖拿铁 ¥10
>>>>>>> github/gh-pages
这是 git 用于标记冲突的语法, 七个左尖括号到七个等号之间是当前分支的内容, 七个等号到七个右尖括号之间是待合并分支的内容.
然后, 工具(Tools)
> edit this file
打开这个文件编辑. 因为我们正在"订外卖", 所以两条都要保留下来, 最后变成这样:
(空行)
5+0 醇香咖啡 ¥8
kuangyj 焦糖拿铁 ¥10
保存之后回到 Git GUI 重新扫描(Rescan)
, 修改内容已经反映到diff上了, 这时可以将 WC 的修改 stage
然后 commit
.
上传(Push)
以上几乎就是 一个凡人级别的程序猿/媛 日常使用git 所会碰到的全部问题了. git的命令还有很多, 某些指令例如 git log
, git status
, git branch
已经隐含在图形界面操作之中; git rm
, git mv
等因为很少用到所以略过; git stash
git rebase
等将在进阶教程(还没写出来)内讲述, 当然也可以独自阅读 reference 和 Pro Git 学习.
嗯, Github 的口号...
很难定义 Github 是什么, 他不是单纯的软件仓库, 不是社交网络, 不是协作工具, 虽然它样样都占点边.
围绕 git 的版本管理功能, 它扩展了很多好玩的功能, 使写代码变成一件相当有趣的事.(蓝星人就知道刷微博...唉)
好吧正题...
登录之后的第一个画面就是 Timeline, 不过通常都没啥好看的, 因为大部分信息都没有价值.
随便戳一个人的名字会去到他的个人主页(比如副主任的)左边是 biography, 自己在 settings 填写. 右侧分了好几块, 从上到下分别是:
哦对了, 访问别人的主页时右上角会有 按钮, 不解释.
当遇见喜欢的 repo, 比如这篇教程, 可以使用右上角有三个操作 . 它们大致对应于蓝星微博的 收藏 点赞 转发 操作, 更详细的含义请自行在Github的帮助系统搜索.
旁边的数字表示 Watch/Star/Fork 这个仓库的人数, 戳进去可以看具体是谁.
每个仓库都会附带一个轻量级的跟踪系统, 可以用于 你发现bug并且想报告给作者/向作者提问提建议/请求队友协助(比如要求新的API)/记录自己的待办事项, 用法和 teamibition 的任务版大同小异, 这里就不再展开说了.
如果作者愿意, 会开放并且撰写 Wiki. Wiki 通常用于弥补文档注释的不足, 用来放置用户文档或者系统文档. 不过就实际使用情况来说, 其实不是那么方便...
前面我们教了上传(push), 能使用 push 的前提条件是你对远程仓库有写权限. 举个栗子, 刚刚我们用于订外卖的仓库, 只所以强调要提前加入组织就是为了授予对仓库的写权限. 如果没有写权限而又想要往仓库推送内容的话, 就应该使用 Pull Request 操作.
galin
)上传到 Github.然后仓库的主人和这个 PR 的责任者会收到邮件. 然后他会检查你的 PR, 从而选择接受或者拒绝你的提交. 到这里 PR 就完成了, 界面看上去会变成题图的样子.
PR 的应用场景包括但不限于以下几种:
就是你正在看这篇教程所依赖的托管服务了, 它会将当前目录的 gh-pages
发布成静态网站. 并且支持一种名为 jekyll 的脚本语言. 嗯...然后, 你懂的. Where there is an API, there is a way.
比如本工作室的博客就是几只大牛利用业余时间受老邝所迫撸出来的.
经常会有一些小脚本你想抄起来以后用, 但它本身的规模又没大到需要专门建个仓库去安置它.
Gist就是用来满足这种需求的. 随手写, 随时用, 闲得慌了还能"手气不错"一下.
最开始工作室开荒的时候, 大家都不是很懂, 于是提交描述各种乱来...
整合
↑ 整合了啥没说, 还是要翻代码
有时还会看到些嘲讽向的:
没修改什么
没修改什么你交个毛线!! (#°д°)
于是乎, 久病成良医, 慢慢地琢磨出一套标准:
登录/激活功能追加完成
+ Web API, 详情请参见javadoc
+ /authorize/register
! 现在还不能发邮件, 但是会通过json返回激活之必要参数
+ /authorize/activate
* /authorize/login
+ 追加了样例
* /authorize/logout
+ 追加了样例
* /authorize/getRsaKey
+ 追加Criteria机能, 详请参考wiki:Criteria
+ 追加了用于RSA加密的实用工具, 详请参考wiki:服务器部署指南
提交的标题不说了, 很容易就能总结出来.
然后下面以树状的方式列出更新的内容. 前导的符号表示更新的类型, +
表示新增, *
表示修改, -
表示删除, 这些和 git diff
的表示法相容. 需要额外注意的内容则用 !
表示.
有一些约定俗成的命名规则:
git clone
拷贝回来的, 那么源仓库会被命名为 origin, 也就是 本源 的意思, 在命令行执行 git fetch
git push
且没有指定远程仓库的名字时, 会默认使用这个.master
, 用于存放用于发布的稳定版本. 且作为软件基线(发布基线).develop
, 用于收集和积淀开发过程中的功能性更新, 且作为软件基线(开发基线). 通常这两个基线的每一个提交都要求是完备的, i.e. 能够正确编译且通过全部测试用例(不过工作室一直以来都没测试管理, 所以说了也白说...).后记
妈蛋这又不是轻小说写毛线后记(╯‵д′)╯︵┻━┻
进阶版再说吧...