github使用说明

github使用说明

前言

什么是github,github能作什么?它是一个代码仓库,可是你能够把它当作一个远程硬盘(云盘、网盘)。和通常网盘的区别在于,它经过一个叫作git的软件进行同步,上传或下载操做,这个软件有很是强大的同步功能,甚至能够创建不一样的存储分支,让同步的文件有多个不一样的版本(这对代码开发来讲是颇有意义的)。可是,若是你不想要,不须要这个功能,也能够把它当作纯粹的免费网盘使用。github

如今就有不少人,经过github来存放我的笔记,日记,博客等文档资料,在不一样电脑上,只要同步一下,就能继续编辑,很是方便。这个甚至比通常的网盘要来得轻松,由于git对版本的控制更好,数据传输量更少。同步更加智能化,版本管理更加方便。安全

多说无益,本文介绍git的原理和使用方法,你亲自看一下是否对你有用。bash

1、git原理

1.1 分布式储存

git是一个分布式同步工具,简单来讲,它不要求你创建一个特定的服务器,你能够在任何地方创建本身的存储仓库,不一样的仓库没有地位的差别,都是平等的,这就去中心化了,因此叫分布式。服务器

这有什么好处,好比你不须要依赖某个网盘提供商,若是它不当心倒闭了,只要你把仓库搬到另外一个提供商就能够,甚至,你直接弄一台电脑放仓库也是能够的。这个理念我认为是很是有居安思危精神的。千万别过于相信网络,要给数据一个备份。网络

若是是传统的网盘,你须要用它的软件,下载文件到你的电脑,而后用另外一家的软件,上传到另外一个网盘备份,不用两天你就受不了。若是你不跟踪备份,可能网盘没通知你就把你的学习资料删除了,那你是怎么也要不回来的。相信经历过的朋友都知道。而只需用git,就能统一的管理各个仓库,轻松进行复杂的同步。编辑器

1.2 版本库 repository

也就是储存仓库,可是这个仓库不但能够放文件,还对文件的修改、删除等历史记录做跟踪,让你能够回溯到某个历史时期。这是git 最强大的功能。分布式

为了利用好版本管理功能,要求文件类型是文本类型,最好是UTF-8编码的。工具

git init #在当前目录下创建仓库,将新建一个.git文件夹来存储仓库数据

1.3 添加到仓库

在当前目录新建文件,而后加入仓库,git便可维护该文件的同步管理。性能

git add file.txt #将当file.txt文件加入git仓库

1.4 提交到仓库

添加并不会马上提交,也不会自动同步,这个交给用户本身判断恰当的提交时机。

git commit -m "这里写备注" #提交数据

每次提交,都要求你写一个备注,来记录你此次提交作了什么,这是个良好的习惯,由于这样你回溯历史的时候,才知道哪一个版本是你的目标版本。

1.4.1 显示文件变化

当前被跟踪的文件,和仓库版本有什么差别,能够用git status 列出哪些文件改动了的文件。

若是你还想知道具体修改了什么地方,能够用git diff xxx来查看xxx文件的改动状况。

1.5 变动到不一样的历史版本

这个是比较高级的功能,也许你用得上,也许用不上。首先,git reflog会显示你提交文档的版本:

#样例输出
f9adcba (HEAD -> master) HEAD@{0}: reset: moving to f9adc
9a75fd8 HEAD@{1}: reset: moving to HEAD~1
f9adcba (HEAD -> master) HEAD@{2}: commit: 测试回退功能
9a75fd8 HEAD@{3}: commit: 加了一点
781b0ad HEAD@{4}: commit: 有加了一点
55227c1 HEAD@{5}: commit: git文档修改
f2d5850 HEAD@{6}: commit (amend): ss2
ff6877d HEAD@{7}: commit (initial): ss

要跳到那个版本,使用git reset --hard f9ad,其中f9ad用具体的版本号替换。在以上样例的第一列,只须要给出几位,git就会寻找到对应版本。

当跳转到该版本,相应的文档数据会当即修改。

1.6 工做区和版本库的区别

当你在某个目录下面,建立仓库git init,该目录就是你的工做区,而具体的仓库的一些配置信息,是放在.git目录下的(可能被隐藏)。

工做区的做用就是你要同步的文件,应该放在这个目录下面,你只须要修改对应的文件,git负责其他的一切。你不须要刻意的去修改或者理会.git目录下面的内容,而应该使用git软件来输入命令。

1.7 暂存区 stage

当用git add xxx添加文件,实际上就是把文件放入暂存区。当git commit就会把暂存区的内容正式提交到某个分支(之后解释分支),并清空暂存区。

若是要撤销工做区的修改,能够用git checkout -- xxx;若是要撤销暂存区的修改,能够用git reset HEAD xxx

