分布式版本控制系统Git与项目托管平台Github相关概念操作方法开发流程与常用命令

Posted 刻刻帝丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式版本控制系统Git与项目托管平台Github相关概念操作方法开发流程与常用命令相关的知识,希望对你有一定的参考价值。

tip:有问题或者需要大厂内推的+我脉脉哦:丛培森 ٩( ‘ω’ )و

【本文源址:http://blog.csdn.net/q1056843325/article/details/54667602 转载请添加该地址】

#简介

GitHub 是一个面向开源及私有软件项目的托管平台
因为它只支持 Git 作为唯一版本库格式进行托管,所以命名GitHub
(hub 英文 枢纽、中心 的意思)


Git是一个开源的分布式版本控制系统
可以有效、高速的处理从很小到非常大的项目版本管理
它也是目前世界上最先进的分布式版本控制系统(Git自称)
(git 英文 饭桶、废物 的意思 (⊙_⊙)?)

什么是版本控制系统呢?
简单地说,它有以下功能

  • 备份(记录多个版本文件的功能)
  • 记录操作时间线(查看历史操作,进行版本回滚、前进的功能)
  • 多端共享代码(代替各种云盘的功能)
  • ‘自动’合并(解决多人开发冲突问题)

这样的一个系统的优点是不言而喻的
如果没有版本控制系统,我们的工作一定会变得非常困难


介绍一下Git和SVN的区别

集中式版本控制系统SVN
版本库集中放在中央服务器,工作时首先要从中央服务器得到最新版本,工作完成后,再推送到中央服务器。集中式版本控制系统必须联网才能工作,如果没网就GG了

分布式版本控制系统Git
Git是没有中心服务器的,每个人机器上都是一个完整的库,平时开发代码时的中央服务器其实和我们自己机器上的库内容基本是完全一样的,工作时完全不需要互联网


Git的去中心化
意味着没有权威、没有主力,人人平等
这对社区的影响是巨大的,Github上的fork功能,允许你fork任何一个你喜欢的项目,然后按自己的喜好修改成自己的项目,或是发起pull request请原作者merge你的功能到他们项目里去(这同样也得益于Git另一项与SVN很大不同的功能——分支策略),而且大多数开源项目都会鼓励你去fork它们。这里面没有权威,没有主从,所有人只要有兴趣都可以在其他人的基础上去构建更强大或是更有领域针对性的项目

#安装
安装包去Git官网下载就好了
安装完毕后,在桌面或任意文件夹右键就会发现多了两个选项

证明我们安装成功了
在开始菜单中找到Git Bash点开
(Git GUI是一个可视化工具,我们先不用管它)

首先我们需要配置用户名和邮箱作为标识
输入命令:
git config --global user.name <username>
git config --global user.email <useremail>

什么信息也没反馈给我们就代表成功了(这是Git的设计理念,下面介绍的命令也是一样)
git config --global 意味着全局配置
当然我们可以针对某个库设置特定的用户名和邮箱

#管理
首先我在桌面创建了一个文件夹demo作为我们的项目文件夹
内部创建了一个foo.txt的文件
在文件夹内部Git Bash(这样比较方便,cd定位盘符太麻烦,pwd命令查看当前目录)

输入命令 git init(创建本地仓库)

现在我们的目录就变成了Git可以管理的仓库
我们把文件夹选项改成显示隐藏文件就会发现

Git为我们在目录中创建了一个.git的文件

它就是跟踪管理版本的奥秘所在
不要胡乱删改它里面的文件就可以了

#基本概念

为了更好的理解我们接下来匪夷所思的操作
我们有必要了解一下Git的基本概念

工作区Working Directory
我们电脑上可以显示的目录就是工作目录
比如说我们的例子中,工作区只有一个foo.txt文件

版本库Repository
隐藏文件.git就是版本库,它也叫做仓库
仓库里所有文件都通过Git来实现版本管理,Git都能跟踪并记录在该目录中发生的所有更新
版本库中最重要的就是stage/index缓存区和Git为我们创建的主分支master
还有一个指向master的指针Head

缓存区Stage
缓存区就是版本库内的一个区域,用来缓存我们的修改


