每天造轮子 - Git详解

参考资料html

版本控制是什么

概念

版本控制最主要的功能就是追踪文件的变动。它将何时、什么人更改了文件的什么内容等信息忠实地了记录下来。每一次文件的改变,文件的版本号都将增长。除了记录版本变动外,版本控制的另外一个重要功能是并行开发。软件开发每每是多人协同做业,版本控制能够有效地解决版本的同步以及不一样开发者之间的开发通讯问题,提升协同开发的效率。并行开发中最多见的不一样版本软件的错误(Bug)修正问题也能够经过版本控制中分支与合并的方法有效地解决。vue

论必要性

  • 单人单功能开发 -- 至少你须要在开发在发现思路错误时快速退回到上一个正确的还原点
  • 单人多功能并行 + Bug fix -- 须要灵活的在多个功能点分支和Bug解决分支间切换
  • 多人多功能点 -- 须要多人间同步最新工做成果
  • 多人多功能点多版本多基线 -- 须要使用不一样分支和Tag标识开发版本和里程碑,而且经过配置管理员将新的Feather和Bug Fix配置到不一样的版本。

基础功能

  • 检入(Checkin)检出(Checkout)控制
  • 分支合并
  • 历史记录

常见工具

  • CVS -- Dick Grune在1984年~1985年基于RCS开发的一个客户一服务器架构的版本控制软件,长久以来一直是免费版本控制软件的主要选择。
  • SVN -- SVN是一个比较好的开源版本控制工具
  • Git -- 今天的主题

Git的历史

引用:廖雪峰的资料git

不少人都知道,Linus在1991年建立了开源的Linux,今后,Linux系统不断发展,已经成为最大的服务器系统软件了。 Linus虽然建立了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢? 事实是,在2002年之前,世界各地的志愿者把源代码文件经过diff的方式发给Linus,而后由Linus本人经过手工方式合并代码! 你也许会想,为何Linus不把Linux代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?由于Linus坚决地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,并且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。 不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续经过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,因而Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,受权Linux社区无偿使用这个版本控制系统。 安定团结的大好局面在2005年就被打破了,缘由是Linux社区牛人汇集,难免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图【破】【解】BitKeeper的协议(这么干的其实也不仅他一个),被BitMover公司发现了(监控工做作得不错!),因而BitMover公司怒了,要收回Linux社区的无偿使用权。 Linus能够向BitMover公司道个歉,保证之后严格管教弟兄们,嗯,这是不可能的。实际状况是这样的: Linus花了两周时间本身用C写了一个分布式版本控制系统,这就是Git!一个月以内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?你们能够体会一下。 Git迅速成为最流行的分布式版本控制系统,尤为是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。 历史就是这么偶然,若是不是当年BitMover公司威胁Linux社区,可能如今咱们就没有免费而超级好用的Git了。github

安装

Linux

sudo apt-get install git
复制代码

Mac

首先安装homebrew,而后经过homebrew安装Git,具体方法请参考homebrew的文档:brew.sh/。缓存

brew install 
复制代码

Windows

首先安装Liunx子系统,而后参考Linux安装指南bash

本地版本

建立本地仓库

建立仓库的过程其实就是将一个普通的文件夹升级为一个具有版本控制能力的文件夹服务器

# 建立文件夹
mkdir hello-git
# 改变工做目录到hello-git
cd hello-git
# 初始化Git至关将文件夹升级为仓库
git init
复制代码

实际上git命令会在文件夹下建立一个.git文件夹全部后面神奇的版本控制功能都是经过这个文件夹里面的这些神奇的文件实现的。 咱们能够经过事先仰望一下后面用到了会给你们一一解析markdown

tree -a
复制代码

将文件添加到版本库

首先咱们建立一个文件架构

# 建立一个文件
echo 'Step01 Create File' >> README.md
复制代码

而后咱们查看一下版本哭的状态ssh

git status
复制代码

咱们会发现Git会提示咱们这个文件属于未跟踪文件 若是在Vscode中

文件也会用绿色表示

其实Git的版本控制的要求也就是说即便处于版本库文件夹内的文件你也要明确的声明须要版本控制功能git才会跟踪他的版本变化。这样的白名单作法是为了防止多一些诸如编译结果文件,日志文件,开发工具本地配置等彻底没有必要进行版本控制的文件进行了跟踪占用不必的系统资源。

