版本控制(3) Git和github
Git
Git介绍
Git是一个开源的分布式版本控制系统,分布式相比集中式的最大区别是Git没有“中央服务器”,每位开发者都可以通过克隆远程库,在本地机器上存储一个完整的Git仓库,还可以把代码的修改提交到本地库
目的:借助github托管项目代码。
基本概念:
-
仓库(
repository):仓库用来存放项目代码,每个项目对应一个仓库,多个开源项目则有多个仓库。 -
收藏(
star):仓库主页star按钮,意思为收藏项目的人数,在github上如果你有一个项目获得100个star都算很不容易了。 -
复制克隆项目(
Fork):该fork的项目是独立存在的
Git结构

Git中独有的术语,理解这些术语非常重要:
-
远程仓库(Remote):也叫作资源库,是远程机器上的代码库。
-
本地库(Repository):是用户在本地创建的目录,拥有远程库的一个快照,由工作区和版本库构成。
-
工作区(Workspace):本地库的根目录中除.git目录以外的内容,存储内容的实际文件;
-
版本库(.git目录):是本地库的根目录中的一个隐藏目录.git,用于记录版本信息,Git进行版本控制所需要的文件,则都放在.git文件夹中;
-
暂存区(Index):也叫做缓存区,暂存信息存放在.git目录"下的index文件(.git/index)中,用于临时保存内容的修改;
-
HEAD文件:是.git目录下的HEAD文件(.git/HEAD),指向最后依次提交的结果。
-
分支(Branch):本地库中默认创建一个主(master)分支,分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。
Git安装
1、进入/local,新建目录git
cd /usr/local/
mkdir git
2、进入git目录,下载git的源码包,最新
cd /usr/local/git; wget https://github.com/git/git/archive/v2.17.0.tar.gz
3、安装编译源码所需依赖,出现提示输入y即可
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
4、解压
tar zxvf v2.17.0.tar.gz
5、进入目录,执行编译
make prefix=/usr/local/git all
6、make install
make prefix=/usr/local/git install
7、配置环境变量
vi /etc/profile
PATH=$PATH:/usr/local/git/bin
export PATH
8、编辑环境变量,让配置即时生效
source /etc/profile
9、测试
git --version

Git命令行操作
3.4.1 初始化
git init命令可以把当前目录变成git可以管理的仓库。
mkdir /home/gitrepo
cd gitrepo
git init
初始化完成后,就多一个隐藏了.git文件,ls -la能看到具体细节
ll .git

3.4.2 设置签名
类似于设置了用户信息,需要设置用户名和邮箱
注意:这里设置的签名和远程库的账号、密码没有任何关系
设置本地仓库用户名和邮箱(必须cd到仓库的目录里)
cd /home/gitrepo
git config user.name caichang
git config user.email caichangfast@qq.com
信息放在.git/config配置文件中
cat config

设置全局用户名和邮箱
git config --global user.name caichang_global
git config --global user.email caichangfast@sohu.com
存放路径放在/root/.gitconfig,因为是用root用户登录
cat /root/.gitconfig

3.4.3 查看状态
注意路径要在新建的版本库位置上,不能在具体的隐藏文件下
cd /home/gitrepo
git status

3.4.4 添加并提交(是2个动作)
1、在仓库下任意新建文件,然后添加,提交。
cd /home/gitrepo
vi helloGit.txt
git add helloGit.txt
git commit helloGit.txt
注意:1、要撤销add,可以采用
git rm --cached helloGit.txt
2、提交后,需要输入一些内容,然后保存退出,跟svn一样,这些内容是作为提交的一个注释或者备注的。
this is my first commit.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
# new file: httpd.conf
#
3、修改文件后想再次提交,直接commit就可以

4、提交时采用带 -m "具体message"就可以,这样就不用进vi编辑器了
git commit -m "second commit" httpd.conf
github
注册github账号
我的GitHub账号:
- 用户名:jimmy688
- 邮箱:15219743651@163.com
新建github远程库
新建一个远程库,右上角,new repository,填入对应信息即可。新创建的库有提示,这个提示很重要,可以用命令去实现提交等,但实际往往用一些工具去处理。