此外还要注意,所有版本控制系统,只能够跟踪文本的改动,例如txt、html、css、js等等
但是图片、音频等二进制文件,它只能够知道文件大小变动了多少
至于变动了什么,它无法知道

#工作流程

我们Git大体的工作流程就是这样滴

  1. git add 把文件从工作区添加到版本库中的缓存区
  2. git commit 提交代码,把缓存区所有内容提交到当前分支

每次提交后系统都会记录一下这次操作的相关信息
形成一张张“快照”
通过它们我们就可以实现“回溯”
内部其实就是指针与链表

#基本操作
了解了相关概念以及流程之后
我们来看看具体的操作
首先我在我们工作区的foo.txt文件内输入一行文字:aaa
##文件提交
1.工作区→缓存区
输入命令:git add <filename>
将foo.txt文件添加到仓库的缓存区

如果想要将工作区全部文件添加到缓存区就使用git add .

2.缓存区→主分支
输入命令:git commit -m 'xxx'
-m是message的意思,后面的字符串就代表本次提交的注释
就好比我们洗了一张照片,背面用笔写了这张照片的相关信息

##查看状态
完成这两步后,我们就算是已经提交foo.txt了
使用git status命令可以查看仓库状态
(commit提交前后,最好使用这个命令检查一下)

由于我对foo.txt文件的修改,文件夹中产生了备份文件foo.txt.bak
所以git提示我们它还没有上传它
没关系,我们不需要这个文件删掉就好了

这回Git提示我们工作区干净了,没什么要提交的了

##增删信息
现在我在foo.txt中再添加一行bbb

恩关了文件夹后我忘了改什么了,怎么办?
使用命令:git diff <filename>

可以清晰的看出我们所作出的修改
这回可以安心提交了,同样git addgit commit

##版本查看
继续向foo.txt文件中添加一行ccc,然后提交到本地仓库
到目前为止,我们的仓库中已经有了三个版本的foo.txt了
使用命令git log查看我们的版本信息

黄色的那几行就代表版本号
(GG我第一次提交注释first submit中间居然没加-,强迫症)
如果大家觉得乱七八糟的东西太多
可以输入:git log --pretty=oneline
只显示版本号和版本注释

##版本回溯
终于到了这一步
这正是Git的强大之处
如果我们想要回到上个版本
请输入:git reset --hard HEAD^
如果我们想要回到上上个版本
请输入:git reset --hard HEAD^^
假如我们想要回到10000个版本之前
可以敲一天“^”
git reset --hard HEAD^^^^^^^^^......
不过更简便的等价操作是
git reset --hard HEAD~10000

当然我们不可能这么丧心病狂的回溯
现在我们来试着回溯一步

好了Git提示我当前穿越成功了
使用cat <filename>查看文件验证一下

果不其然这就是我们foo.txt的第二个版本

##历史记录
再次查看版本信息
我们发现第三次版本的信息没有了

不用担心,既然我们能穿越回来也能穿越回去
不过稍微麻烦一点点
要想回到最新版本foo-3.0,我们需要知道它的版本号
但问题是版本信息查不到了
这时需要我们查看历史记录
命令:git reflog

看到黄字没,猜猜那是神马
没错就是版本号的前7位
有了它我们就可以穿越回去了

##版本前进
前进版本命令:git reset --hard <version>
只需要版本号的前6位就可以了

如此一来我们便可以回到最新版本

##撤销修改
现在我们当前的最新版本foo-3.0又添加了一行ddd
可是我又后悔了,我想要撤销
目前我们有两种办法

  1. 直接手动修改,或者Ctrl+Z
  2. 版本回溯

第一种简单粗暴,我们的例子实在太简单了,所以一个Ctrl+Z就解决了
但实际开发中可没这么轻松
第二种又比较麻烦,我比较懒不想这么做

那怎么办?
我们可以使用git checkout -- <filename>

这个命令的作用就是讲我们在工作区所作出的改变全部撤销(恢复到上一次commit)
不过如果在此之前我们已经将工作区保存到缓存区了,那么只能恢复到缓存的状态(恢复到上一次add)

怕大家不理解,我再演示一下第二种情况
在foo.txt中再次输入ddd
但是这次我先把它保存到缓存区

