我写东西废话向来很多,这次不扯东扯西,争取20分钟之内进入正题。
Just kidding.
今天来介绍一下Git和Github。本文必将有不少奇怪和模糊(但足够初学者大致理解)的比喻以及极度口语化的文字,请慎重阅读。
Git & Github:
Git是一个版本控制软件。你在写代码的时候想要测试一个新功能,却并不想在已经稳定的版本上做实验(万一删删改改出了问题,想要恢复到之上个版本怎么办?),这时就需要版本控制,将当前的代码保护起来,另起炉灶;如果测试结果不满意,把不稳定的炉灶全部推倒,还能滚回之前好用的版本。
你用git控制的文件和这些文件的修改记录都是保存在本地的,为了多人协作/不把鸡蛋放在一个篮子里,某位古神(应该是Linus)创建了网站github。你可以用git在本地控制每个文件,记录每一次增删,然后把这些文件连同所有的修改记录推送到github上。
好的,跟我重复重点:
Git是本地的版本控制软件,可以跟踪文件的所有修改记录;
Github是修改记录和文件的在线保存地。
Github和多人协作:
张三等人一起用github开发一个软件,他们认为该软件主要有3个功能。
张三写好了功能1,测试稳定了;
李四在张三的基础上写好了功能2,测试稳定了;
王五觉得自己能写出更高效的功能2,就从张三的版本上另起炉灶,写了功能2',测试稳定了,三人讨论后决定采用2'版本,于是王五把自己的功能2'推送回了主程序,成为主程序的一部分;
张三和李四也一起写好了功能3,和王五同步完成工作;
bad bad example, just for reference.
最简单的git指令以及工作流程
定义
- zelda.txt是我需要版本控制的文件
- 我的项目名称叫mario
往下看之前确认你知道cd是什么意思。
另外强烈建议边看教程边动手做一遍。
1. 创建repository
为了版本控制任何文件,你首先要创建一个修改记录储藏中心,又叫做repository。
这个中心可以
- 从无到有生成(如果你在写一个全新的项目)
或者
- 从别人已有的储藏中心拷贝一份过来(如果你想接着别人的进度继续写)
对于1,你又有两种方法
a. cd到任意一个文件夹里,比如说~/Desktop/,用git init mario
来创建新的repository。这步之后你会在桌面上看到一个叫做mario的文件夹,点进去,把你的zelda.txt文件拷贝进去,之后就可以在mario这个repository之中开始版本控制啦。
b. 到github官网,点击一个绿色的按键(new repository),在新页面中给新repository起名叫mario,确定;然后他会在新页面中有一个地方让你复制链接(非常类似于https://github.com/chenxi-ge/mario.git
的一个链接);复制,cd到任意一个文件夹里,用git clone 刚才的链接
来把在线创建的repository联动到本地。
对于2,直接用git clone 别人的repository
就可以了。
好的,重复重点:
本地生成,git init folder_name
在线拷贝下来(不管是自己的还是别人的),git clone repo_url
插一句,Github是可以免费使用的。但免费使用的代价是,你也要保持所有的代码开源:任何人都可以查看你的代码,你也可以下载别人的代码,程序员们在互相学习中成长。开源是我非常钦佩和坚持的精神——不然写啥教程啊。
当然对于企业用户,每人每月7刀,可以创建私人repository用于公司项目,也挺好。
2. 管理文件
那么现在你有一个文件夹,叫mario,在本地;这个文件夹里有一个幽灵(.git)在监视着所有你让他监视的文件;还有一个你刚刚拷贝进去的zelda.txt。
现在这个zelda.txt是没有被监视的,幽灵也是有拖延症的,不会主动帮你干活的。
何以见得?用git status
查看当前管理进度。
git status
之后,你会看到zelda.py是在'Untracked Files'里面的,并且是红色的。于是我们使用git add zelda.txt
,告诉git开始监视zelda.txt的每一行增删(把这个文件add到监视列表里)。
增加之后再用git status
,会发现文件进入了'Changes to be committed'的列表里,并且名字前面显示'new file'。
那么我们来谈谈commit。什么叫commit呢?就是告诉git:在这儿存个档,记录一下当前文件和上一次commit的差异。这样追根溯源,之后就能恢复每个文件每个版本。
我习惯在add新文件之后进行一次commit。
git commit -a -m 备注内容
是commit的常用方法,这里-a 是要求“记录所有修改”,-m是提示后面紧跟着备注,而备注内容当然是人类能看懂的语言,不好好写吊起来打。
在commit之后,再再再git status
一下,发现所有的改动都已提交,无比清爽。
我猜这儿正经教程要开始讲什么叫stage,不然没法讲清
git commit -a
的-a
是什么。然而这种会搞乱新手的东西我也不能说完全能讲清,想了解的请自己去看官方文档。
这时我们手贱去改动一下zelda.txt的内容,然后git status
,会发现zelda.txt又变成了modified,并且是红色状态。很好,如果改动是你需要的,就commit;如果是commit之后发现不需要的(比如十几个commit后发现性能反而降低了),之后会讲如何回滚。
在commit之前,如果你想了解一下你的改动,用git diff
可以做到这一点。但绿色代表什么,加减号又代表什么,请查阅文档。
好的重复重点,
git add
跟踪文件
git status
查看当前跟踪进度
git commit
存档一下
3. 版本控制
最后光速讲一下log
, reset
和push
然后我就去睡觉。
首先,之前吹了半天版本控制,到底怎么才能回滚到之前的一个稳定可用版本呢?
首先是查看记录,用git log
可以查看到历史上所有的commit编号、commit的提交者和提交时间,还有当时的备注。假设你在有一个稳定可用版本时commit了一下,这条commit记录会留在log上。
然后是回滚版本,用git reset --hard log编号
。所谓log编号是用git log
查看时在每个commit最顶端的一串30个字母左右的乱码,在reset的时候只要输入前六位就可以回滚版本。执行完git reset
指令后,再次查看zelda.txt就会发现回到了那条特定的commit时的样子。
新手不必在意git reset log编号
和有--hard
的版本不一样,前者是回滚所有commit但不修改本地文件,后者是回滚所有commit并且修改本地文件。
最后就是git push
。之前所有的版本控制都是在本地的,如果想把本地的所有修改都推送到github上存储怎么办呢?git push origin master
,认准这一条。其中git push
很显然是推送,origin master
是说推送目标是主分支,对于没有开其他分支的你——你要能读到这儿,肯定是还没用到啦——也是唯一选择。
git push
的频率当然可以自己定,我习惯是每写好一个功能/最多15分钟commit
一下,而每写完一个项目(比如说一次作业),如果是连续的几个小时写完就最后push一次,否则今天的份额写完了就push。
PS,如果忘记在写完项目之后做git push
,这个project就拿零分了。
重点?
git log
查看所有commit
git reset
回滚版本
git push
推送修改到Github——在线的数据中心
4. 坑
说了是坑嘛,肯定不会填的。
这个教程最主要是面向新手,展示一个文件跟踪的流程,用到的都是最基本的几个指令:git init
, git clone
, git add
, git commit
, git log
, git push
, git reset
,让人能跟踪一个文件,不断记录修改,可以方便回滚,也可以提交到github,这些足够啦。
度过了最开始的confusion,任何一个官方文档不比我说的严谨标准一万倍么。
所以这一块主要是说一下还有哪些没说到的,留给读者自行探索吧。
-
git merge
,git fetch
,git branch
分支控制 -
git stash
暂存修改 -
git pull
下载别人的修改