最好不好勾选Initialize this repository with a README,原因是:https://blog.csdn.net/ever69/article/details/97565768。
当点击创建仓库时,它会帮我们做一次初始提交。于是我们的仓库就有了README.md和.gitignore文件,然后我们把本地项目关联到这个仓库,并把项目推送到仓库时,回报文章开题的那个错误,这是因为,我们在关联本地与远程时,两端都是有内容的,但是这两份内容并没有联系,当我们推送到远程或者从远程拉取内容时,都会有没有被跟踪的内容,于是你看git报的详细错误中总是会让你先拉取再推送,但是拉取总是失败。
想要避免这种问题,就要保持创建的仓库是一个空仓库,什么都没有。

…or create a new repository on the command line
echo "# nba" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/jimmy688/nba.git
git push -u origin master
…or push an existing repository from the command line
git remote add origin https://github.com/jimmy688/nba.git
git push -u origin master


会得到自己的远程库地址:https://github.com/jimmy688/nba.git (使用https协议连接)
ssh协议连接的远程库地址:git@github.com:jimmy688/nba.git
(https协议连接和ssh协议连接的地址是不同的,用ssh协议会更快一点)
老师给的地址是:https://github.com/caichang5201314/mtesting.git
给远程库取别名
不然特别麻烦,每次都要输入一长串远程地址,mtesting为远程库的别名
git remote add origin https://github.com/jimmy688/nba.git
或者
git remote add origin_ssh git@github.com:jimmy688/nba.git
远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。
如果要删除远程库的设置,操作如下:
git remote rm origin
4、查看,fetch表示取回地址,push表示推送
[root@localhost gitrepo]# git remote -v

把本地库推送给远程库
需要输入你远程库的用户名和密码
https协议:
[root@localhost gitrepo]# git push -u origin master
ssh协议:
[root@localhost gitrepo]# git push -u origin_ssh master

5、刷新远程库,就可以看到已推送过去了

克隆远程库
1、进入任何你想要clone的目录,如:/tmp/test
2、输入命名clone下来
cd /tmp/test
用https协议来克隆:
[root@Jimmy test]# git clone https://github.com/jimmy688/nba.git
用ssh协议来克隆:
[root@Jimmy test]# git clone git@github.com:jimmy688/nba.git

时光穿梭
首先来查看一下git的状态:
cd /home/gitrepo
git status

Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的。
下面,修改一个文件的内容来试验一下:

git status告诉我们,将要被提交的修改包括 hello3.txt
git diff顾名思义就是查看difference,显示的格式正是Unix通用的diff格式,可以从上面的命令输出看到,我们在第三行添加了一个change2单词。
知道了对hello3.txt作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add:
git add hello3.txt
同样没有任何输出。在执行第二步git commit之前,我们再运行git status看看当前仓库的状态:

提交之后,status又回归到了clean的状态。
版本回退
下面继续以hello3.txt文件为例,讲解版本回退:
查看git的log日志:
git log

git log命令显示从最近到最远的提交日志。看到的一大串类似ef042f...的是commit id(版本号),和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id和我的肯定不一样,以你自己的为准。为什么commit id需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:
注意:这个版本不是针对某个文件的,而是针对整个仓库来讲的。
现在,我们尝试回退到上一个版本:
首先必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交ef042f...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
现在,我们要把当前版本add change2(版本名称是我们之前提交时候的备注 -m) 回退到上一个版本c2,就可以使用git reset命令:
git reset --hard HEAD^
cat hello3.txt

可以看到,hello3.txt的内容已经回到上一次的状态了,即回退成功了。
不过且慢,我们用git log再看看现在版本库的状态:
git log

最新的那个版本add change2已经看不到了!好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?
办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个add change2的commit id是ef042f3636c6fe146935f4eac66f7363a8411e81,于是就可以指定回到未来的某个版本:
git reset --hard ef042f