然后输入撤销指令

我们发现撤销失败了,因为它恢复到我们缓存区的状态,依然没有任何变化
所以即使是提交到缓存区,也要斟酌一番

##文件删除
在这个控制台中
我们还可以删除文件
命令:rm <filename>

再次查看文件发现确实不在了

如果我们没有提交到缓存区那么就可以使用撤销命令恢复文件

#分支机制
如果我们在开发过程中遇到了非常复杂的任务
写了一半后到深夜了,提交吧,代码不完整其他人没法开发;不提交,还可能丢失代码
不用担心,因为Git中有一个强大而重要的机制——分支branch
在自己的分支上工作,什么时候完成,什么时候合并分支
既不影响别人,同时也更加安全 ( ̄_, ̄ )

##分支原理

  1. 我们每经过一次commit提交就是一个时间点,Git将这些时间点串联成一条时间线
    最开始只有默认的master主分支,HEAD指针指向当前分支的当前版本

  2. 现在我们创建自己的分支dev(命令:git branch dev),Git会开辟一个指针,它会指向master指向的版本

  3. 有了dev分支我们还需要切换到dev分支(命令:git checkout dev),此时HEAD指针指向dev

  4. 这样我们在dev分支上开发,只有dev指针在动,master指针没有动

  5. 当我们在dev分支上完成任务后,就需要将它合并到主分支master
    合并前需要将分支切换回master(命令:git branch master)

  6. HEAD指针重新指向了master主分支,然后我们就可以合并了(命令:git merge dev)

  7. 这是正常的情况,如果在合并的时候发生了冲突,你修改了文件file,但是你的另一个朋友也修改了file中的相同语句,并且上传到了master主分支,这时就需要手动解决冲突调整代码后,再合并

  8. 合并完成dev分支就没有用了,删除即可(命令:git branch -d dev)

##分支策略

在开发中,我们使用分支管理应该遵循以下原则

  1. master主分支仅用来发布新版本,平时不要在master分支上开发,master分支应与远程仓库保持同步
  2. 平常开发都在dev分支上,正式版本发布前,把dev分支合并到master上,dev分支也应与远程保持同步(git push/git pull解决冲突)
  3. 团队每位成员都在本地的各自dev分支上干活,不时地往远程dev分支上push/pull(git push/pull解决冲突)

##分支使用
上面的分支原理已经把分支命令都介绍的差不多了
我再通过例子把流程扫一遍
现在我重新创建一个demo文件夹
内部有一个文档foo.txt,内容aaa
add、commit提交到本地仓库
现在主分支上就有我们的foo-1.0了

###创建与切换分支
其实分支的创建和切换是可以通过一个命令同时完成的
现在我们创建一个叫做dev的分支并切换到它上面
输入命令:git checkout -b dev

它相当于下面两个命令的并集
创建分支dev git branch dev
切换分支dev git checkout dev

###查看分支
创建并切换完毕后,我们可以来查看全部分支
输入命令:git branch

可以看到蓝字dev就表示我们当前在dev分支
我们输入的命令显示了全部分支,并且当前分支dev用绿字高亮了

###合并分支
现在我们在foo.txt添加一行bbb
然后add、commit提交到本地仓库
dev分支的任务就算完成了
合并前需要切换回主分支
输入命令:git checkout master

此时的foo.txt仍然是我们的foo-1.0版本
也就是说肯定没有我们添加的bbb


现在可以合并了
输入命令:git merge dev

现在主分支就是我们的foo-2.0版本了

###删除分支

查看一下分支,此时dev还是存在的

我们不需要它删掉就好了
输入命令:git branch -d dev

合并分支Git默认使用Fast forward模式,删除分支后,分支信息消失
合并时如果使用命令git merge --no-ff -m <comment> <branch>可以禁用Fast forward模式
这样删除分支,信息也不会丢失
###解决冲突
我们当前的foo-2.0内容是aaabbb
现在我重新创建一个dev分支,添加ccc,提交add、commit

再回到master主分支,添加ddd,提交add、commit

现在我再合并分支

Git提示我们产生了冲突
查看仓库状态

Git提供给了我们冲突的详细信息

此时我们再查看文件