1.8 远程仓库

还记的我说过git是分布式的么?若是只是在本身电脑目录建立一个仓库,那就没什么意思了,如今学习怎么添加远端的仓库。

首先,申请github.com网站的帐户,并申请一个仓库的使用权,而后获得一个仓库的连接地址,而后:

git remote add 仓库别名 连接 #添加远端仓库
git push -u 仓库别名 master #将本地分支master提交到仓库。-u表示关联对应分支
git remote -v #显示远程仓库状况
git pull #从远程仓库拉取最新版本

1.9 分支

git容许创建不一样分支,所谓的分支,就是另外一条修改文件的路线。git记录每一条路线不一样的修改内容,当合并的时候会要求你对有冲突的修改内容进行选择。

git branch git #建立名为git的分支
git checkout git #切换到git分支
git branch #查看当前分支状况
git merge git #将git合并到当前分支
git branch -d git #删除git分支

建立分支后,所作任何修改,只影响当前分支,当切换分支,文件会瞬间回到另外一个分支的状态下。

虽然git分支这个功能看上去很强大,又很复杂,但实际上运做很是高效,它总能按照你指望的方式去运做。所以,推荐多使用,用来划分不一样的关注点也是挺好的。

一个合理的使用分支的方法是:

  1. 保持主分支不变,其余分支修改
  2. 而后将当前主分支合并到某个分支,解决冲突
  3. 最后用主分支合并该分支,更新主分区

这样就算再多人一块儿合做编辑,也能保证主分支是稳定可靠的。

不过,最好仍是不要随便跳转分支,由于跳转分支容易致使当前数据丢失,而后还会致使不少不少的误操做。(本博客就是这样丢失了一些历史信息,╮(╯▽╰)╭!)q

1.10 储藏

特别要注意,切换分支是一个高度危险的操做!由于它会毁掉当前工做区的状态。切换分支以前,应该先提交当前修改内容到仓库。可是,若是占时没法提交,能够借助储藏功能,把当前工做区保存在一个栈表里面。

git stash #保存并清空当前工做区修改状态
git stash pop #回弹当前工做区上一个状态。
git stash list #显示储藏栈表

1.11 标签

标签对应了commit 提交版本,由于这个版本号太复杂,所以用标签名来代替,更加容易识别。也做为一个发行版本号来使用。

git tag v0.9 #当前版本命名为标签v0.9
git tag #查看当前标签
git tag -d v0.9 #删除对应标签
git push origin v0.9 #提交标签到远程仓库

2、实践

2.1 流程总结

纵观理论知识,咱们能够得出一些结论:

  1. git是分布式,多仓库的,其中最直接的仓库就在当前工做目录下的.git文件,还能添加远程仓库。
  2. 工做流程是: 初始化并配置git本地仓库--》在工做区编辑文件--》提交到暂存区--》本地仓库--》远程仓库。
  3. 有回退的机制:远程仓库——pull或clone—》本地仓库--版本回溯--》当前版本工做区。
  4. 有储藏现场机制: 工做区、暂存区--stash--》储藏堆栈; 储藏堆栈--stash pop--》恢复当前工做区、暂存区。
  5. 有版本控制: 每次commit提交,就会产生一个版本记录,任什么时候候,只要有这个记录就能回退到该版本的状态。所以,commit以后的操做至少能够保证该版本的数据是安全的。
  6. 有分支能力: 分支对团队来讲是最重要的支持能力,恰当使用分支,能够多人同时编辑,而不会产生太多数据冲突。
  7. 有些操做是危险的:若是没有提交到仓库,就切换分支,当前工做内容就可能丢失,由于切换分支并不懂得自动保存当前工做区的状态。只要是会对当前工做区产生影响的操做,都有可能影响到数据安全(若是当前工做区没有提交,有修改状态),好比拉取,同步,切换分支,版本跳转,所以这些操做以前特别要注意查看当前工做区状态,先提交,或者储藏现场。

  8. 工做区和暂存区,都是不安全的,能够视为临时数据,他们之间造成一个小型的临时版本控制机制。工做区的内容能够放到暂存区,暂存区的内容也可能回退到工做区。

2.2 配置git

2.2.1 安装git

git 官网在http://git-scm.com,下面以deepin系统为例:

apt install git #安装git
git --version #版本号2.17

2.2.2 建立本地仓库

cd ~
mkdir gittest
cd gittest
git init    #在gittest目录下建立仓库,当前工做区便是gittest

git help #查看使用说明

2.2.3 克隆远程仓库

非新项目,能够从远程仓库克隆建立。

git clone https://github.com/Anduin2017/HSharp.git cloneProj #从已有的远程仓库克隆建立名为cloneProj的本地仓库。该远程连接能够在github任意一个公开项目中获取。