版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
可以看到,hello3.txt内容又变回到add change2版本的状态了。
工作区与暂存区
工作区(Working Directory)
就是linux的一个目录,比如下面的gitrepo就是一个工作区:

版本库(Repository)
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
分支和HEAD的概念我们以后再讲。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
- 第一步是用
git add把文件添加进去,实际上就是把文件修改添加到暂存区; - 第二步是用
git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
例如,先对helloGit.txt做个修改,加上一行内容.
然后,在工作区新增一个readme.txt文本文件(内容随便写)。
最后用git status查看一下状态:

Git非常清楚地告诉我们,helloGit.txt被修改了,而readme.txt还从来没有被添加过,所以它的状态是Untracked。
现在,使用两次命令git add,把helloGit.txt和readme.txt都添加后,用git status再查看一下:

现在,暂存区的状态就变成这样了:
所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。

一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
现在版本库变成了这样,暂存区就没有任何内容了:
管理修改
掌握了暂存区的概念。下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。
你会问,什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。
为什么说Git管理的是修改,而不是文件呢? 我们还是做实验。
- 第一步,对
readme.txt做一个修改,比如加一行内容: - 第二步,add添加到暂存区。
- 第三步,再修改
readme.txt - 最后,提交,查看状态

咦,怎么第二次的修改没有被提交?
别激动,我们回顾一下操作过程:
第一次修改 -> git add -> 第二次修改 -> git commit
你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
提交后,用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别:
git deff HEAD -- readme.txt
或者
git diff readme.txt

可见,第二次修改确实没有被提交。
那怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
撤销修改
注意,这里的撤销修改跟版本回退是有区别的。
如果你在readme.txt末尾中添加了一行 My stupid boss still prefers SVN.:

在你准备提交前,你猛然发现了stupid boss可能会让你丢掉这个月的奖金!
既然错误发现得很及时,就可以很容易地纠正它。你可以删掉最后一行,手动把文件恢复到上一个版本的状态。如果用git status查看一下:

你可以发现,Git会告诉你,git checkout -- file可以丢弃工作区的修改:
git checkout -- readme.txt
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
- 一种是
readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态; - 一种是
readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,checkout就是让这个文件回到最近一次git commit或git add时的状态。
现在,看看readme.txt的文件内容:

文件内容果然复原了。
git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。
再举一个撤销例子:
现在假定是凌晨3点,你不但写了一些胡话,还git add到暂存区了:
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss still prefers SVN.
$ git add readme.txt
庆幸的是,在commit之前,你发现了这个问题。用git status查看一下,修改只是添加到了暂存区,还没有提交:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
Git同样告诉我们,用命令git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
再用git status查看一下,现在暂存区是干净的,工作区有修改:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
还记得如何丢弃工作区的修改吗?
$ git checkout -- readme.txt
$ git status
On branch master
nothing to commit, working tree clean
整个世界终于清静了!
假设你不但改错了东西,还从暂存区提交到了版本库,怎么办呢?还记得版本回退一节吗?可以回退到上一个版本。不过,这是有条件的,就是你还没有把自己的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后面会讲到远程版本库,一旦你把stupid boss提交推送到远程版本库,你就真的惨了……
删除文件
在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交:
$ git add test.txt
$ git commit -m "add test.txt"
[master b84166e] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:
$ rm test.txt
这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
现在,文件就从版本库中被删除了。
小提示:先手动删除文件,然后使用git rm <file>和git add<file>效果是一样的。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
git checkout -- file

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!
分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
其他版本控制系统如SVN等都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支比蜗牛还慢,简直让人无法忍受,结果分支功能成了摆设,大家都不去用。
但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。
创建和合并分支
在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
真是太神奇了,你看得出来有些提交是通过分支完成的吗?
下面开始实战。
首先,我们创建dev分支,然后切换到dev分支:
git checkout -b dev

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
git branch dev 创建
git checkout dev 切换
然后,用git branch命令查看当前分支:
git branch