将文件添加到版本库

git add README.md
复制代码

添加完成后我么你发现这个时候文件状态变为要提交状态。 这是由于相对于旧的版本记录Git发现新添加了一个文件。咱们试用git status就能够看到这样的提示。

从暂存中恢复文件

一旦文件被提交到版本库实际上Git就会将README文件的快照已经缓存了一份到暂存盘,若是有须要你还能够将这个镜像取出来。不信的话咱们能够作一个小实验。

# 删除文件
rm -f README.md
# 从缓存区检出文件
git checkout README.md
# 查看文件
cat README.md

复制代码

另外若是你想一次添加多个和放弃跟踪能够参考下面的方法

添加多个文件跟踪

# 添加本目录下文件具有递归文件夹功能
git add .
复制代码

取消跟踪

# 取消添加
git rm --cached README.md
复制代码

忽略文件.gitignore

若是你但愿在使用 add .的时候忽略某一个文件能够在目录下建立一个 .gitignore文件

#.gitignore
# 忽略dist.js
dist.js
复制代码

这个时候就可让git文件放弃对此文件的关注。 固然若是你曾经将忽略的文件天交到git的跟踪列表中的话,即便你你在ignore文件中声明了git也不会主动放弃跟踪

提交代码commit

提交代码是指已经完成了某一阶段的代码开发好比你完成了某一个代码功能(features)或者修改了某一个代码缺陷(fix),你就能够建立一次代码提交。

git commit -m 'add README.js'

复制代码

提交的本质是讲原有工做区的代码提交到本地仓库中,咱们看一下提交先后的对比。

保存临时工做成果Stash

在你须要并行作好几件事的时候,好比你正在开发一个功能程序开发到一半,有一个紧急的bug须要处理又或者你忽然对另一个新特性来了思路,可是你现有的代码还在一个中间状态甚至编译都有问题。你须要可定须要一个功能保存如今的工做现场,而后去干另一件事。这个时候stash功能就能够帮助你解决。

# 创建一个临时的工做成果
echo 'TEMP xxxx' >> README.md

# 保存工做现场到栈
git stash

# 从栈中弹出工做现场
git stash pop


复制代码

放弃修改

git restore .
复制代码

回退到上一个提交

首先咱们修改一下文件,再作一次提交

echo 'STEP02 ADD FUN01' >> README.md
# 参数-a 是先添加到缓冲区再提交的意思
git commit -am 'README ADD STEP02'
复制代码

这个时候咱们会有两个提交记录 咱们能够用git log检查一下

git log
git log –-oneline # 简短日志
git reflog # 操做记录 包括回退记录也会被显示
复制代码

# 只是版本回退 不更新工做区
git reset HEAD^

# 不但版本回退 也会更新工做区(文件目录)的文件到上一个版本
git reset --hard HEAD^

复制代码

工做区(Working Directory)、缓存区(Stage)、版本库(Repository)小结

  • 工做区 --- 就是文件目录由于你的开发工做就是对文件的修改因此叫作工做区
  • 缓存区 --- 没有提交前也就是没有完成完成工做结果代码保存的地方
  • 版本库 --- 每个工做结果的时间带会被按照不一样的提交记录保存起来

分支管理

若是你每次只开发一个功能点或者修改一个Bug。不须要并行开发的可能你不须要分支。不过现实状况是颇有可能你正在开发一个长达几天的新特性时你又不的不去修改一些紧急的bug,又或是有个小伙伴急着让你帮助他解决他所遇到的问题。这就有点像你须要不断的从不一样进度点开始玩游戏。这个时候分支就能够帮咱们解决这个问题。 git的分支管理在全部的版本控制工具中出类拔萃分厂推荐你们使用分支功能。

建立分支开发

默认状况下咱们会处于master分支,在开始开发前咱们首先要作的就是切分一个新的分支。好比开发一个叫作FunA的功能点。

# 分支A
# 建立分支并切换分支到funA
git checkout -b 'funA'
# 完成功能
echo 'FunA XXXXXXX' >> README.md
# 提交功能
git commit -am 'funA add'
# 检出master分支
git checkout master
# 合并将开发分支合并到主分支
git merge funA
# 能够利用-d合并的同时删除分支
git merge -d funA

复制代码

分支的查看、删除

# 查看
git branch 
# 查看 - a 包括远程分支
git branch -a
# 删除
git branch -D <分支名称>