2.2.4 配置本地仓库信息

git仓库的配置信息,能够存在三个地方:

  1. system 影响全部用户,文件位于/etc/gitconfig
  2. global 影响当前用户,~/.gitconfig
  3. local 影响当前仓库,.git/config
#添加用户名和邮箱信息,必备,由于每一次提交仓库都要记录当前提交人的这些信息
git config --local user.name "myname" #添加user.name的记录为myname,其中--local为默认值,能够省略
git config user.email myname@163.com #添加user.email为myname@163.com

git config --list #列出当前已经配置的内容
git config user.name #列出某项的值,即myname

2.2.5 忽略某些文件 .gitignore

若是不想某些文件被加入仓库,能够用.gitignore文件指定,内容例如:

#忽略.cpp文件和~符号结尾的文件
*.cpp
*~

2.3 检查工做区和暂存区状态

应该常用这个命令确认文件状态。

注意: 若是你使用编辑器来编辑,要注意当前编辑状态和当前文件状态是不一样的。git是针对文件而不能知道你有没有正在编辑。若是你正在编辑,又经过git命令修改了文件,你的编辑器就会提示你原始文件已经被修改,你没法保存等异常状态。所以,你在使用git命令前,应该先把编辑状态下的文件,用编辑器保存一下。

git status #查询状态

2.4 正式进入工做

2.4.1 工做区和暂存区交互

  1. 编辑工做区上的文件,而后放到暂存区,继续编辑
  2. 若是编辑后不满意,用暂存区的内容恢复到工做区
  3. 若是满意,继续放进暂存区
#建立一个新文件,并在末尾输入内容“hello world!”
cat >>myfile.txt
hello world!
^C
#将该文件放入暂存区
git add myfile.txt
#继续编辑,并在末尾添加“hello.”
cat >>myfile.txt
hello.
^C
# 这时,就存在两个不一样的版本,一个是修改前放进暂存区的"hello word!"版本,一个是工做区内的“hello word!hello."版本。
git status #遇事不决,先用这个确认状态。能够发现同一个文件,有两种状态。一种是放在暂存区的,提示让你提交;另外一种是在工做区的,提示让你暂存变动。
git diff myfile.txt #确认一下文件内容的差异。显示工做区和暂存区两个同名文件的对比,若是你会看diff输出格式,就能发现差异是添加"hello."

#选择1,放弃当前修改,返回上次暂存内容
git checkout -- myfile.txt
#选择2,确认修改,放入暂存
git add myfile.txt
#git status的提示很丰富,提示上面有以上指令的使用格式

#删除文件
#若是某个文件被删除,这在git中也是一个特殊的修改
git rm xxx #删除xxx,并把删除状况告知暂存区

git rm --staged yyy #从暂存区删除yyy文件,但不影响工做区

2.4.2 暂存区和本地仓库交互

暂存区的内容并不会产生一个稳定的版本,最终要正式加入仓库,须要commit提交。

提交会要让你输入每次提交的备注,命令行下面的编辑器由git config core.editor选项控制。

git commit #向本地仓库提交暂存区的内容
git reset HEAD myfile.txt #取消暂存区内容。

git diff --staged #比较暂存区和仓库版本的不一样

git commit -a -m ”备注“ #把工做区的改动所有暂存起来,而后直接提交。-a参数将缩减提交的步骤。

git log -2 #观察最近两条提交记录
git log  --pretty="%h %an,%ar:%s" #按指定格式显示记录
git log --pretty=oneline --graph #显示按分支提交结构图

apt install gitk #安装图形化显示记录的工具

2.4.3 远程仓库

git remote -v #查看远程仓库列表
git remote add remotegit https://github.com/Anduin2017/HSharp.git #添加一个远程仓库,命名为remotegit

git fetch remotegit #下载远程仓库remotegit的对象和引用

git remote show remotegit #显示远程仓库关联信息
git remote rename remotegit newname #把远程仓库命名进行修改
git remote rm newname #删除远程仓库的关联

git clone https://github.com/Anduin2017/HSharp.git clonegit #克隆生成一个彻底同样的本地仓库,建立工做目录为clonegit
2.4.3.1 远程分支

远程仓库上面的分支,称为远程分支。

git remote -v #查看远端仓库状况
git remote add gitbak file:///home/user/git #加入本地另外一处仓库

git fetch gitbak #下载仓库信息
git branch -av #查看全部分支,包括远端仓库
git branch --set-upstream-to=gitbak/master #当前分支关联gitbak/master分支
git pull gitbak master --allow-unrelated-histories #合并不关联的历史数据

git push cloneProj HEAD:master #提交本地分支到远端仓库

