git总结

Git 诞生

linux之父Linus为了更好的管理他自己的开源项目linux系统而自己开发了一个软件,这个软件可以帮助Linux更好的进行开源开发,名字就叫Git。

它是个分布式版本控制系统,Git是最当前流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。

安装Git

ubuntu下:

sudo apt-get install gi

可以直接通过源码安装,先从Git官网下载源码,然后解压,之后:

./config
make
sudo make install

创建版本库

什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”

创建本地仓库的两种方法:

  • 从服务器上克隆仓库:git clone [email protected]:slaming/Markdown.git
  • 在工作区初始化仓库: git init

创建完版本库,当前路径里就会发现一个.git的文件夹,这个就是Git的版本库。Git版本库里面有一个称为stage(或者叫index)的暂存区,和还有Git为我们自动创建的第一个分支master,以及指向master的第一个指针HEAD,示意图如下:

git总结_第1张图片

将工作区的更改加入本地仓库

我们把文件往Git版本库里添加的时候,是分两步执行的:

(1) 用 git add 命令把变化加入到暂存区

  • git add .
  • git add 文件名

git总结_第2张图片

(2)用 git commit 将缓存区的所有内容提交到当前分支,由于我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

  • git commit -m "提交描述"

git总结_第3张图片

一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的,利用git status查看:

$ git status
On branch master
nothing to commit, working tree clean

关联远程仓库

(1)与github远程仓库关联

$ git remote add origin [email protected]:slaming/learngit.git

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

(2)本地仓库向远程仓库提交

$ git push -u origin master

如果远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

本地创建新的分支

(1)常用命令

创建新的分支:

$ git branch dev

切换到dev分支:

$ git checkout dev

为了简单,常用下面命令,创建新的分支dev,并且切换到dev分支:

$ git checkout -b dev

查看版本库有什么分支,git branch命令会列出所有分支,当前分支前面会标一个*号:

$ git branch
* dev
master

合并分支:

$ git merge dev

(2)创建与合并分支

每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点,每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:

git总结_第4张图片

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

git总结_第5张图片

从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

git总结_第6张图片

假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是切换到master分支,直接把master指向dev的当前提交,这样就完成了合并:

git总结_第7张图片

(3) 分支合并的冲突

假如开辟了新的分支features1

$ git checkout -b feature1

修改readme.txt最后一行,改为:

Creating a new branch is quick AND simple.

提交:

$ git add readme.txt

$ git commit -m "AND simple"

切换到master分支:

$ git checkout master

在master分支上把readme.txt文件的最后一行改为:

Creating a new branch is quick & simple.

提交:

$ git add readme.txt

$ git commit -m "& simple"

git总结_第8张图片

合并:

$ git merge feature1

这时Git不能自动合并,会出现冲突。

git merge 的原理

三路合并

三路合并就是先找出一个基准,然后以基准为Base 进行合并,如果2个文件相对基准(base)都发生了改变 那git 就报冲突,然后让你人工决断。否则,git将取相对于基准(base)变化的那个为最终结果。

git总结_第9张图片

Base 代表上一个版本,即公共祖先
Mine 代表你本地修改
Theirs 代表其他人修改
这样当git进行合并的时候,git就知道是其他人修改了,本地没有更改,git就会自动把最终结果变成如下,这个结构也是大多merge 工具的常见布局。

git总结_第10张图片

如果换成下面的这样,就需要人工解决了:

git总结_第11张图片

上面就是git merge 最基本的原理 “三路合并”。

下面的合并就是我们常见的分支graph,结合具体分析

git总结_第12张图片

上面①~⑨代表一个个修改集合(commit)每个commit都有一个唯一7位SHA-1唯一表示。
①,②,④,⑦修改集串联起来就是一个链,此时用master指向这个集合就代表master分支,分支本质是一个快照,其实类比C中指针
同样dev分支也是由一个个commit组成
现在在dev分支上由于各种原因要运行git merge master需要把master分支的更新合并到dev分支上,本质上就是合并修改集 ⑦(Mine) 和 ⑧(Theirs) ,此时我们要 利用DAG(有向无环图)相关算法找到我们公共的祖先 ②(Base)然后进行三方合并,最后合并生成 ⑨。

多人协作

你从远程仓库克隆到本地,就可以开始你的开发了。

要查看远程库的信息,用git remote:

$ git remote
origin

或者,用git remote -v显示更详细的信息:

$ git remote -v
origin  [email protected]:slaming/learngit.git (fetch)
origin  [email protected]:slaming/learngit.git (push)
 

上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

把分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

$ git push origin dev

但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?

  • master分支是主分支,因此要时刻与远程同步;

  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

在实际开发中,我们应该按照几个基本原则进行分支管理:

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

所以,团队合作的分支看起来就像这样:

git总结_第13张图片

抓取分支

多人协作时,大家都会往master和dev分支上推送各自的修改。

当你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的地方作了修改,并试图推送:

$ git push origin dev

推送会失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,和merge类似。这时需要手动改写。

你可能感兴趣的:(git总结)