复制代码

冲突解决

假设两个分支都针对同一行代码进行修改,就会形成冲突,须要人工肯定那一个分支获得保留。 就比如两我的一个主张走A路线,另外一个主张走B路线。最后须要再合并的时候决定到底走哪一个路线。

首先咱们先制造这样一个冲突,假设咱们将开启连个分支 分别将README文件的第一行 作不一样而修改

  • step01 : Step01 Create File AAA
  • step01 : Step01 Create File BBB
# 建立分支并切换分支到funA
git checkout master
git checkout -b 'funA'
echo 'STEP01 AAA' > README.md
git commit -am 'step01 AAA'

# 建立分支并切换分支到
git checkout -b 'funB'
echo 'STEP01 BBB' > README.md
git commit -am 'step01 BBB'


# 能够利用-d合并的同时删除分支
git checkout master
git merge -d funA
git merge -d funB

复制代码

因为对同一行代码进行了修改这个时候Git就须要人工区合并代码 若是 想要撤销merge状态

git merge --abort
复制代码

若是在VSCode编辑器中会更加清晰一些

下面要作的就是人工保留你须要的部分, 而后进行一次merge提交。其实取舍AAA仍是BBB自己就是一次变动因此其实就是一次的代码commit。

git commit -am 'Merge branch funB'
复制代码

最后咱们能够经过log看一下此次合并过程

git log --graph --pretty=oneline --abbrev-commit
复制代码

清洗提交历史 -- squash方式合并

若是你的分支开发历经各类磨难,里面有不少细节的功能进展你不但愿其余人了解,又或者你在开发的过程当中肚子饿了,但愿经过一次的commit来保留中间成果。可是最终提交的时候不但愿你的这些中间细节被被人了解,能够采用这样的办法

# 建立分支并切换分支到funA
git checkout master
git checkout -b 'funA'
echo 'STEP02 BBB' >> README.md
git commit -am 'FunA commit 01'
echo 'STEP03 BBB' >> README.md
git commit -am 'FunA commit 02'

# 切换master分支
# 使用squash方式提交 只合并不commit
git merge --squash funA
复制代码

这个时候咱们能够用git status查看一下发现合并代码后并无提交。只是将全部的提交都整合到了一块儿放在暂存区。

# 建立分支并切换分支到funA
git commit -am 'funA update'
复制代码

这个时候咱们可使用commit方式进行提交留下光辉的而干净的一笔。

Rebase变基操做

去除版本合并痕迹 (待续)

其余命令总结

# 删除分支
git branch -D <branch_name>
复制代码

标签管理

标签管理就是给本身的代码打上版本标记。其实就是给本身的版本设置里程碑。

# 将最新提交打标签
git tag v1.0

# 将指定commit打标签
git tag v0.9 4ab025

# 查看打标签
git tag 

# 查看与某标签之间的差距
git show v0.9
复制代码

远程仓库GitHub

如何获取远程仓库

  • GitHub 世界上最大的开源社区
  • Gitee 国内的速度快
  • 本身搭建Gitlab

(后续会教你们如何一行配置搞定gitlab搭建)

git创建远程仓库

另外与远程资源库通信一般采用ssh协议,因此须要将你的ssh公钥添加到github帐户中

获取公钥的方法能够参考 公钥获取方法

添加远程分支

# 添加远程分支
git remote add origin git@github.com:su37josephxia/hello-git.git

复制代码

查看

git remote -v
复制代码

推送 push

git push
复制代码

拉去 fetch

git fetch
# 若是有多个远程源时
git fetch <拉去源>
复制代码

拉去 pull

至关与先fetch + merge

git pull
复制代码

GitHub之Watch

表示关注、这个项目的全部动态包括PR ISSUE你的信息中心和邮箱都会收到。

GitHub之Star

表示点赞、表示对这个项目支持。 github.com/su37josephx… Star一下我这个项目。

欢迎你们来造轮子

GitHub之Fork

至关于复制了目前项目的文件,后续变化必须手动更新。 手动更新方法以下:

# 本地新加一个新的远程库upstream
git remote add upstream https://github.com/vuejs/vue-next

复制代码
# 从远程仓库拉去代码
git fetch upstream
# 切换分支
git chekout master
# 合并远程分支
git merge upstream/master
复制代码
相关文章
相关标签/搜索