Github
我们使用github来托管项目代码
仓库(Repository):用来存放项目代码,每个项目对应一个仓库,多个项目则有多个仓库
复制克隆项目(Fork):将别人的仓库完全复制到你的账号下(生成一个相同的仓库,会说明来自哪个用户)
发起请求(Pull Request):这个事基于fork的,张三复制了李四的test仓库,那么张三可以在复制过来的仓库中添加东西,但是两者的仓库是独立存在的,如果张三想让李四知道他改进后的仓库,那么张三就可以点击Pull Request,就会发起请求,李四就可以收到该请求,李四可以查看他的改进,如果觉得不错,李四就可以接受它的请求,将其合并到它的分支,两者的仓库就一样了
关注(Watch):关注了某个项目只有以后项目有更新就会提醒你
事务卡片(Issue):发现代码bug,需要讨论时使用;eg:我开源了一个项目,别人发现我的项目中有bug或者那些地方做的不够好,他就可以给我提一个Issue(相当于问题),我看到这个issue就可以去修复,修复完成就可以关掉
Git
Git是目前世界上最先进的分布式版本控制系统
Git的优势
- 可以不需要联网
- Git有强大的分支管理
集中式与分布式比较
集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。两者之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。(ps:在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。)
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。
安装Git
安装完成后,还需要最后一步设置,在命令行输入
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。
注意git config
命令的--global
参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
创建版本库
版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录
$ mkdir learngit
$ cd learngit
第二步,通过git init
命令把这个目录变成Git可以管理的仓库:
git init
瞬间Git就把仓库建好了,而且告诉你是一个空的仓库,可以发现当前目录下多了一个.git
的目录,这个目录是Git来跟踪管理版本库的,没事不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
文件添加到版本库
ps:所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。
我们编写一个test.txt文件,一定要放到learngit
目录下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。(实际上目前在工作区存放的)
第二步,将test.txt文件从工作区放到暂存区
git add readme.txt //每次git add只能连一个文件,可反复多次使用,添加多个文件
第三步,用命令git commit
告诉Git,把文件提交到本地仓库:
git commit -m "wrote a test file" //将暂存区的所有文件一次提交到本地仓库
-m
后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
可以运行git status
命令查看结果状态
git status
//红色的一般是在工作区的,绿色的是放入暂存区的
不论执行了增删改哪一种操作,版本都会记录下来,需要重新提交到本地仓库
eg:我们起初给test.txt中写了hello world,之后我们修改成hello world Bob再使用git status查看
上面的命令输出告诉我们,test.txt
被修改过了,但还没有准备提交的修改,它又存放在工作区了,我们可以根据上边的流程重新提交一次即可。git status
命令可以让我们时刻掌握仓库当前的状态。
如果git status
告诉你有文件被修改过,我们可以用git diff查看具体修改了什么内容
ps:当暂存区和工作区不同时,git diff对比的是工作区和暂存区的不同;当暂存区和工作区一致时,git diff无输出;当暂存区“干净”,git diff对比的是工作区和仓库的不同,如果当前工作区也是“干净”的,即工作区无修改,和版本库中最新版本一致,那么git diff也是没有输出的)
git diff test.txt //
git diff
顾名思义就是查看difference
当前工作区已经提交且未改变,无输出
如果我们要明确比较工作区和版本库的不同我们给git diff还要加对应的参数
git diff HEAD -- filename
这种情况只有当前工作区与版本库一致时,才会无输出
版本回退
我们不断的对文件修改,每次当我们觉得文件修改到一定程度的时候,我们就可以将其存放的本地仓库,就相当于“保存了一个快照”,这个快照在Git中被称为commit
。一旦我们把文件改乱了,或者误删了文件,还可以从最近的一个commit
恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
上文我提交了两个test的版本
版本1:wrote a test file
hello world
版本2: add Bob
hello world Bob
在实际工作中,我们不可能记得一个几千行的文件每次都改了什么内容。版本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,我们用git log
命令查看:
git log //查看每个版本的情况以及我们当时提交的说明(git commit -m后面的说明)
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数:
git log --pretty=oneline
你看到的一大串类似1a0d79c...
的是commit id
(版本号)
每提交一个新版本,实际上Git就会把它们自动串成一条时间线。
我们现在处于add Bob的版本,我们怎么将其回退到first这个版本呢,使用git reset
命令
ps:使用git reset之前我们要明确在Git中,用HEAD
表示当前版本(已经提交到本地仓库的这些版本,在暂存区和工作区的不算),上一个版本就是HEAD^
,上上一个版本就是HEAD^^,
当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
git reset --hard HEAD^ //
--hard
参数有啥意义?这个后面再讲,现在你先放心使用。
ps:可以看出如果你在版本回退前又修改了test文件,但是存放在工作区或者暂存区,并未提交到本地仓库,那么版本回退后这些修改全部被覆盖掉
我们再用git log查看一下
我们发现只有这一个版本了,那么我们还有没有办法再回到我们回退之前的版本(或者它之后的任何版本),办法其实还是有的,只要知道之前版本的commit id就能退回到对应的版本(只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个add Bob的commit id
是1a0d79c...
,于是就可以指定回到未来的某个版本):
git reset --hard
1a0d7
ps:版本号没必要写全,前几位就可以了,Git会自动去找。
那如果我们并不知道之后的那个commit id我们怎么回到那个版本呢?(比如:你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本,不知道新版本的commit id)
可以使用git reflog记录每一次命令
git reflog
这样就可以获取到我们之后版本的commit id了
Git的版本回退速度非常快,因为Git内部有个指向当前版本的HEAD
指针,当回退版本的时候,Git仅仅是把HEAD从指向first
-
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。 -
穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 -
要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
详解工作区和暂存区
1:工作区就是你在电脑里能看到的目录,比如我的learngit
文件夹就是一个工作区
2:版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支(本地仓库)
当我们git add一次后,版本库如下图:
当用git commit提交后,且没有对工作区做任何修改,那么工作区就是“干净”的,版本库变成了这样,暂存区就没有任何内容了
管理修改
Git比其他版本控制系统设计得优秀的原因是因为Git跟踪并管理的是修改,而非文件。(增删改都是修改)
我们进行一个操作
第一次修改 -> git add
-> 第二次修改 -> git commit
这个第二次的修改会被提交吗?
根据上文的分析,我们git commit只会提交暂存区的,第二次修改的还未放入暂存区,还在工作区,所以按照分析应该只会提交第一次的修改,不会提交第二次的修改,验证一下。
最后一幅图可以看出我们提交了暂存区的版本,并未提交我们第二次的修改,与我们猜想的一致。所以记住git commit
只负责把暂存区的修改提交;可以使用git diff HEAD -- test.txt查看当前工作区与版本库最新版本的不同
撤销修改
撤销有两种情况
1:修改了还未放入暂存区,那么撤销修改后工作区就回到和版本库一模一样的状态
2:已经添加到暂存区后,又作了修改,现在,撤销修改后,工作区就回到添加到暂存区后的状态。
总之,就是让这个工作区文件回到最近一次git commit
或git add
时的状态
使用以下命令即可撤销修改,这个--
很重要,没有--
,就变成了“切换到另一个分支”的命令
git checkout -- test.txt
对于已经放入暂存区的我们怎么撤销呢?Git告诉我们用命令git reset HEAD <file>
可以把暂存区的修改撤销掉重新放回工作区
git reset HEAD test.txt
git reset
命令既可以回退版本,也可以把暂存区的修改回退到工作区(清空暂存区)。当我们用HEAD
时,表示最新的版本 。那么暂存区现在干净了,我们再使用git checkout -- test.txt即可丢弃工作区的修改。对于已经提交到本地仓库的就可以使用版本回退解决。
删除文件
删除也是修改的一种
当我们提交到版本库中一个版本后,我们删除了工作区的文件(rm删除),这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status
命令会立刻告诉你哪些文件被删除了:
假如我们的确要删除版本库中的文件,那就用git rm删除,并且将此次删除(修改)提交。
ps:使用git rm <file>和git add<file>效果是一样的。
git rm test.txt
假如我们工作区的是删除错了呢?因为我们删除也算是修改,所以就可以用工作区的撤销方式即可把误删的文件恢复到最新版本,仍旧是使用git checkout -- test.txt。但是注意一点,从来没有被添加到版本库就被删除的文件,是无法恢复的!即你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。