它向我们标记了不同分支的内容
这样我们就可以手动修改代码解决冲突了
(统一master分支和dev分支的代码)
###隐藏现场
当我们在dev分支上开发的时候,突然发现主分支master上有bug
此时就遇到了问题,修复这个bug需要一定时间但是我们dev上的工作还没有完成
没有关系,我们可以隐藏当前工作现场
在此之前我们先查看一下仓库状态

Git提示我们还没有提交foo.txt

隐藏工作现场使用命令:git stash

这次再查看一下仓库状态

可以看到我们的工作现场确实被Git隐藏了

###隐藏列表
被我们隐藏的现场我们时可以查看的
使用命令:git stash list

###恢复现场
然后我们就可以安心的切换到master主分支修改bug
(比如新建临时issue分支,修改bug后回到master主分支,再删除issue分支)
bug修复后,回到我们的dev分支
恢复现场,我们又两个选择

  1. git stash pop 恢复现场并且销毁stash list中的记录
  2. git stash apply 恢复现场但不销毁记录,使用git stash drop删除栈顶记录

直接删除stash中的内容

手动删除stash中的内容

#Github远程仓库
Git的远程仓库也就是Github
没有账号的小伙伴需要注册Github账号
不过注册后还没完,要想让本地仓库和远程仓库建立连接
我们需要设置SSH加密,SSH是建立在应用层基础上的安全协议
在本地Git和远程Github之间建立信任关系
##创建SSH Key
打开你的用户主目录

看看有没有这两个文件

如果没有的话,打开命令行
输入命令:ssh-keygen -t rsa –C “email@xx.com”
后面输入你自己的邮箱
如果对网络有一些了解,id_rsa是私钥不能泄露给别人,id_rsa.pub公钥无所谓

有了这两个文件后
登录Github账号,进入右上的设置选项

在左侧的Personal settings
点击SSH and GPG keys

然后点击右侧的New SSH Key

输入标题后,将id_rsa.pub公钥内容原封不动的拷贝到Key栏里,最后Add SSH Key即可

如果看到了这个恭喜你成功了

##添加远程库
上面我们也说到了,开发项目我们的本地Git仓库最好和远程Github仓库保持同步
同样在Github中,在右上找新建仓库

输入仓库名、可选的描述等等就可以创建了

然后我们就可以将这个空仓库克隆到本地
本地开发完,又可以同步到Github

##本地库→远程库
首先,我们按照Github的提示
在本地的demo仓库中运行命令
git remote add origin <url>

(在Git Bash控制台中Shift + Ins粘贴)
(输入命令时必须是 git init 由Git管理的仓库)

将本地库的master分支同步到远程库的主分支
输入命令:git push -u origin master

命令中的-u其实是把本地库和远程库关联起来了
所以我们以后再同步的时候
只需输入命令:git push origin master 就可以了

现在我们再登录Github就可以发现远程库已经更新了

开发时,master主分支要经常与远程库同步,修复bug的临时分支不需要同步
在同步主分支前,最好先确认远程master与本地master是否一样
(可能其他同学已经上传了新版本)
将远程的master拉过来
使用命令:git pull origin master

##远程库→本地库
刚才我们从本地库同步到远程库
现在我们从远程库克隆到本地库

我把本地的demo仓库删掉

在Github中我们还可以找到这个地址

输入命令git clone <url>克隆远程库的代码到本地

当我们从远程库克隆代码到本地,Git就会自动将本地master和远程建立联系了
不过我们的克隆只能把远程的master分支拷贝到本地
如果想要将远程dev分支拷贝过来的话
使用命令:git fetch origin dev

即使我们本地没有dev分支,Git也会帮我们创建

##查看远程库信息
想要查看远程库的信息
输入命令:git remote
查看远程库详细信息
输入命令:git remote -v

远程库的默认名称就是origin

##访问网页
如果我们想要访问自己远程库的网页怎么做呢?
很简单,在Github中创建新分支“gh-pages”
(或者将我们的master推到远程仓库的gh-pages分支)

这样我们就可以访问自己的页面了
简直酷炫

格式就是:https://<用户名>.github.io/<仓库名>/<路径>.../<文件名>