git branch命令会列出所有分支,当前分支前面会标一个*号。
然后,我们就可以在dev分支上正常提交,比如对readme.txt做个修改,末尾加上一行new content:

然后提交:


现在,dev分支的工作完成,我们就可以切换回master分支:

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!

因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
现在,我们把dev分支的工作成果合并到master分支上:
git merge dev
cat readme.txt

git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。
注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。
合并完成后,就可以放心地删除dev分支了:
git branch -d dev
删除后,查看branch,就只剩下master分支了:
git branch

因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。
switch
我们注意到切换分支使用git checkout <branch>,而前面讲过的撤销修改则是git checkout -- <file>,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:
创建并切换到新的dev分支,可以使用:
git switch -c dev 不是最新版本的git有可能没有这个命令
直接切换到已有的master分支,可以使用:
git switch master
使用新的git switch命令,比git checkout要更容易理解。
小结:
- 查看分支:
git branch - 创建分支:
git branch <name> - 切换分支:
git checkout <name>或者git switch <name> - 创建+切换分支:
git checkout -b <name>或者git switch -c <name> - 合并某分支到当前分支:
git merge <name> - 删除分支:
git branch -d <name>
解决合并冲突
创建分支feature1并切换到该分支:
git branch feature1
git checkout feature1
修改readme.txt最后一行,改为 quick And simple:

在feature1分支上提交:
git add readme.txt
git commit -m 'q And s' readme.txt
切换到master分支:
git checkout master

Git还会自动提示我们当前master分支比远程的master分支要超前1个提交。
在master分支上把readme.txt文件的最后一行改为 quick & simple,然后提交:
vi readme.txt
git add readme.txt
git commit -m 'q & s' readme.txt
现在,master分支和feature1分支各自都分别有新的提交,变成了这样:
这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:
git merge feature1

果然冲突了!Git告诉我们,readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:

我们可以直接查看readme.txt的内容:

Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存:

再提交:

注意:提交的时候不需要指定readme.txt文件,否则会报错:during a merge。
现在,master分支和feature1分支变成了下图所示:
用带参数的git log也可以看到分支的合并情况:
git log --graph --pretty=oneline --abbrev-commit

最后,删除feature1分支:
git branch -d feature1
工作完成。
分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
下面我们实战一下--no-ff方式的git merge:
首先,仍然创建并切换dev分支:
$ git switch -c dev
Switched to a new branch 'dev'
修改readme.txt文件,并提交一个新的commit:
$ git add readme.txt
$ git commit -m "add merge"
[dev f52c633] add merge
1 file changed, 1 insertion(+)
现在,我们切换回master:
$ git switch master
Switched to branch 'master'
准备合并dev分支,请注意--no-ff参数,表示禁用Fast forward:
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
合并后,我们用git log看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* e1e9c68 (HEAD -> master) merge with no-ff
|\
| * f52c633 (dev) add merge
|/
* cf810e4 conflict fixed
...
可以看到,不使用Fast forward模式,merge后就像这样:
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
小结
Git分支十分强大,在团队开发中应该充分应用。
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
Feature分支
软件开发中,总有无穷无尽的新的功能要不断添加进来。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
现在,你终于接到了一个新任务:开发代号为Vulcan的新功能,该功能计划用于下一代星际飞船。
于是准备开发:
$ git switch -c feature-vulcan
Switched to a new branch 'feature-vulcan'
5分钟后,开发完毕:
$ git add vulcan.py
$ git status
On branch feature-vulcan
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: vulcan.py
$ git commit -m "add feature vulcan"
[feature-vulcan 287773e] add feature vulcan
1 file changed, 2 insertions(+)
create mode 100644 vulcan.py
切回dev,准备合并:
$ git switch dev
一切顺利的话,feature分支和bug分支是类似的,合并,然后删除。
但是!
就在此时,接到上级命令,因经费不足,新功能必须取消!
虽然白干了,但是这个包含机密资料的分支还是必须就地销毁:
$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.
销毁失败。Git友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D参数。。
现在我们强行删除:
$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 287773e).
终于删除成功!

浙公网安备 33010602011771号