#注意:应该尽可能保持本地分支名称和远程一致。

2.4.4 储藏

这个功能比较简单。

git stash #储藏当前工做区和暂存区变更
git stash pop #恢复

2.4.5 版本

每一次提交,都会产生一个版本,任什么时候候均可以跳转到该版本,可是版本标识是一个字符串哈希序列(sha-1 40字符哈希),不方便对外公布。

git tag #显示现有标签
git tag v1.0 #为当前版本命名标签
git show #显示HEAD关联提交对象信息
git show v1.0 #显示特定版本信息
git push origin v1.0 #向远程仓库提交标签

git commit -am"备注" #建立一个新提交"commit"对象,并改变HEAD指针指向新对象,若是头指针指向某个分支,先改变该分支指向新对象,再用HEAD指针指向该分支。简而言之,建立新版本

git reset 2341a --hard #HEAD指针调到散列为2341a开始的commit对象,即跳到该版本,--hard参数重置当先工做区和暂存区

2.4.6 分支

git中的分支,相似一个指针,一个提交(commit)相似链表中的一个节点。commit保存了父节点,和整个目录树结构,所以当分支(指针)指向某个commit,内容天然就是该节点的状态。理解这点很重要。也许你会担忧每次提交都产生一个当前文件目录的快照,会不会致使存储量变得很大,实质上是不须要担忧的。git以一种高效的方式进行相关记录,无论是性能仍是空间,都容许你瞬间执行提交,产生新的快照。

一开始有个master的分支,有个HEAD指针,它指向master,而master指向具体的commit节点,每次提交,master都会更新到新的节点上。若是你使用某种命令移动这个指向,天然就会变动到不一样的版本,这就是实现版本管理的基础。

git branch -va #显示分支状况,-a表示全部分支,包括远程分支,这个命令常用,由于它会显示分支的状况,相似git status显示文件状况。

git branch testbranch #基于当前分支建立一个新分支,实质不过是复制一个指针而已,效率很是高

#当你想切换到其余分支
#1. 保存正在编辑的文件
#2. 储藏现场git stash push -m "备注"
#2.2 或者提交git commit
#3. 切换分支
#为何?由于切换分支会清空现场,你将丢失掉工做区和暂存区的改动数据
git checkout testbranch #切换到testbranch,它和此前分支上一次提交版本如出一辙

git commit -m “备注” #每次提交,都会移动当前分支,指向最新的commit对象

#分支的成果最终要合并起来
git merge master #将master分支合并到当前分支
#合并过程可能会出现数据冲突,参考提示,手工选择后合并成功
git checkout master
git merge testbranch #更新master分支,通常这个分支做为默认的主分支
git branch -d testbranch #删除分支
#若是该分支新增的内容没有被合并到其余分支,就会提示让你先合并,善用git status,根据提示来操做便可。

git mergetool #调用图形界面来解决内容冲突

分支的功能并不算太复杂,可是如何设计适合本身须要的分支系统,就是一门值得思考的功课。建议master做为集成主分支,有若干分支负责实际编辑,编辑完毕合并到主分支。而后每一个细分支有里程碑(用标签标注),发布版本应该选择恰当的里程碑组合,进度稍微比主分支慢。

另外,若是须要修补,能够选择在里程碑新建一个补丁分支,它须要和主分支合并,也须要和发布分支合并。

  1. master分支,负责最新版本的持续集成
  2. publish分支,负责里程碑版本的特定集成
  3. featureX分支,负责各项具体内容,并在特定版本打下里程碑标签
  4. patch分支,负责修补漏洞,选择要修复的版本,并打上修订号。由于集成是一件比较费劲的事情,因此能够选择只对特定版本进行修复。

可能用到的技术包括:

  1. 建立分支: git branch 分支名 提交对象
  2. 跳转到该分支: git checkout 分支名
  3. 编辑,保存,提交
  4. 跳转到集成分支:git checkout xxx
  5. 集成:git merge x1
  6. 打标签:git tag v1.0.0.f1
  7. 分离头指针: git checkout --detach
  8. 跳转版本:git reset --hard commit对象

集成merge的基本逻辑是:

  1. 寻找共同祖先,计算出各自不一样点
  2. 让用户选择合并那些内容

所以应该采起的策略:每一个分支应该尽可能寻求共同祖先。那么共同祖先是怎么来的?实质之前某个merge节点(或者是分裂的初始点),不然分支怎么会有共同祖先?所以解决集成merge冲突复杂化的办法,实际是分红屡次集成,也就是持续集成的意义所在。

其余使用技巧

  1. 若是显示的中文文件名变成了\344\275\277\347\224\250相似的编码格式,能够用:
    git config --global core.quotepath false