#开发流程
介绍一下不同规模公司的开发流程

##小公司开发

###个人开发

  • 在本地master分支上创建新分支dev 开发完毕后合并到master分支
  • 把master分支直接推送到远程master分支上
  • 之后如果项目删除或者丢失可以重新克隆项目(此时只有master分支)
  • 把远程dev分支上的代码clone下来并在本地创建这个分支(命令:git fetch orgin dev:dev)


###多人开发

  • 流程大体与个人开发类似,稍有不同
  • 远程dev用来保存代码(同样适用个人开发),如果本地dev分支上未开发完毕,不能合并到本地的master分支上
    可以先把本地的dev分支保存在远程的dev分支上(命令:git push origin dev:dev )
  • 合并本地dev分支前,在master分支上来取下远程master分支的代码
    确保本地的master分支是最新的代码(命令:git pull origin master)

##大公司开发

  • 与小公司开发相似的流程,稍微复杂一点
  • 不要在本地master分支上开发,在其他分支如dev上开发后,合并到master
  • 上传到远程的非master分支如dev分支(命令:git push origin master:dev)
  • 之后项目参与者可以【new pull request】 进行代码比对和阅读
  • 项目管理人员在同意的情况下,会把远程dev分支上的东西合并到远程master分支上


#Git常用命令
最后最后时间不早了
总结一下Git的常用命令
命令中我使用了一些特殊含义词汇如下

描述含义
<num>数字
<url>地址
<filename>文件名称
<branchname>分支名称
<version-id>版本号
<comment>注释字符串
<local-branchname>本地分支名称
<remote-branchname>远程分支名称

|命令|含义| |---|---| |`mkdir `|创建空目录 |`cat `|查看文件内容 |`rm `|删除文件 |`pwd`|显示当前目录的路径 |`git init`|把当前的目录变成git管理仓库,生成隐藏文件.git |`git add `|工作区某文件添加到缓存区 |`git add .`|工作区文件全部添加到缓存区 |`git commit –m `|提交文件 |`git status`|查看仓库状态 |`git diff `|查看文件修改内容 |`git log`|查看历史记录 |`git reset --hard HEAD^`|版本回溯(回退次数为^个数) |`git reset --hard HEAD~`|版本回溯n次 |`git reset --hard `|版本前进 |`git reflog`|查看历史记录的版本号 |`git checkout -- `|撤销文件在工作区的修改 |`git remote add origin `|关联远程库 |`git push –u origin `|将某分支关联并推送到远程库(master) |`git push origin `|将本地某分支推送到远程库对应的分支上 |`git push origin -f`|将本地某分支强行覆盖到远程库对应的分支上 |`git push origin :`|将本地某分支推送到远程库的某分支上 |`git push origin HEAD:refs/for/`|提交评审 |`git pull origin `|将远程某分支推送到本地库对应的分支上 |`git pull origin :`|将远程某分支推送本地的某分支上 |`git clone `|从远程库克隆文件到本地(master分支) |`git fetch origin `|从远程库分支拷贝到本地相应分支(非master分支) |`git fetch origin :`|从远程库某分支拷贝到本地某分支(非master分支) |`git checkout `|切换到某分支 |`git checkout –b `|创建并切换到某分支上 |`git branch`|查看当前所有的分支 |`git branch `|创建某分支 |`git branch –d `|删除某分支 |`git merge `|在当前的分支上合并某分支 |`git stash`|隐藏当前工作待恢复现场后继续工作 |`git stash list`|查看所有被隐藏的文件列表 |`git stash pop`|恢复隐藏文件并删除记录 |`git stash apply`|恢复隐藏的文件但不删除记录 |`git stash drop`|删除隐藏文件记录 |`git remote`|查看远程库信息 |`git remote –v`|查看远程库详细信息
[==主页传送门==](http://blog.csdn.net/q1056843325)

以上是关于分布式版本控制系统Git与项目托管平台Github相关概念操作方法开发流程与常用命令的主要内容,如果未能解决你的问题,请参考以下文章

github 和 git的区别

分布式版本控制系统Git| 国内代码托管中心-Gitee自建代码托管平台-GitLab

初识GIT

github简介

GitHub

gitblit 与github有啥区别