GitHub简明教程1中给出了从github上clone仓库到本地,形成本地仓库,并通过git add、git commit、git push命令来提交到github上仓库的基本操作,接下来从以下4个方面来讲述github的使用问题:
注:github简明教程是指git和github的使用教程
- git仓库的结构
- branch和master分支的应用流程
- 版本的回退、穿梭
- 本地仓库push到github上
- clone他人的仓库使用方法
1. git仓库的结构
mkdir tutorial
cd tutorial
git init
初始化后,生成了名为tutorial的仓库,里面有一个.git的隐藏文件夹,该文件夹中存储着管理当前目录内容所需要的仓库数据
注:tutorial文件中的内容称为该仓库的工作树,文件的编辑等工作在工作树种进行,并通过git命令操作提交到git的仓库的版本管理对象中,
通过git status查看仓库的状态
git status
结果显示我们在master分支下。
接下来是讲述tutorial仓库是如何运行工作的:
我们在仓库中创建了文件(代码文件,文本文件),但是这些文件不会被记入git仓库的版本管理对象中,要想使文件成为git仓库的管理对象,就需要用git add命令加入暂存区。
git add README.txt
要想从历史版本中恢复,还需要通过git commit命令来讲暂存区的文件保存到仓库的历史记录中。
借鉴http://josh-persistence.iteye.com/blog/2215214博客中的图片来说明仓库的基本架构和操作流程:
仓库中包含了工作区和版本库,版本库则包含index(暂存区)和master分支
注:git内部有一个HEAD指针,它指向当前分支版本对象上,当回退到历史版本时,只要HEAD指针的指向从当前版本转向历史 版本即可,实现快速回退。
git add 作用:
将工作区对文件的时间戳、长度、id等信息存储到index的树目录中,并将本地内容的信息做快照保存到版本库对象objects中(在.git/objects目录下)
git commit 作用:
将index区中的文件版本存到master分区目录树中,并将index版本库中的对象也存到master分区中的对象中
git diff 作用:
用来查看工作区文件和index区对应文件的变动,是和index中当前版本库对象做对比,git diff HEAD,比较工作区和分支版本文件的差别,这因为HEAD指针指向分支上的当前版本对象。
注:add之前,index和master中当前版本对象时一样的,都是旧的,add之后,commit之前,index当前版本对象更新,master依然是旧的,commit之后,master更新,和index中一样。
git status 作用:
查看当前工作区中文件状态的变化。实际上是调用index中版本库对象中的信息(文件时间戳、长度等)做对比,发现时间戳不同,说明文件发生了改变。
2. branch和master分支的应用流程
为什么要使用branch?
当在本地开发程序,一般在master分支上,但是当实习好多小功能时,每次都提交一个,会造成版本信息混乱不清晰,可以用分支,在分支上完成后,通过merge,这些小功能commit一次master就可以了。
(2)github上协同开发时,master是最稳定的版本,每个小组各自一个分支进行开发,分支完成后再pullRequest进行请求合并,比如在1.4版本发布,但是发现有bug,怎么办?开发新功能的小组继续开发V2.0,V2.1版本,在V1.4版本上branch一个分支,进行debug修正,V1.6版本是debug版本,再和V2.1进行合并,这样各自任务都没有延搁,开发效率更高。
如何建立branch?
git branch #查看有哪些分支
git branch AA #建立分支AA
git checkout AA #切换到AA分支
如何和mater分支merge?
git checkout master
git merge AA
为了能在历史记录中记录本次分支合并,可以加上参数 --no-off
git merge --no-of AA
3. 版本的回退、穿梭
显示从最近到过去的提交日志,但是如果日志较多,则只会显示前3次
$ git log
commit 9842ee50722e72e1ccd1ffc6e168711404adc821 (HEAD -> master, origin/master, origin/HEAD)
Author: chuankang wu <1650912111@qq.com>
Date: Thu May 10 21:43:24 2018 +0800
commit the package day7
commit abc3017368721d30ef318adb865b53cf02beda5b
Author: chuankang wu <1650912111@qq.com>
Date: Thu May 10 20:57:45 2018 +0800
add checkCode.py
commit 0af69423d5aaef67bd5f8c53295711969c737eca
Author: wuchuankang <1650912111@qq.com>
Date: Wed May 9 15:01:21 2018 +0000
Initial commit
git log --pretty=oneline 作用:
git log显示的信息太庞杂,加上参数后,会简化输出:版本号+提交信息
$ git log --pretty=oneline
9842ee50722e72e1ccd1ffc6e168711404adc821 (HEAD -> master, origin/master, origin/HEAD) commit the package day7
abc3017368721d30ef318adb865b53cf02beda5b add checkCode.py
0af69423d5aaef67bd5f8c53295711969c737eca Initial commit
前面的一大串0af694...7eca,这个可以看成是commit id(版本号),它是用SHA 1计算出的一个哈希值,它确保了版本号的唯一性,因为有时候多人在同一个版本里工作,如果大家都用1,2,3...作为版本号,则会造成版本号的冲突。
git reset -- 参数 哈希值(不用输全,前4-5位即可,命令会自动匹配到该哈希值) 作用:
该命令的本身是将HEAD指针从当前分支的版本指向另外一个commit版本
有参数--soft,--hard,--mixed
--hard(常用):
hard参数具有强制作用,它将重置所有的东西,即工作区、index区、当前分支区都会被重置,所以使用git reset --hard之前,如果没有add或add、commit,因为工作区、index区、当前分支区都被重置,则当前工作区的版本数据就会被破坏、丢失,所以使用该命令参数之前,一定要add、commit
--soft:只是将HEAD重新指向另外一个commit,其他不变
--mixed:是reset的默认参数,它重置了HEAD指向,并且重置了index以便和HEAD匹配,其他不变
$ git reset --hard abc3
HEAD is now at abc3017 add checkCode.py
退回到某一历史版本后,又想穿梭到该版本之后的某一版本怎么办?现在用git log,发现该版本之前的log已经没有(因为工作区、index区、当前分支区都被重置),那么之后版本的哈希值找不到,也就没法回去了。
$ git log --pretty=oneline
abc3017368721d30ef318adb865b53cf02beda5b (HEAD -> master) add checkCode.py
0af69423d5aaef67bd5f8c53295711969c737eca Initial commit
现在就是git reflog 的作用了:
$ git reflog
abc3017 (HEAD -> master) HEAD@{0}: reset: moving to abc3
9842ee5 (origin/master, origin/HEAD) HEAD@{1}: commit: commit the package day7
abc3017 (HEAD -> master) HEAD@{2}: commit: add checkCode.py
0af6942 HEAD@{3}: clone: from git@github.com:wuchuankang/python_socket
它将历史版本的日志都显示出来了,各个版本的哈希值都有了,就可以穿梭了
4. 本地仓库push到github上
git是分散型管理系统,本地仓库可以连接网络端的远程仓库(github上的),之前我们在本地建立了一个本地仓库tutorial,现在在github上新建一个仓库,为了防止连接时,和github上的其他仓库混淆,github上的仓库名取和仓库名相同。
注意:不要勾选initialize this repository with a README,因为一旦勾选,github上会自动生成README,便失去了和本地仓库的整合性。
添加远程仓库:
$git remote add origin git@github.com:wuchuankang/tutorial
push到 远程仓库上:
$git push -u origin master
origin是主体,代指remote repo,可以与clone远程仓库到本地的clone相对应
如果出现:origin does not to be a git repository,一般是上述命令写错,可以通过一些命令来删除,重新添加
$git remote rm origin
-u参数是将remote repo设置为local repo的upstream repo,这样通过pull命令从remote repo中获取内容就不用添加参数。
5. clone他人的仓库使用方法
$ git clone git@github.com:wuchuankang/data.git
Cloning into 'data'...
Enter passphrase for key '/c/Users/wck/.ssh/id_rsa':
remote: Counting objects: 3981, done.
remote: Compressing objects: 100% (5/5), done.
Receiving objects: 31% (1251/3981), 10.37 MiB | 50.00 KiB/s
这里讲述一下git clone和git pull的区别,参照https://blog.csdn.net/zhou_xiaomiao/article/details/53185712中的论述:
从字面意思也可以理解,都是往下拉代码,git clone是克隆,git pull 是拉。
但是,也有区别:
从远程服务器克隆一个一模一样的版本库到本地,复制的是整个版本库,叫做clone.(clone是将一个库复制到你的本地,是一个本地从无到有的过程)
从远程服务器获取到一个branch分支的更新到本地,并更新本地库,叫做pull.(pull是指同步一个在你本地有版本的库内容更新的部分到你的本地库)
git pull相当于是从远程获取最新版本并merge(合并)到本地 git pull = git fetch + git merge,git fetch更安全一些
git clone是远程操作的第一步,通常是从远程主机克隆一个版本库,eg:$ git clone ## 该命令会在本地主机生成一个目录,与远程主机的版本库同名,如果要是制定不同的目录名,可以将目录名作为git clone 命令的第二个参数。eg:$ git clone #版本库网址# #本地目录名# git clone支持多种协议,除了http(s),还有ssh,git,本地协议。
git pull 作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。它的完整格式稍稍有点复杂。eg:$ git pull ##远程主机(origin) #远程分之(next)#:#本地分之(master)#
注:他人的github仓库中也有download这也选项,为什么不用这个?这是因为直接download,在本地无法实现版本管理,如果单纯使用一下,参照一下,那么download也没有问题